AsmParser: Add support for .ifc and .ifnc directives.
authorBenjamin Kramer <benny.kra@googlemail.com>
Sat, 12 May 2012 11:18:51 +0000 (11:18 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sat, 12 May 2012 11:18:51 +0000 (11:18 +0000)
Based on a patch from PaX Team.

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

lib/MC/MCParser/AsmParser.cpp
test/MC/AsmParser/ifc.s [new file with mode: 0644]

index b0491e79fe8b7d7284526f90adae0458f44df42a..d6f9236077e91239cb38726ff1bfeb791ed72fb4 100644 (file)
@@ -209,6 +209,10 @@ private:
   /// will be either the EndOfStatement or EOF.
   StringRef ParseStringToEndOfStatement();
 
+  /// \brief Parse until the end of a statement or a comma is encountered,
+  /// return the contents from the current token up to the end or comma.
+  StringRef ParseStringToComma();
+
   bool ParseAssignment(StringRef Name, bool allow_redef);
 
   bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
@@ -247,6 +251,8 @@ private:
   bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
   // ".ifb" or ".ifnb", depending on ExpectBlank.
   bool ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+  // ".ifc" or ".ifnc", depending on ExpectEqual.
+  bool ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
   // ".ifdef" or ".ifndef", depending on expect_defined
   bool ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
   bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
@@ -604,6 +610,18 @@ StringRef AsmParser::ParseStringToEndOfStatement() {
   return StringRef(Start, End - Start);
 }
 
+StringRef AsmParser::ParseStringToComma() {
+  const char *Start = getTok().getLoc().getPointer();
+
+  while (Lexer.isNot(AsmToken::EndOfStatement) &&
+         Lexer.isNot(AsmToken::Comma) &&
+         Lexer.isNot(AsmToken::Eof))
+    Lex();
+
+  const char *End = getTok().getLoc().getPointer();
+  return StringRef(Start, End - Start);
+}
+
 /// ParseParenExpr - Parse a paren expression and return it.
 /// NOTE: This assumes the leading '(' has already been consumed.
 ///
@@ -1048,6 +1066,10 @@ bool AsmParser::ParseStatement() {
     return ParseDirectiveIfb(IDLoc, true);
   if (IDVal == ".ifnb")
     return ParseDirectiveIfb(IDLoc, false);
+  if (IDVal == ".ifc")
+    return ParseDirectiveIfc(IDLoc, true);
+  if (IDVal == ".ifnc")
+    return ParseDirectiveIfc(IDLoc, false);
   if (IDVal == ".ifdef")
     return ParseDirectiveIfdef(IDLoc, true);
   if (IDVal == ".ifndef" || IDVal == ".ifnotdef")
@@ -2342,6 +2364,38 @@ bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
   return false;
 }
 
+/// ParseDirectiveIfc
+/// ::= .ifc string1, string2
+bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
+  TheCondStack.push_back(TheCondState);
+  TheCondState.TheCond = AsmCond::IfCond;
+
+  if(TheCondState.Ignore) {
+    EatToEndOfStatement();
+  } else {
+    StringRef Str1 = ParseStringToComma();
+
+    if (getLexer().isNot(AsmToken::Comma))
+      return TokError("unexpected token in '.ifc' directive");
+
+    Lex();
+
+    StringRef Str2 = ParseStringToEndOfStatement();
+
+    if (getLexer().isNot(AsmToken::EndOfStatement))
+      return TokError("unexpected token in '.ifc' directive");
+
+    Lex();
+
+    TheCondState.CondMet = ExpectEqual == (Str1 == Str2);
+    TheCondState.Ignore = !TheCondState.CondMet;
+  }
+
+  return false;
+}
+
+/// ParseDirectiveIfdef
+/// ::= .ifdef symbol
 bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
   StringRef Name;
   TheCondStack.push_back(TheCondState);
diff --git a/test/MC/AsmParser/ifc.s b/test/MC/AsmParser/ifc.s
new file mode 100644 (file)
index 0000000..20e55c0
--- /dev/null
@@ -0,0 +1,65 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifc foo, foo
+       .byte 1
+.else
+       .byte 0
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifc "foo space", "foo space"
+       .byte 1
+.else
+       .byte 0
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifc foo space, foo space
+       .byte 1
+.else
+       .byte 0
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifc unequal, unEqual
+       .byte 0
+.else
+       .byte 1
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifnc foo, foo
+       .byte 0
+.else
+       .byte 1
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifnc "foo space", "foo space"
+       .byte 0
+.else
+       .byte 1
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifnc foo space, foo space
+       .byte 0
+.else
+       .byte 1
+.endif
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifnc unequal, unEqual
+       .byte 1
+.else
+       .byte 0
+.endif