[COMMITTED 09/42] gccrs: Add llvmInlineAsm node

Arthur Cohen arthur.cohen@embecosm.com
Mon Apr 28 16:24:26 GMT 2025


Hi,

On 4/28/25 6:09 PM, Andrew Pinski wrote:
> On Mon, Apr 28, 2025 at 9:05 AM Andrew Pinski <pinskia@gmail.com> wrote:
>>
>> On Mon, Apr 28, 2025 at 8:48 AM <arthur.cohen@embecosm.com> wrote:
>>>
>>> From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
>>>
>>> InlineAsm node does not support memory clobbers.
>>
>> A few review on this.
>> I think this should just be called extended rather than referencing LLVM here.
>>
>>>
>>> gcc/rust/ChangeLog:
>>>
>>>          * ast/rust-ast-collector.cc (TokenCollector::visit): Make visitor
>>>          unreachable.
>>>          * ast/rust-ast-collector.h: Add visit for LlvmInlineAsmNode.
>>>          * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add visit
>>>          function for the default ast visitor.
>>>          * ast/rust-ast-visitor.h: Add function prototype.
>>>          * ast/rust-ast.cc (LlvmInlineAsm::accept_vis): Add accept_vis to
>>>          LlvmInlineAsm node.
>>>          * ast/rust-ast.h: Add LlvmInlineAsm node kind.
>>>          * ast/rust-expr.h (class LlvmInlineAsm): Add LlvmInlineAsm node.
>>>          * expand/rust-derive.h: Add visit function for LlvmInlineAsm node.
>>>          * expand/rust-macro-builtins-asm.cc (MacroBuiltin::llvm_asm_handler):
>>>          Add handler for llvm inline assembly nodes.
>>>          (parse_llvm_asm): Add function to parse llvm assembly nodes.
>>>          * expand/rust-macro-builtins-asm.h (parse_llvm_asm): Add function
>>>          prototypes.
>>>          * expand/rust-macro-builtins.cc (inline_llvm_asm_maker): Add macro
>>>          transcriber.
>>>          * expand/rust-macro-builtins.h: Add transcriber function prototype.
>>>          * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add visit
>>>          function for LlvmInlineAsm node.
>>>          * hir/rust-ast-lower-base.h: Add visit function prototype.
>>>          * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visit
>>>          function for LlvmInlineAsm node.
>>>          * resolve/rust-ast-resolve-base.h: Add visit function prototype.
>>>
>>> Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
>>> ---
>>>   gcc/rust/ast/rust-ast-collector.cc         | 10 ++++-
>>>   gcc/rust/ast/rust-ast-collector.h          |  1 +
>>>   gcc/rust/ast/rust-ast-visitor.cc           |  4 ++
>>>   gcc/rust/ast/rust-ast-visitor.h            |  2 +
>>>   gcc/rust/ast/rust-ast.cc                   |  6 +++
>>>   gcc/rust/ast/rust-ast.h                    |  1 +
>>>   gcc/rust/ast/rust-expr.h                   | 48 ++++++++++++++++++++++
>>>   gcc/rust/expand/rust-derive.h              |  1 +
>>>   gcc/rust/expand/rust-macro-builtins-asm.cc | 21 ++++++++++
>>>   gcc/rust/expand/rust-macro-builtins-asm.h  |  7 ++++
>>>   gcc/rust/expand/rust-macro-builtins.cc     | 11 ++++-
>>>   gcc/rust/expand/rust-macro-builtins.h      |  4 ++
>>>   gcc/rust/hir/rust-ast-lower-base.cc        |  4 ++
>>>   gcc/rust/hir/rust-ast-lower-base.h         |  1 +
>>>   gcc/rust/resolve/rust-ast-resolve-base.cc  |  4 ++
>>>   gcc/rust/resolve/rust-ast-resolve-base.h   |  1 +
>>>   16 files changed, 124 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
>>> index 8ee63752f32..90ff2e36251 100644
>>> --- a/gcc/rust/ast/rust-ast-collector.cc
>>> +++ b/gcc/rust/ast/rust-ast-collector.cc
>>> @@ -1520,7 +1520,15 @@ TokenCollector::visit (AsyncBlockExpr &expr)
>>>
>>>   void
>>>   TokenCollector::visit (InlineAsm &expr)
>>> -{}
>>> +{
>>> +  rust_unreachable ();
>>> +}
>>> +
>>> +void
>>> +TokenCollector::visit (LlvmInlineAsm &expr)
>>> +{
>>> +  rust_unreachable ();
>>> +}
>>>
>>>   // rust-item.h
>>>
>>> diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
>>> index b014c23ed0b..f45e3cc51ae 100644
>>> --- a/gcc/rust/ast/rust-ast-collector.h
>>> +++ b/gcc/rust/ast/rust-ast-collector.h
>>> @@ -303,6 +303,7 @@ public:
>>>     void visit (AwaitExpr &expr);
>>>     void visit (AsyncBlockExpr &expr);
>>>     void visit (InlineAsm &expr);
>>> +  void visit (LlvmInlineAsm &expr);
>>>     // rust-item.h
>>>     void visit (TypeParam &param);
>>>     void visit (LifetimeWhereClauseItem &item);
>>> diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
>>> index 9d524c3cc4c..beb3360c4e1 100644
>>> --- a/gcc/rust/ast/rust-ast-visitor.cc
>>> +++ b/gcc/rust/ast/rust-ast-visitor.cc
>>> @@ -713,6 +713,10 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
>>>       }
>>>   }
>>>
>>> +void
>>> +DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr)
>>> +{}
>>> +
>>>   void
>>>   DefaultASTVisitor::visit (AST::TypeParam &param)
>>>   {
>>> diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
>>> index 51661df76b4..6d243e7b063 100644
>>> --- a/gcc/rust/ast/rust-ast-visitor.h
>>> +++ b/gcc/rust/ast/rust-ast-visitor.h
>>> @@ -131,6 +131,7 @@ public:
>>>     virtual void visit (AwaitExpr &expr) = 0;
>>>     virtual void visit (AsyncBlockExpr &expr) = 0;
>>>     virtual void visit (InlineAsm &expr) = 0;
>>> +  virtual void visit (LlvmInlineAsm &expr) = 0;
>>>
>>>     // rust-item.h
>>>     virtual void visit (TypeParam &param) = 0;
>>> @@ -314,6 +315,7 @@ public:
>>>     virtual void visit (AST::AwaitExpr &expr) override;
>>>     virtual void visit (AST::AsyncBlockExpr &expr) override;
>>>     virtual void visit (InlineAsm &expr) override;
>>> +  virtual void visit (LlvmInlineAsm &expr) override;
>>>
>>>     virtual void visit (AST::TypeParam &param) override;
>>>     virtual void visit (AST::LifetimeWhereClauseItem &item) override;
>>> diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
>>> index 06e0e7b0fbc..4e82be420fe 100644
>>> --- a/gcc/rust/ast/rust-ast.cc
>>> +++ b/gcc/rust/ast/rust-ast.cc
>>> @@ -4650,6 +4650,12 @@ InlineAsm::accept_vis (ASTVisitor &vis)
>>>     vis.visit (*this);
>>>   }
>>>
>>> +void
>>> +LlvmInlineAsm::accept_vis (ASTVisitor &vis)
>>> +{
>>> +  vis.visit (*this);
>>> +}
>>> +
>>>   void
>>>   TypeParam::accept_vis (ASTVisitor &vis)
>>>   {
>>> diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
>>> index 91611ec6a62..55f178d782c 100644
>>> --- a/gcc/rust/ast/rust-ast.h
>>> +++ b/gcc/rust/ast/rust-ast.h
>>> @@ -1264,6 +1264,7 @@ public:
>>>       Await,
>>>       AsyncBlock,
>>>       InlineAsm,
>>> +    LlvmInlineAsm,
>>>       Identifier,
>>>       FormatArgs,
>>>       MacroInvocation,
>>> diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
>>> index 69538df63e5..0dfb4e5fd60 100644
>>> --- a/gcc/rust/ast/rust-expr.h
>>> +++ b/gcc/rust/ast/rust-expr.h
>>> @@ -5330,6 +5330,54 @@ public:
>>>     Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
>>>   };
>>>
>>> +class LlvmInlineAsm : public ExprWithoutBlock
>>> +{
>>> +  // llvm_asm!("" :         : "r"(&mut dummy) : "memory" : "volatile");
>>> +  //           Asm, Outputs, Inputs,            Clobbers, Options,
>>> +
>>> +private:
>>> +  location_t locus;
>>> +  std::vector<Attribute> outer_attrs;
>>> +
>>> +  std::vector<TupleClobber> clobber_abi;
>>> +  bool is_volatile;
>>> +  bool align_stack;
>>> +  enum class Dialect
>>> +  {
>>> +    Att,
>>> +    Intel,
>>> +  } dialect;
>>
>> Asm Dialect is target specific so this should just be an integer which
>> gets translated via target hooks instead of a full on enum.
>>
>> Note GCC's extended asm dialects support up a full 32bit #:
>> #ifdef ASSEMBLER_DIALECT
>>
>> /* Number of the assembler dialect to use, starting at 0.  */
>> static int dialect_number;
>> #endif
>> X86 is not the only target which supports an asm dialect: sh, pa,
>> pdp11 and bpf are other targets which support one.
> 
> I forgot to mention, GCC does not currently have a way to change the
> dialect dynamically. it is controlled by the backend only. Do you have
> patches to final.cc and the backends to support dynamically changing
> the dialect while processing inline-asm?

No, we do not have patches to the backend to handle this and will not be 
producing any. As far as I understand it this is a rather complex 
problem :) As mentioned in my last email, this is just a dummy node for 
one specific Rust function, so we will not go that far to properly 
support it.

Thanks for the reviews,

Arthur

> 
> Thanks,
> Andrew Pinski
> 
>>
>> Thanks,
>> Andew Pinski
>>
>>> +
>>> +public:
>>> +  LlvmInlineAsm (location_t locus) : locus (locus) {}
>>> +
>>> +  Dialect get_dialect () { return dialect; }
>>> +
>>> +  location_t get_locus () const override { return locus; }
>>> +
>>> +  void mark_for_strip () override {}
>>> +
>>> +  bool is_marked_for_strip () const override { return false; }
>>> +
>>> +  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
>>> +
>>> +  void accept_vis (ASTVisitor &vis) override;
>>> +
>>> +  std::string as_string () const override { return "InlineAsm AST Node"; }
>>> +
>>> +  void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }
>>> +
>>> +  LlvmInlineAsm *clone_expr_without_block_impl () const override
>>> +  {
>>> +    return new LlvmInlineAsm (*this);
>>> +  }
>>> +
>>> +  Expr::Kind get_expr_kind () const override
>>> +  {
>>> +    return Expr::Kind::LlvmInlineAsm;
>>> +  }
>>> +};
>>> +
>>>   } // namespace AST
>>>   } // namespace Rust
>>>
>>> diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
>>> index d8cc0a480ab..5fca49ca1f3 100644
>>> --- a/gcc/rust/expand/rust-derive.h
>>> +++ b/gcc/rust/expand/rust-derive.h
>>> @@ -171,6 +171,7 @@ private:
>>>     virtual void visit (AwaitExpr &expr) override final{};
>>>     virtual void visit (AsyncBlockExpr &expr) override final{};
>>>     virtual void visit (InlineAsm &expr) override final{};
>>> +  virtual void visit (LlvmInlineAsm &expr) override final{};
>>>     virtual void visit (TypeParam &param) override final{};
>>>     virtual void visit (LifetimeWhereClauseItem &item) override final{};
>>>     virtual void visit (TypeBoundWhereClauseItem &item) override final{};
>>> diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc
>>> index 97f7e3cff77..8bee4524d49 100644
>>> --- a/gcc/rust/expand/rust-macro-builtins-asm.cc
>>> +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
>>> @@ -660,6 +660,15 @@ MacroBuiltin::asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
>>>     return parse_asm (invoc_locus, invoc, semicolon, is_global_asm);
>>>   }
>>>
>>> +tl::optional<AST::Fragment>
>>> +MacroBuiltin::llvm_asm_handler (location_t invoc_locus,
>>> +                               AST::MacroInvocData &invoc,
>>> +                               AST::InvocKind semicolon,
>>> +                               AST::AsmKind is_global_asm)
>>> +{
>>> +  return parse_llvm_asm (invoc_locus, invoc, semicolon, is_global_asm);
>>> +}
>>> +
>>>   tl::expected<InlineAsmContext, InlineAsmParseError>
>>>   parse_asm_arg (InlineAsmContext inline_asm_ctx)
>>>   {
>>> @@ -970,4 +979,16 @@ validate (InlineAsmContext inline_asm_ctx)
>>>   {
>>>     return tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx);
>>>   }
>>> +
>>> +tl::optional<AST::Fragment>
>>> +parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
>>> +               AST::InvocKind semicolon, AST::AsmKind is_global_asm)
>>> +{
>>> +  MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
>>> +  Parser<MacroInvocLexer> parser (lex);
>>> +  auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
>>> +
>>> +  AST::LlvmInlineAsm llvm_asm{invoc_locus};
>>> +}
>>> +
>>>   } // namespace Rust
>>> diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h
>>> index 8081dae5140..e13ee25a935 100644
>>> --- a/gcc/rust/expand/rust-macro-builtins-asm.h
>>> +++ b/gcc/rust/expand/rust-macro-builtins-asm.h
>>> @@ -172,4 +172,11 @@ tl::optional<std::string>
>>>   parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
>>>               InlineAsmContext &inline_asm_ctx);
>>>
>>> +// LLVM ASM bits
>>> +
>>> +WARN_UNUSED_RESULT
>>> +tl::optional<AST::Fragment>
>>> +parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
>>> +               AST::InvocKind semicolon, AST::AsmKind is_global_asm);
>>> +
>>>   } // namespace Rust
>>> diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
>>> index 8b406fff9e6..b58ed71ba4e 100644
>>> --- a/gcc/rust/expand/rust-macro-builtins.cc
>>> +++ b/gcc/rust/expand/rust-macro-builtins.cc
>>> @@ -103,6 +103,15 @@ inline_asm_maker (AST::AsmKind global_asm)
>>>     };
>>>   }
>>>
>>> +AST::MacroTranscriberFunc
>>> +inline_llvm_asm_maker (AST::AsmKind global_asm)
>>> +{
>>> +  return [global_asm] (location_t loc, AST::MacroInvocData &invoc,
>>> +                      AST::InvocKind semicolon) {
>>> +    return MacroBuiltin::llvm_asm_handler (loc, invoc, semicolon, global_asm);
>>> +  };
>>> +}
>>> +
>>>   std::unordered_map<std::string, AST::MacroTranscriberFunc>
>>>     MacroBuiltin::builtin_transcribers = {
>>>       {"assert", MacroBuiltin::assert_handler},
>>> @@ -121,7 +130,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
>>>       {"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)},
>>>       {"asm", inline_asm_maker (AST::AsmKind::Inline)},
>>>       // FIXME: Is that okay?
>>> -    {"llvm_asm", inline_asm_maker (AST::AsmKind::Inline)},
>>> +    {"llvm_asm", inline_llvm_asm_maker (AST::AsmKind::Inline)},
>>>       {"global_asm", inline_asm_maker (AST::AsmKind::Global)},
>>>       {"option_env", MacroBuiltin::option_env_handler},
>>>       /* Unimplemented macro builtins */
>>> diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
>>> index ff06ebf2289..541e95636b1 100644
>>> --- a/gcc/rust/expand/rust-macro-builtins.h
>>> +++ b/gcc/rust/expand/rust-macro-builtins.h
>>> @@ -180,6 +180,10 @@ public:
>>>                                                    AST::InvocKind semicolon,
>>>                                                    AST::AsmKind is_global_asm);
>>>
>>> +  static tl::optional<AST::Fragment>
>>> +  llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
>>> +                   AST::InvocKind semicolon, AST::AsmKind is_global_asm);
>>> +
>>>     static tl::optional<AST::Fragment>
>>>     format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
>>>                         AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
>>> diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
>>> index 5039798a810..2d9a4450c90 100644
>>> --- a/gcc/rust/hir/rust-ast-lower-base.cc
>>> +++ b/gcc/rust/hir/rust-ast-lower-base.cc
>>> @@ -267,6 +267,10 @@ void
>>>   ASTLoweringBase::visit (AST::InlineAsm &)
>>>   {}
>>>
>>> +void
>>> +ASTLoweringBase::visit (AST::LlvmInlineAsm &)
>>> +{}
>>> +
>>>   //  void ASTLoweringBase::visit(MatchCasematch_case) {}
>>>   // void ASTLoweringBase:: (AST::MatchCaseBlockExpr &) {}
>>>   // void ASTLoweringBase:: (AST::MatchCaseExpr &) {}
>>> diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
>>> index b3bb174babf..31161810c6f 100644
>>> --- a/gcc/rust/hir/rust-ast-lower-base.h
>>> +++ b/gcc/rust/hir/rust-ast-lower-base.h
>>> @@ -152,6 +152,7 @@ public:
>>>     virtual void visit (AST::IfLetExpr &expr) override;
>>>     virtual void visit (AST::IfLetExprConseqElse &expr) override;
>>>     virtual void visit (AST::InlineAsm &expr) override;
>>> +  virtual void visit (AST::LlvmInlineAsm &expr) override;
>>>     //  virtual void visit(MatchCase& match_case) override;
>>>     // virtual void visit (AST::MatchCaseBlockExpr &match_case) override;
>>>     // virtual void visit (AST::MatchCaseExpr &match_case) override;
>>> diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
>>> index 6c35a22b7f6..b781ce33f3f 100644
>>> --- a/gcc/rust/resolve/rust-ast-resolve-base.cc
>>> +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
>>> @@ -327,6 +327,10 @@ void
>>>   ResolverBase::visit (AST::InlineAsm &)
>>>   {}
>>>
>>> +void
>>> +ResolverBase::visit (AST::LlvmInlineAsm &)
>>> +{}
>>> +
>>>   void
>>>   ResolverBase::visit (AST::TypeParam &)
>>>   {}
>>> diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
>>> index ab74e84f079..5bb9e4f1822 100644
>>> --- a/gcc/rust/resolve/rust-ast-resolve-base.h
>>> +++ b/gcc/rust/resolve/rust-ast-resolve-base.h
>>> @@ -110,6 +110,7 @@ public:
>>>     void visit (AST::AwaitExpr &);
>>>     void visit (AST::AsyncBlockExpr &);
>>>     void visit (AST::InlineAsm &);
>>> +  void visit (AST::LlvmInlineAsm &);
>>>
>>>     void visit (AST::TypeParam &);
>>>
>>> --
>>> 2.49.0
>>>

-- 
Arthur Cohen <arthur.cohen@embecosm.com>

Toolchain Engineer

Embecosm GmbH

Geschäftsführer: Jeremy Bennett
Niederlassung: Nürnberg
Handelsregister: HR-B 36368
www.embecosm.de

Fürther Str. 27
90429 Nürnberg


Tel.: 091 - 128 707 040
Fax: 091 - 128 707 077

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0x1B3465B044AD9C65.asc
Type: application/pgp-keys
Size: 3143 bytes
Desc: OpenPGP public key
URL: <https://gcc.gnu.org/pipermail/gcc-rust/attachments/20250428/8292c0c8/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <https://gcc.gnu.org/pipermail/gcc-rust/attachments/20250428/8292c0c8/attachment-0001.sig>


More information about the Gcc-rust mailing list