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

Daniel Dunbar daniel at zuster.org
Sun Jul 18 11:54:12 PDT 2010


Author: ddunbar
Date: Sun Jul 18 13:54:11 2010
New Revision: 108653

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

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=108653&r1=108652&r2=108653&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Sun Jul 18 13:54:11 2010
@@ -45,6 +45,25 @@
   Macro(StringRef N, StringRef B) : Name(N), Body(B) {}
 };
 
+/// \brief Helper class for storing information about an active macro
+/// instantiation.
+struct MacroInstantiation {
+  /// The macro being instantiated.
+  const Macro *TheMacro;
+
+  /// The macro instantiation with substitutions.
+  MemoryBuffer *Instantiation;
+
+  /// The location of the instantiation.
+  SMLoc InstantiationLoc;
+
+  /// The location where parsing should resume upon instantiation completion.
+  SMLoc ExitLoc;
+
+public:
+  MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL);
+};
+
 /// \brief The concrete assembly parser instance.
 class AsmParser : public MCAsmParser {
   friend class GenericAsmParser;
@@ -75,6 +94,9 @@
   /// MacroMap - Map of currently defined macros.
   StringMap<Macro*> MacroMap;
 
+  /// ActiveMacros - Stack of active macro instantiations.
+  std::vector<MacroInstantiation*> ActiveMacros;
+
   /// Boolean tracking whether macro substitution is enabled.
   unsigned MacrosEnabled : 1;
 
@@ -115,11 +137,20 @@
 private:
   bool ParseStatement();
 
+  bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M);
+  void HandleMacroExit();
+
+  void PrintMacroInstantiations();
   void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const;
     
   /// EnterIncludeFile - Enter the specified file. This returns true on failure.
   bool EnterIncludeFile(const std::string &Filename);
-  
+
+  /// \brief Reset the current lexer position to that given by \arg Loc. The
+  /// current token is not set; clients should ensure Lex() is called
+  /// subsequently.
+  void JumpToLoc(SMLoc Loc);
+
   void EatToEndOfStatement();
   
   bool ParseAssignment(StringRef Name);
@@ -247,12 +278,22 @@
   delete GenericParser;
 }
 
+void AsmParser::PrintMacroInstantiations() {
+  // Print the active macro instantiation stack.
+  for (std::vector<MacroInstantiation*>::const_reverse_iterator
+         it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it)
+    PrintMessage((*it)->InstantiationLoc, "while in macro instantiation",
+                 "note");
+}
+
 void AsmParser::Warning(SMLoc L, const Twine &Msg) {
   PrintMessage(L, Msg.str(), "warning");
+  PrintMacroInstantiations();
 }
 
 bool AsmParser::Error(SMLoc L, const Twine &Msg) {
   PrintMessage(L, Msg.str(), "error");
+  PrintMacroInstantiations();
   return true;
 }
 
@@ -272,7 +313,12 @@
   
   return false;
 }
-                  
+
+void AsmParser::JumpToLoc(SMLoc Loc) {
+  CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
+  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer());
+}
+
 const AsmToken &AsmParser::Lex() {
   const AsmToken *tok = &Lexer.Lex();
   
@@ -281,9 +327,7 @@
     // include stack.
     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
     if (ParentIncludeLoc != SMLoc()) {
-      CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
-      Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), 
-                      ParentIncludeLoc.getPointer());
+      JumpToLoc(ParentIncludeLoc);
       tok = &Lexer.Lex();
     }
   }
@@ -716,7 +760,12 @@
   default: // Normal instruction or directive.
     break;
   }
-  
+
+  // If macros are enabled, check to see if this is a macro instantiation.
+  if (MacrosEnabled)
+    if (const Macro *M = MacroMap.lookup(IDVal))
+      return HandleMacroEntry(IDVal, IDLoc, M);
+
   // Otherwise, we have a normal instruction or directive.  
   if (IDVal[0] == '.') {
     // Assembler features
@@ -806,17 +855,6 @@
     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);
@@ -871,6 +909,54 @@
   return HadError;
 }
 
+MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL)
+  : TheMacro(M), InstantiationLoc(IL), ExitLoc(EL)
+{
+  // Macro instantiation is lexical, unfortunately. We construct a new buffer
+  // to hold the macro body with substitutions.
+  llvm::SmallString<256> Buf;
+  Buf += M->Body;
+
+  // We include the .endmacro in the buffer as our queue to exit the macro
+  // instantiation.
+  Buf += ".endmacro\n";
+
+  Instantiation = MemoryBuffer::getMemBufferCopy(Buf, "<instantiation>");
+}
+
+bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,
+                                 const Macro *M) {
+  // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate
+  // this, although we should protect against infinite loops.
+  if (ActiveMacros.size() == 20)
+    return TokError("macros cannot be nested more than 20 levels deep");
+
+  EatToEndOfStatement();
+
+  // Create the macro instantiation object and add to the current macro
+  // instantiation stack.
+  MacroInstantiation *MI = new MacroInstantiation(M, NameLoc,
+                                                  getTok().getLoc());
+  ActiveMacros.push_back(MI);
+
+  // Jump to the macro instantiation and prime the lexer.
+  CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
+  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
+  Lex();
+
+  return false;
+}
+
+void AsmParser::HandleMacroExit() {
+  // Jump to the EndOfStatement we should return to, and consume it.
+  JumpToLoc(ActiveMacros.back()->ExitLoc);
+  Lex();
+
+  // Pop the instantiation entry.
+  delete ActiveMacros.back();
+  ActiveMacros.pop_back();
+}
+
 bool AsmParser::ParseAssignment(StringRef Name) {
   // FIXME: Use better location, we should use proper tokens.
   SMLoc EqualLoc = Lexer.getLoc();
@@ -1715,9 +1801,15 @@
   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.
+  // If we are inside a macro instantiation, terminate the current
+  // instantiation.
+  if (!getParser().ActiveMacros.empty()) {
+    getParser().HandleMacroExit();
+    return false;
+  }
+
+  // Otherwise, this .endmacro 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");
 }

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=108653&r1=108652&r2=108653&view=diff
==============================================================================
--- llvm/trunk/test/MC/AsmParser/macros-parsing.s (original)
+++ llvm/trunk/test/MC/AsmParser/macros-parsing.s Sun Jul 18 13:54:11 2010
@@ -8,7 +8,7 @@
 // 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





More information about the llvm-commits mailing list