[llvm-commits] [llvm] r108652 - in /llvm/trunk: lib/MC/MCParser/AsmParser.cpp test/MC/AsmParser/macros-parsing.s

Daniel Dunbar daniel at zuster.org
Sun Jul 18 11:47:21 PDT 2010


Author: ddunbar
Date: Sun Jul 18 13:47:21 2010
New Revision: 108652

URL: http://llvm.org/viewvc/llvm-project?rev=108652&view=rev
Log:
MC/AsmParser: Add basic parsing support for .macro definitions.

Modified:
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/test/MC/AsmParser/macros-parsing.s

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=108652&r1=108651&r2=108652&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Sun Jul 18 13:47:21 2010
@@ -36,6 +36,15 @@
 
 namespace {
 
+/// \brief Helper class for tracking macro definitions.
+struct Macro {
+  StringRef Name;
+  StringRef Body;
+
+public:
+  Macro(StringRef N, StringRef B) : Name(N), Body(B) {}
+};
+
 /// \brief The concrete assembly parser instance.
 class AsmParser : public MCAsmParser {
   friend class GenericAsmParser;
@@ -63,6 +72,9 @@
   /// in the directive name and the location of the directive keyword.
   StringMap<std::pair<MCAsmParserExtension*, DirectiveHandler> > DirectiveMap;
 
+  /// MacroMap - Map of currently defined macros.
+  StringMap<Macro*> MacroMap;
+
   /// Boolean tracking whether macro substitution is enabled.
   unsigned MacrosEnabled : 1;
 
@@ -179,12 +191,21 @@
     Parser.AddDirectiveHandler(this, ".macros_off",
                                MCAsmParser::DirectiveHandler(
                                  &GenericAsmParser::ParseDirectiveMacrosOnOff));
+    Parser.AddDirectiveHandler(this, ".macro", MCAsmParser::DirectiveHandler(
+                                 &GenericAsmParser::ParseDirectiveMacro));
+    Parser.AddDirectiveHandler(this, ".endm", MCAsmParser::DirectiveHandler(
+                                 &GenericAsmParser::ParseDirectiveEndMacro));
+    Parser.AddDirectiveHandler(this, ".endmacro", MCAsmParser::DirectiveHandler(
+                                 &GenericAsmParser::ParseDirectiveEndMacro));
   }
 
   bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc);
   bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc);
   bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc);
+
   bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc);
+  bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
+  bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc);
 };
 
 }
@@ -785,6 +806,17 @@
     if (IDVal == ".include")
       return ParseDirectiveInclude();
 
+    // If macros are enabled, check to see if this is a macro instantiation.
+    if (MacrosEnabled) {
+      if (const Macro *M = MacroMap.lookup(IDVal)) {
+        (void) M;
+
+        Error(IDLoc, "macros are not yet supported");
+        EatToEndOfStatement();
+        return false;
+      }
+    }
+
     // Look up the handler in the handler table.
     std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
       DirectiveMap.lookup(IDVal);
@@ -1626,6 +1658,70 @@
   return false;
 }
 
+/// ParseDirectiveMacro
+/// ::= .macro name
+bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive,
+                                           SMLoc DirectiveLoc) {
+  StringRef Name;
+  if (getParser().ParseIdentifier(Name))
+    return TokError("expected identifier in directive");
+
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in '.macro' directive");
+
+  // Eat the end of statement.
+  Lex();
+
+  AsmToken EndToken, StartToken = getTok();
+
+  // Lex the macro definition.
+  for (;;) {
+    // Check whether we have reached the end of the file.
+    if (getLexer().is(AsmToken::Eof))
+      return Error(DirectiveLoc, "no matching '.endmacro' in definition");
+
+    // Otherwise, check whether we have reach the .endmacro.
+    if (getLexer().is(AsmToken::Identifier) &&
+        (getTok().getIdentifier() == ".endm" ||
+         getTok().getIdentifier() == ".endmacro")) {
+      EndToken = getTok();
+      Lex();
+      if (getLexer().isNot(AsmToken::EndOfStatement))
+        return TokError("unexpected token in '" + EndToken.getIdentifier() +
+                        "' directive");
+      break;
+    }
+
+    // Otherwise, scan til the end of the statement.
+    getParser().EatToEndOfStatement();
+  }
+
+  if (getParser().MacroMap.lookup(Name)) {
+    return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
+  }
+
+  const char *BodyStart = StartToken.getLoc().getPointer();
+  const char *BodyEnd = EndToken.getLoc().getPointer();
+  StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+  getParser().MacroMap[Name] = new Macro(Name, Body);
+  return false;
+}
+
+/// ParseDirectiveEndMacro
+/// ::= .endm
+/// ::= .endmacro
+bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive,
+                                           SMLoc DirectiveLoc) {
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in '" + Directive + "' directive");
+
+  // If we see a .endmacro directly, it is a stray entry in the file; well
+  // formed .endmacro directives are handled during the macro definition
+  // parsing.
+  return TokError("unexpected '" + Directive + "' in file, "
+                  "no current macro definition");
+}
+
 /// \brief Create an MCAsmParser instance.
 MCAsmParser *llvm::createMCAsmParser(const Target &T, SourceMgr &SM,
                                      MCContext &C, MCStreamer &Out,

Modified: llvm/trunk/test/MC/AsmParser/macros-parsing.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/macros-parsing.s?rev=108652&r1=108651&r2=108652&view=diff
==============================================================================
--- llvm/trunk/test/MC/AsmParser/macros-parsing.s (original)
+++ llvm/trunk/test/MC/AsmParser/macros-parsing.s Sun Jul 18 13:47:21 2010
@@ -1,8 +1,23 @@
-// RUN: llvm-mc %s 2> %t.err
+// RUN: not llvm-mc %s 2> %t.err
 // RUN: FileCheck --check-prefix=CHECK-ERRORS %s < %t.err
 
-.macros_on
+.macro .test0
+.endmacro
+
 .macros_off
+// CHECK-ERRORS: 9:1: warning: ignoring directive for now
+.test0
+.macros_on
+// CHECK-ERRORS: 12:1: error: macros are not yet supported
+.test0
+
+// CHECK-ERRORS: macro '.test0' is already defined
+.macro .test0
+.endmacro
+
+// CHECK-ERRORS: unexpected '.endmacro' in file
+.endmacro
+
+// CHECK-ERRORS: no matching '.endmacro' in definition
+.macro dummy
 
-// CHECK-ERRORS: .abort '"end"' detected
-.abort "end"





More information about the llvm-commits mailing list