[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