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
This commit is contained in:
Daniel Dunbar 2010-07-18 18:47:21 +00:00
parent fb2d1b2e0a
commit 6d8cf082f6
2 changed files with 116 additions and 5 deletions

View File

@ -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,

View File

@ -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
.macros_off
.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"