From 0fd90bc12f77820e757ef3a427fab9f66aba6381 Mon Sep 17 00:00:00 2001
From: Benjamin Kramer <benny.kra@googlemail.com>
Date: Tue, 8 Feb 2011 22:29:56 +0000
Subject: [PATCH] Support for .ifdef / .ifndef in the assembler parser. Patch
 by Joerg Sonnenberger.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125120 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/MC/MCParser/AsmParser.cpp | 32 +++++++++++++++++++++++++++++++-
 test/MC/AsmParser/ifdef.s     | 29 +++++++++++++++++++++++++++++
 test/MC/AsmParser/ifndef.s    | 29 +++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 test/MC/AsmParser/ifdef.s
 create mode 100644 test/MC/AsmParser/ifndef.s

diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 8654db55966..80bab43a22a 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -202,6 +202,8 @@ private:
   bool ParseDirectiveInclude(); // ".include"
 
   bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
+  // ".ifdef" or ".ifndef", depending on expect_defined
+  bool ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
   bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
   bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
   bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
@@ -222,7 +224,6 @@ class GenericAsmParser : public MCAsmParserExtension {
     getParser().AddDirectiveHandler(this, Directive,
                                     HandleDirective<GenericAsmParser, Handler>);
   }
-
 public:
   GenericAsmParser() {}
 
@@ -887,6 +888,10 @@ bool AsmParser::ParseStatement() {
   // example.
   if (IDVal == ".if")
     return ParseDirectiveIf(IDLoc);
+  if (IDVal == ".ifdef")
+    return ParseDirectiveIfdef(IDLoc, true);
+  if (IDVal == ".ifndef" || IDVal == ".ifnotdef")
+    return ParseDirectiveIfdef(IDLoc, false);
   if (IDVal == ".elseif")
     return ParseDirectiveElseIf(IDLoc);
   if (IDVal == ".else")
@@ -1933,6 +1938,31 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
   return false;
 }
 
+bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
+  StringRef Name;
+  TheCondStack.push_back(TheCondState);
+  TheCondState.TheCond = AsmCond::IfCond;
+
+  if (TheCondState.Ignore) {
+    EatToEndOfStatement();
+  } else {
+    if (ParseIdentifier(Name))
+      return TokError("expected identifier after '.ifdef'");
+
+    Lex();
+
+    MCSymbol *Sym = getContext().LookupSymbol(Name);
+
+    if (expect_defined)
+      TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined());
+    else
+      TheCondState.CondMet = (Sym == NULL || Sym->isUndefined());
+    TheCondState.Ignore = !TheCondState.CondMet;
+  }
+
+  return false;
+}
+
 /// ParseDirectiveElseIf
 /// ::= .elseif expression
 bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
diff --git a/test/MC/AsmParser/ifdef.s b/test/MC/AsmParser/ifdef.s
new file mode 100644
index 00000000000..98bff6525b2
--- /dev/null
+++ b/test/MC/AsmParser/ifdef.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifdef undefined
+	.byte 0
+.else
+	.byte 1
+.endif
+
+defined:
+
+# CHECK: .byte 1
+# CHECK-NOT: .byte 0
+.ifdef defined
+	.byte 1
+.else
+	.byte 0
+.endif
+
+	movl	%eax, undefined
+
+# CHECK-NOT: .byte 0
+# CHECK: .byte 1
+.ifdef undefined
+	.byte 0
+.else
+	.byte 1
+.endif
diff --git a/test/MC/AsmParser/ifndef.s b/test/MC/AsmParser/ifndef.s
new file mode 100644
index 00000000000..d9c9c5457a7
--- /dev/null
+++ b/test/MC/AsmParser/ifndef.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+# CHECK: .byte 1
+# CHECK-NOT: byte 0
+.ifndef undefined
+	.byte 1
+.else
+	.byte 0
+.endif
+
+defined:
+
+# CHECK-NOT: byte 0
+# CHECK: .byte 1
+.ifndef defined
+	.byte 0
+.else
+	.byte 1
+.endif
+
+	movl	%eax, undefined
+
+# CHECK: .byte 1
+# CHECK-NOT: byte 0
+.ifndef undefined
+	.byte 1
+.else
+	.byte 0
+.endif