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

gcc/rust/ChangeLog:

        * expand/rust-macro-builtins-asm.cc (parse_clobber_abi):
        added comments
        (parse_options): Likewise
        (parse_asm_arg): Likewise
        (parse_asm): Likewise
        * expand/rust-macro-builtins-asm.h: Likewise

gcc/testsuite/ChangeLog:

        * rust/compile/inline_asm_illegal_options.rs: new test
        * rust/compile/inline_asm_illegal_operands.rs: New test.
        This is expected to fail but we couldn't resolve parse_expr()'s
        general functionality yet

Signed-off-by: badumbatish <tanghocle...@gmail.com>
---
 gcc/rust/expand/rust-macro-builtins-asm.cc    | 51 +++++++++----------
 gcc/rust/expand/rust-macro-builtins-asm.h     | 14 +++--
 .../compile/inline_asm_illegal_operands.rs    | 24 +++++++++
 .../compile/inline_asm_illegal_options.rs     |  2 +-
 4 files changed, 60 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/inline_asm_illegal_operands.rs

diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc 
b/gcc/rust/expand/rust-macro-builtins-asm.cc
index 05d8f866c61..dbbe0fa7732 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -49,8 +49,6 @@ parse_clobber_abi (InlineAsmContext inline_asm_ctx)
   auto token = parser.peek_current_token ();
   if (!parser.skip_token (LEFT_PAREN))
     {
-      // TODO: Raise error exactly like rustc if left parenthesis is not
-      // encountered.
       token = parser.peek_current_token ();
 
       // TODO: Error reporting shifted to the left 1 character, I'm not sure
@@ -71,8 +69,6 @@ parse_clobber_abi (InlineAsmContext inline_asm_ctx)
 
   if (parser.skip_token (RIGHT_PAREN))
     {
-      // TODO: We encountered a "clobber_abi()", which should be illegal?
-      // 
https://github.com/rust-lang/rust/blob/c00957a3e269219413041a4e3565f33b1f9d0779/compiler/rustc_builtin_macros/src/asm.rs#L381
       rust_error_at (
        parser.peek_current_token ()->get_locus (),
        "at least one abi must be provided as an argument to %<clobber_abi%>");
@@ -491,9 +487,9 @@ parse_options (InlineAsmContext &inline_asm_ctx)
   // Parse everything commitedly
   if (!parser.skip_token (LEFT_PAREN))
     {
-      // We have shifted `options` to search for the left parenthesis next, we
-      // should error out if this is not possible.
-      // TODO: report some error.
+      auto local_token = parser.peek_current_token ();
+      rust_error_at (local_token->get_locus (), "expected %qs, found %qs", "(",
+                    local_token->as_string ().c_str ());
       return tl::unexpected<InlineAsmParseError> (COMMITTED);
     }
 
@@ -538,7 +534,6 @@ parse_options (InlineAsmContext &inline_asm_ctx)
        }
       else
        {
-         // TODO: Unexpected error, please return the correct error
          rust_error_at (token->get_locus (),
                         "expected one of %qs, %qs, %qs, %qs, %qs, %qs, %qs, "
                         "%qs, %qs, or %qs, found %qs",
@@ -562,7 +557,6 @@ parse_options (InlineAsmContext &inline_asm_ctx)
          rust_unreachable ();
          token = parser.peek_current_token ();
          return tl::unexpected<InlineAsmParseError> (COMMITTED);
-         ;
        }
     }
 
@@ -678,34 +672,45 @@ parse_asm_arg (InlineAsmContext inline_asm_ctx)
       // Ok after the left paren is good, we better be parsing correctly
       // everything in here, which is operand in ABNF
 
-      // TODO: Parse clobber abi, eat the identifier named "clobber_abi" if 
true
+      // Parse clobber abi, eat the identifier named "clobber_abi" if true
       if (check_identifier (parser, "clobber_abi"))
        {
          auto expected = parse_clobber_abi (inline_asm_ctx);
          if (expected || expected.error () == COMMITTED)
            return expected;
 
-         continue;
+         // The error type is definitely non-committed (we have checked above),
+         // we are allowed to keep on parsing
        }
 
-      // TODO: Parse options
       if (check_identifier (parser, "options"))
        {
          auto expected = parse_options (inline_asm_ctx);
          if (expected || expected.error () == COMMITTED)
            return expected;
 
-         continue;
+         // The error type is definitely non-committed (we have checked above),
+         // we are allowed to keep on parsing
        }
 
       // 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;
 
-      // TODO: BUBBLE UP THIS EXPECTED(...)
       auto expected = parse_reg_operand (inline_asm_ctx);
       if (expected || expected.error () == COMMITTED)
        return expected;
+
+      // Since parse_reg_operand is the last thing we've considered,
+      // The non-committed parse error type means that we have exhausted our
+      // search path
+
+      // We then should return the error of COMMITTED, even though we have not
+      // committed to anything So that the error bubbles up and we recover from
+      // this error gracefully
+      rust_error_at (token->get_locus (),
+                    "expected operand, clobber_abi, options, or additional "
+                    "template string");
+      return tl::unexpected<InlineAsmParseError> (COMMITTED);
     }
   return tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx);
 }
@@ -715,19 +720,12 @@ parse_asm (location_t invoc_locus, AST::MacroInvocData 
&invoc,
           AST::InvocKind semicolon, AST::AsmKind is_global_asm)
 {
   // From the rule of asm.
-  // We first peek and see if it is a format string or not.
-  // If yes, we process the first ever format string, and move on to the
-  // recurrent of format string Else we exit out
-
-  // After that, we peek and see if it is a reoccuring stream of format string
-  // or not. If it is, keep on going to do this format string. Else, move on
+  // We first parse all formatted strings. If we fail, then we return
+  // tl::nullopt
 
-  // After that, we peek and see if it is a reoccuring stream of operands or 
not
-  // If it is, keep on going to do this operand thingy.
-  // Else, move on
+  // We then parse the asm arguments. If we fail, then we return tl::nullopt
 
-  // We check if there is an optional "," at the end, per ABNF spec.
-  // If it is, consume it.
+  // We then validate. If we fail, then we return tl::nullopt
 
   // Done
   MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
@@ -738,7 +736,6 @@ parse_asm (location_t invoc_locus, AST::MacroInvocData 
&invoc,
                             is_global_asm == AST::AsmKind::Global);
   auto inline_asm_ctx = InlineAsmContext (inline_asm, parser, last_token_id);
 
-  // operands stream, also handles the optional ","
   tl::expected<InlineAsmContext, InlineAsmParseError> resulting_context
     = tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx);
   resulting_context.and_then (parse_format_strings)
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h 
b/gcc/rust/expand/rust-macro-builtins-asm.h
index 201f80715a1..32a8d0ba030 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.h
+++ b/gcc/rust/expand/rust-macro-builtins-asm.h
@@ -6,11 +6,19 @@
 #include "rust-macro-invoc-lexer.h"
 #include "rust/ast/rust-expr.h"
 namespace Rust {
-// All the operands are called asm_args in rustc asm.rs, we create a struct 
that
-// can store all of these AsmArgs This replaces the phase where we have to 
parse
-// all operands.
+
 enum InlineAsmParseError
 {
+  // Enum for InlineAsmParseError
+
+  // Currently with two error, COMMITTED AND NONCOMMITTED (to a token),
+  // which directs the parser to either bubbles the error up, or keep on going
+  // (vertical or horizontal)
+
+  // COMMITTED can be use as a way for parser to bubble up
+  // after it has exhausted its search space despite it not having committed to
+  // any token
+
   COMMITTED,
   NONCOMMITED,
 };
diff --git a/gcc/testsuite/rust/compile/inline_asm_illegal_operands.rs 
b/gcc/testsuite/rust/compile/inline_asm_illegal_operands.rs
new file mode 100644
index 00000000000..5a13fb96b0a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/inline_asm_illegal_operands.rs
@@ -0,0 +1,24 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {}
+}
+
+fn main() {
+    let mut _x: u64 = 4;
+    unsafe {
+       asm!(
+            "add {x}, {1}",
+            x = in(reg) _x, 
+            x = in(reg) _x,  // { dg-error {duplicate argument named 'x'} "" { 
xfail *-*-* } .-1 }
+        );
+
+        asm!(
+            "mov {x}, {x}",
+            x = inout("eax") _x, //  { dg-error {explicit register arguments 
cannot have names} "" { xfail *-*-* } .-1 }
+            x = inout(reg) _x, // It then proceeds to parse this line, 
resulting in only 1 error instead of duplication error as well.
+        );
+    }
+    _x = 1;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/inline_asm_illegal_options.rs 
b/gcc/testsuite/rust/compile/inline_asm_illegal_options.rs
index 2cf354d6d12..ef546414720 100644
--- a/gcc/testsuite/rust/compile/inline_asm_illegal_options.rs
+++ b/gcc/testsuite/rust/compile/inline_asm_illegal_options.rs
@@ -11,6 +11,6 @@ fn main() {
         asm!("nop", options(noreturn, noreturn)); // { dg-error "the 
'noreturn' option was already provided" }
         asm!("nop", options(xxx)); // { dg-error "expected one of '\\)', 
'att_syntax', 'may_unwind', 'nomem', 'noreturn', 'nostack', 'preserves_flags', 
'pure', 'raw', or 'readonly', found 'xxx'" }
         asm!("nop", options(+)); // { dg-error "expected one of '\\)', 
'att_syntax', 'may_unwind', 'nomem', 'noreturn', 'nostack', 'preserves_flags', 
'pure', 'raw', or 'readonly', found '\\+'" }
-
+        asm!("nop", options+); // { dg-error "expected '\\(', found '\\+'" }
     }
 }
\ No newline at end of file
-- 
2.45.2

Reply via email to