Asm Parser: support .error directive
authorSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 23 Feb 2014 23:02:23 +0000 (23:02 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 23 Feb 2014 23:02:23 +0000 (23:02 +0000)
The .error directive is similar to .err in that it will halt assembly if it is
evaluated for assembly.  However, it permits a user supplied message to be
rendered.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201999 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/MCParser/AsmParser.cpp
test/MC/AsmParser/directive-err-diagnostics.s [new file with mode: 0644]
test/MC/AsmParser/directive-err.s

index ae6a23dff99ef69afaa5d2b01f7a415b1de2a662..b068724a95841dedd05589cd7f3defb5b3a7a371 100644 (file)
@@ -361,7 +361,7 @@ private:
     DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
     DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
     DK_SLEB128, DK_ULEB128,
-    DK_ERR,
+    DK_ERR, DK_ERROR,
     DK_END
   };
 
@@ -475,8 +475,8 @@ private:
   // "end"
   bool parseDirectiveEnd(SMLoc DirectiveLoc);
 
-  // "err"
-  bool parseDirectiveErr(SMLoc DirectiveLoc);
+  // ".err" or ".error"
+  bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
 
   void initializeDirectiveKindMap();
 };
@@ -1537,7 +1537,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) {
     case DK_END:
       return parseDirectiveEnd(IDLoc);
     case DK_ERR:
-      return parseDirectiveErr(IDLoc);
+      return parseDirectiveError(IDLoc, false);
+    case DK_ERROR:
+      return parseDirectiveError(IDLoc, true);
     }
 
     return Error(IDLoc, "unknown directive");
@@ -3982,13 +3984,34 @@ bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
   return false;
 }
 
-/// parseDirectiveErr
-/// ::= .err
-bool AsmParser::parseDirectiveErr(SMLoc Loc) {
-  if (!TheCondStack.empty())
-    if (TheCondStack.back().Ignore)
+/// parseDirectiveError
+///   ::= .err
+///   ::= .error [string]
+bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
+  if (!TheCondStack.empty()) {
+    if (TheCondStack.back().Ignore) {
+      eatToEndOfStatement();
       return false;
-  return Error(Loc, ".err encountered");
+    }
+  }
+
+  if (!WithMessage)
+    return Error(L, ".err encountered");
+
+  StringRef Message = ".error directive invoked in source file";
+  if (Lexer.isNot(AsmToken::EndOfStatement)) {
+    if (Lexer.isNot(AsmToken::String)) {
+      TokError(".error argument must be a string");
+      eatToEndOfStatement();
+      return true;
+    }
+
+    Message = getTok().getStringContents();
+    Lex();
+  }
+
+  Error(L, Message);
+  return true;
 }
 
 /// parseDirectiveEndIf
@@ -4117,6 +4140,7 @@ void AsmParser::initializeDirectiveKindMap() {
   DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
   DirectiveKindMap[".purgem"] = DK_PURGEM;
   DirectiveKindMap[".err"] = DK_ERR;
+  DirectiveKindMap[".error"] = DK_ERROR;
 }
 
 MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
diff --git a/test/MC/AsmParser/directive-err-diagnostics.s b/test/MC/AsmParser/directive-err-diagnostics.s
new file mode 100644 (file)
index 0000000..ccc5450
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: not llvm-mc -triple i386 %s 2>&1 | FileCheck %s
+
+       .error 0
+// CHECK: error: .error argument must be a string
+// CHECK:      .error 0
+// CHECK:              ^
+
+       .ifeqs "0", "1"
+               .ifeqs "", ""
+                       .error "message"
+               .endif
+       .endif
+// CHECK-NOT: error: message
+// CHECK-NOT: error: invalid instruction mnemonic 'message'
+// CHECK-NOT:  .error "message"
+// CHECK-NOT:          ^
+
index 59c552a4a12b6215e830900a35a1ebc36e00e26b..63b89397f7ce51565ecac66e6a78e1de18f37694 100644 (file)
        .endif
 // CHECK-NOT: error: .err encountered
 
+       .error "This is my error.  There are many like it, but this one is mine."
+// CHECK: error: This is my error.  There are many like it, but this one is mine.
+
+       .ifc one, two
+               .error "My error is my best friend."
+       .endif
+// CHECK-NOT: error: My error is my best friend.
+
+       .error
+// CHECK: error: .error directive invoked in source file
+