From 761cb0675676f894afa675148bd4e86dcfabd27f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 3 Jun 2012 23:57:14 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157909 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCParser/AsmParser.cpp | 143 +++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 55 deletions(-) diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index e8a8491d27e..04603e994a3 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -113,9 +113,6 @@ private: /// ActiveMacros - Stack of active macro instantiations. std::vector ActiveMacros; - /// ActiveRept - Stack of active .rept directives. - std::vector 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 &Parameters, const std::vector &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 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 &Parameters, const std::vector &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(), ""); + MemoryBuffer::getMemBufferCopy(OS.str(), ""); // 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"); + if (getLexer().is(AsmToken::Eof)) { + Error(DirectiveLoc, "no matching '.endr' in definition"); + return 0; + } - // Chcek if we have a nested .rept. - if (getLexer().is(AsmToken::Identifier) && + if (Lexer.is(AsmToken::Identifier) && (getTok().getIdentifier() == ".rept")) { - Nest++; - EatToEndOfStatement(); - continue; + ++NestLevel; } - // Otherwise, check whether we have reach the .endr. - if (getLexer().is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".endr")) { - Nest--; - if (Nest == 0) { + // 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 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(), ""); - CurBuffer = SrcMgr.AddNewSourceBuffer(Instantiation, SMLoc()); + // 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); + + // Jump to the macro instantiation and prime the lexer. + CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lex(); +} - ActiveRept.push_back(getTok().getLoc()); +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 Parameters; + const std::vector 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; } -- 2.34.1