diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-07-18 18:47:21 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-07-18 18:47:21 +0000 |
commit | 6d8cf082f643a585b82e8dd136641ee4638b8c7a (patch) | |
tree | ce0ddae1f70ee4861ba3ad58f59763d25307a81a /lib/MC/MCParser/AsmParser.cpp | |
parent | fb2d1b2e0a265ee7b3d3bfd769fb59ede22211e9 (diff) |
MC/AsmParser: Add basic parsing support for .macro definitions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108652 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index d4db857a22..eb39205336 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -36,6 +36,15 @@ using namespace llvm; 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 @@ private: /// 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 @@ public: 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 @@ bool AsmParser::ParseStatement() { 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 @@ bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive, 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, |