Represent .rept as an anonymous macro. This removes the need for the ActiveRept

vector. No functionality change.
Extracted from a patch by the PaX Team.

llvm-svn: 157909
This commit is contained in:
Rafael Espindola 2012-06-03 23:57:14 +00:00
parent dd17c237a8
commit 34b9c511c1
1 changed files with 91 additions and 58 deletions

View File

@ -113,9 +113,6 @@ private:
/// ActiveMacros - Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
/// ActiveRept - Stack of active .rept directives.
std::vector<SMLoc> ActiveRept;
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabled : 1;
@ -183,7 +180,7 @@ private:
bool ParseCppHashLineFilenameComment(const SMLoc &L);
bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M);
bool expandMacro(SmallString<256> &Buf, StringRef Body,
bool expandMacro(raw_svector_ostream &OS, StringRef Body,
const std::vector<StringRef> &Parameters,
const std::vector<MacroArgument> &A,
const SMLoc &L);
@ -271,8 +268,12 @@ private:
const MCExpr *ApplyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
bool ParseDirectiveRept(SMLoc DirectiveLoc);
bool ParseDirectiveEndRept(SMLoc DirectiveLoc);
// Macro-like directives
Macro *ParseMacroLikeBody(SMLoc DirectiveLoc);
void InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
raw_svector_ostream &OS);
bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept"
bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
};
/// \brief Generic implementations of directive handling, etc. which is shared
@ -1270,10 +1271,11 @@ bool AsmParser::ParseStatement() {
if (IDVal == ".code16" || IDVal == ".code16gcc")
return TokError(Twine(IDVal) + " not supported yet");
// Macro-like directives
if (IDVal == ".rept")
return ParseDirectiveRept(IDLoc);
if (IDVal == ".endr")
return ParseDirectiveEndRept(IDLoc);
return ParseDirectiveEndr(IDLoc);
// Look up the handler in the handler table.
std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
@ -1438,11 +1440,10 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
NewDiag.print(0, OS);
}
bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body,
bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
const std::vector<StringRef> &Parameters,
const std::vector<MacroArgument> &A,
const SMLoc &L) {
raw_svector_ostream OS(Buf);
unsigned NParameters = Parameters.size();
if (NParameters != 0 && NParameters != A.size())
return Error(L, "Wrong number of arguments");
@ -1527,9 +1528,6 @@ bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body,
Body = Body.substr(Pos);
}
// We include the .endmacro in the buffer as our queue to exit the macro
// instantiation.
OS << ".endmacro\n";
return false;
}
@ -1582,12 +1580,17 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,
// to hold the macro body with substitutions.
SmallString<256> Buf;
StringRef Body = M->Body;
raw_svector_ostream OS(Buf);
if (expandMacro(Buf, Body, M->Parameters, MacroArguments, getTok().getLoc()))
if (expandMacro(OS, Body, M->Parameters, MacroArguments, getTok().getLoc()))
return true;
// We include the .endmacro in the buffer as our queue to exit the macro
// instantiation.
OS << ".endmacro\n";
MemoryBuffer *Instantiation =
MemoryBuffer::getMemBufferCopy(Buf.str(), "<instantiation>");
MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
// Create the macro instantiation object and add to the current macro
// instantiation stack.
@ -3137,50 +3140,38 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
return false;
}
bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
const MCExpr *Value;
if (ParseExpression(Value))
return true;
int64_t Count;
if (!Value->EvaluateAsAbsolute(Count))
return TokError("Cannot evaluate value");
if (Count < 0)
return TokError("Count is negative");
Macro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
AsmToken EndToken, StartToken = getTok();
unsigned Nest = 1;
// Lex the macro definition.
unsigned NestLevel = 0;
for (;;) {
// Check whether we have reached the end of the file.
if (getLexer().is(AsmToken::Eof))
return Error(DirectiveLoc, "no matching '.endr' in definition");
// Chcek if we have a nested .rept.
if (getLexer().is(AsmToken::Identifier) &&
(getTok().getIdentifier() == ".rept")) {
Nest++;
EatToEndOfStatement();
continue;
if (getLexer().is(AsmToken::Eof)) {
Error(DirectiveLoc, "no matching '.endr' in definition");
return 0;
}
// Otherwise, check whether we have reach the .endr.
if (getLexer().is(AsmToken::Identifier) &&
(getTok().getIdentifier() == ".endr")) {
Nest--;
if (Nest == 0) {
if (Lexer.is(AsmToken::Identifier) &&
(getTok().getIdentifier() == ".rept")) {
++NestLevel;
}
// Otherwise, check whether we have reached the .endr.
if (Lexer.is(AsmToken::Identifier) &&
getTok().getIdentifier() == ".endr") {
if (NestLevel == 0) {
EndToken = getTok();
Lex();
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.endr' directive");
if (Lexer.isNot(AsmToken::EndOfStatement)) {
TokError("unexpected token in '.endr' directive");
return 0;
}
break;
}
--NestLevel;
}
// Otherwise, scan til the end of the statement.
// Otherwise, scan till the end of the statement.
EatToEndOfStatement();
}
@ -3188,33 +3179,75 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
const char *BodyEnd = EndToken.getLoc().getPointer();
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
SmallString<256> Buf;
raw_svector_ostream OS(Buf);
for (int i = 0; i < Count; i++)
OS << Body;
// We Are Anonymous.
StringRef Name;
std::vector<StringRef> Parameters;
return new Macro(Name, Body, Parameters);
}
void AsmParser::InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
raw_svector_ostream &OS) {
OS << ".endr\n";
MemoryBuffer *Instantiation =
MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
CurBuffer = SrcMgr.AddNewSourceBuffer(Instantiation, SMLoc());
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
// Create the macro instantiation object and add to the current macro
// instantiation stack.
MacroInstantiation *MI = new MacroInstantiation(M, DirectiveLoc,
getTok().getLoc(),
Instantiation);
ActiveMacros.push_back(MI);
ActiveRept.push_back(getTok().getLoc());
// Jump to the macro instantiation and prime the lexer.
CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
Lex();
}
bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
int64_t Count;
if (ParseAbsoluteExpression(Count))
return TokError("unexpected token in '.rept' directive");
if (Count < 0)
return TokError("Count is negative");
if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.rept' directive");
// Eat the end of statement.
Lex();
// Lex the rept definition.
Macro *M = ParseMacroLikeBody(DirectiveLoc);
if (!M)
return true;
// Macro instantiation is lexical, unfortunately. We construct a new buffer
// to hold the macro body with substitutions.
SmallString<256> Buf;
std::vector<StringRef> Parameters;
const std::vector<MacroArgument> A;
raw_svector_ostream OS(Buf);
while (Count--) {
if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc()))
return true;
}
InstantiateMacroLikeBody(M, DirectiveLoc, OS);
return false;
}
bool AsmParser::ParseDirectiveEndRept(SMLoc DirectiveLoc) {
if (ActiveRept.empty())
bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
if (ActiveMacros.empty())
return TokError("unexpected '.endr' directive, no current .rept");
// The only .repl that should get here are the ones created by
// ParseDirectiveRept.
// InstantiateMacroLikeBody.
assert(getLexer().is(AsmToken::EndOfStatement));
JumpToLoc(ActiveRept.back());
ActiveRept.pop_back();
HandleMacroExit();
return false;
}