From: jjasmine <tanghocle...@gmail.com>

gcc/rust/ChangeLog:

        * expand/rust-macro-builtins-asm.cc (parse_reg_operand):
        Successful parse of in and inout, albeit with str
        (check_identifier): Likewise.
        (parse_asm_arg): Likewise.
        * expand/rust-macro-builtins-asm.h (parse_format_string): Likewise.

gcc/testsuite/ChangeLog:

        * rust/compile/inline_asm_parse_operand.rs: New test.
---
 gcc/rust/expand/rust-macro-builtins-asm.cc    | 108 ++++++++++++++++--
 gcc/rust/expand/rust-macro-builtins-asm.h     |   4 +
 .../rust/compile/inline_asm_parse_operand.rs  |  28 +++++
 3 files changed, 130 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/inline_asm_parse_operand.rs

diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc 
b/gcc/rust/expand/rust-macro-builtins-asm.cc
index 95a268a02de..23f78c01494 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -204,11 +204,15 @@ parse_reg_operand (Parser<MacroInvocLexer> &parser, 
TokenId last_token_id,
   //       };
 
   AST::InlineAsmOperand reg_operand;
+  rust_debug("Enter parse_reg_operand");
   auto token = parser.peek_current_token ();
   auto iden_token = parser.peek_current_token ();
   auto &inline_asm = inline_asm_ctx.inline_asm;
   if (check_identifier (parser, ""))
     {
+    
+      rust_debug("Didn't get passed identifier checking, %s", 
token->as_string().c_str());
+
       auto equal_token = parser.peek_current_token ();
       if (!parser.skip_token (EQUAL))
        {
@@ -218,12 +222,40 @@ parse_reg_operand (Parser<MacroInvocLexer> &parser, 
TokenId last_token_id,
     }
 
   token = parser.peek_current_token ();
+  rust_debug_loc(token->get_locus(), "Got pass identifier checking with %s",  
token->as_string().c_str());
+
 
   bool is_global_asm = inline_asm.is_global_asm;
-  if (!is_global_asm && check_identifier (parser, "in"))
+
+  // For the keyword IN, currently we count it as a seperate keyword called 
Rust::IN
+  // search for #define RS_TOKEN_LIST in code base.
+  if (!is_global_asm && parser.skip_token(IN))
     {
-      rust_unreachable ();
-      return tl::nullopt;
+      rust_debug("Enter parse_reg_operand in");
+
+      auto reg = parse_reg(parser, last_token_id, inline_asm_ctx);
+
+      if (parser.skip_token(UNDERSCORE)) {
+        // We are sure to be failing a test here, based on asm.rs 
+        // 
https://github.com/rust-lang/rust/blob/a330e49593ee890f9197727a3a558b6e6b37f843/compiler/rustc_builtin_macros/src/asm.rs#L112
+        rust_unreachable();
+      }
+
+      auto expr = parse_format_string(parser, last_token_id, inline_asm_ctx) ;
+      reg_operand.register_type = AST::InlineAsmOperand::RegisterType::In;
+      
+      // Since reg is of type optional<T>, we need to check if it is not 
optional first.
+      // TODO: We don't throw any errors since we should have throw any 
encountered parsing error in parse_reg
+      if (reg) {
+        reg_operand.in.reg = reg.value();
+      }
+      
+      // Only clone_expr() if we know that we have parse an expression 
successfully
+      // if (expr) {
+      //   reg_operand.in.expr = expr->clone_expr();
+      // }
+
+      return reg_operand;
     }
   else if (!is_global_asm && check_identifier (parser, "out"))
     {
@@ -237,8 +269,51 @@ parse_reg_operand (Parser<MacroInvocLexer> &parser, 
TokenId last_token_id,
     }
   else if (!is_global_asm && check_identifier (parser, "inout"))
     {
-      rust_unreachable ();
+      rust_debug("Enter parse_reg_operand inout");
+      
+      auto reg = parse_reg(parser, last_token_id, inline_asm_ctx);
+
+      if (parser.skip_token(UNDERSCORE)) {
+        // We are sure to be failing a test here, based on asm.rs 
+        // 
https://github.com/rust-lang/rust/blob/a330e49593ee890f9197727a3a558b6e6b37f843/compiler/rustc_builtin_macros/src/asm.rs#L112
+        rust_unreachable();
+      }
+
+      // TODO: Is error propogation our top priority, the ? in rust's asm.rs 
is doing a lot of work.
+      // TODO: Not sure how to use parse_expr
+      auto expr = parse_format_string(parser, last_token_id, inline_asm_ctx) ;
+
+      std::unique_ptr<AST::Expr> out_expr;
+
+      if (parser.skip_token(MATCH_ARROW)) {
+        rust_debug("Matched MATCH_ARROW");
+        if (!parser.skip_token(UNDERSCORE)) {
+          
+          parse_format_string(parser, last_token_id, inline_asm_ctx) ;
+          //out_expr = parser.parse_expr();
+        }
+
+        reg_operand.register_type = 
AST::InlineAsmOperand::RegisterType::SplitInOut;
+        // reg_operand.split_in_out.in_expr = expr->clone_expr();
+        // reg_operand.split_in_out.out_expr = out_expr->clone_expr();
+        // reg_operand.split_in_out.late = false;
+        return reg_operand;
+
+      } else {
+        reg_operand.register_type = AST::InlineAsmOperand::RegisterType::InOut;
+        // reg_operand.in_out.expr = expr->clone_expr();
+        // reg_operand.in_out.late = false;
+        return reg_operand;
+      }
+    //  if p.eat(&token::FatArrow) {
+    //             let out_expr =
+    //                 if p.eat_keyword(kw::Underscore) { None } else { 
Some(p.parse_expr()?) };
+    //             ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, 
out_expr, late: false }
+    //         } else {
+    //             ast::InlineAsmOperand::InOut { reg, expr, late: false }
+    //         }
       return tl::nullopt;
+
     }
   else if (!is_global_asm && check_identifier (parser, "inlateout"))
     {
@@ -389,17 +464,30 @@ bool
 check_identifier (Parser<MacroInvocLexer> &p, std::string ident)
 {
   auto token = p.peek_current_token ();
-  if (token->get_id () == IDENTIFIER
-      && (token->as_string () == ident || ident == ""))
-    {
+  
+  if (token->get_id () == IDENTIFIER) {
+    auto str = token->as_string();
+
+    // For non-promoted keywords, we need to also check for them.
+
+    if (str == ident) {
       p.skip_token ();
       return true;
     }
-  else
-    {
+    if (ident == "") {
+      if (str != "in" && str != "out" && str != "lateout" && str != "inout" && 
str != "inlateout" && str != "const" && str != "sym" && str != "label")
+      {
+        p.skip_token ();
+        return true;
+      }
       return false;
     }
+  }
+
+  return false;
+
 }
+
 tl::optional<std::string>
 parse_format_string (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
                     InlineAsmContext &inline_asm_ctx)
@@ -485,7 +573,7 @@ parse_asm_arg (Parser<MacroInvocLexer> &parser, TokenId 
last_token_id,
       // Ok after we have check that neither clobber_abi nor options works, the
       // only other logical choice is reg_operand
       // std::cout << "reg_operand" << std::endl;
-      fm_string = parse_format_string (parser, last_token_id, inline_asm_ctx);
+      auto operand = parse_reg_operand (parser, last_token_id, inline_asm_ctx);
     }
   return 0;
 }
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h 
b/gcc/rust/expand/rust-macro-builtins-asm.h
index 45f1fd2f35b..37f5f5aa300 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.h
+++ b/gcc/rust/expand/rust-macro-builtins-asm.h
@@ -68,4 +68,8 @@ int
 parse_clobber_abi (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
                   InlineAsmContext &inline_asm_ctx);
 
+tl::optional<std::string>
+parse_format_string (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
+                    InlineAsmContext &inline_asm_ctx);
+
 } // namespace Rust
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/inline_asm_parse_operand.rs 
b/gcc/testsuite/rust/compile/inline_asm_parse_operand.rs
new file mode 100644
index 00000000000..86d22e08e47
--- /dev/null
+++ b/gcc/testsuite/rust/compile/inline_asm_parse_operand.rs
@@ -0,0 +1,28 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {}
+}
+
+fn main() {
+    unsafe {
+        asm!(
+            "add {0:e}, {0:e}",
+            in(reg) 0
+        );
+    }
+
+    // This adds two numbers num1 and num2 into num1, giving us 30
+    // {0} stands for num1
+    // {1} stands for num2
+    let mut num1: i32 = 10;
+    let num2: i32 = 20;
+    unsafe {
+        asm!(
+            "add {0}, {0}",
+            inout(reg) num1 => num1,
+            in(reg) num2,
+        );
+    }
+}
\ No newline at end of file
-- 
2.45.2

Reply via email to