Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -67,6 +67,7 @@ StringRef Name; StringRef Body; MCAsmMacroParameters Parameters; + unsigned AtPseudoVariableValue; public: MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P) @@ -138,6 +139,9 @@ /// \brief Map of currently defined macros. StringMap MacroMap; + /// \brief Keeps track of how many .macro's have been defined. + unsigned NumOfMacroDefs; + /// \brief Stack of active macro instantiations. std::vector ActiveMacros; @@ -251,8 +255,8 @@ ArrayRef Parameters); bool expandMacro(raw_svector_ostream &OS, StringRef Body, ArrayRef Parameters, - ArrayRef A, - const SMLoc &L); + ArrayRef A, bool EnableAtPseudoVariable, + unsigned AtPseudoVariableValue, const SMLoc &L); /// \brief Are macros enabled in the parser? bool areMacrosEnabled() {return MacrosEnabledFlag;} @@ -503,6 +507,8 @@ SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); + NumOfMacroDefs = 0; + // Initialize the platform / file format parser. switch (Ctx.getObjectFileInfo()->getObjectFileType()) { case MCObjectFileInfo::IsCOFF: @@ -1764,7 +1770,9 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, ArrayRef Parameters, - ArrayRef A, const SMLoc &L) { + ArrayRef A, + bool EnableAtPseudoVariable, + unsigned AtPseudoVariableValue, const SMLoc &L) { unsigned NParameters = Parameters.size(); bool HasVararg = NParameters ? Parameters.back().Vararg : false; if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) @@ -1830,36 +1838,47 @@ Pos += 2; } else { unsigned I = Pos + 1; - while (isIdentifierChar(Body[I]) && I + 1 != End) + + // Check for the \@ pseudo-variable. + if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End) ++I; + else + while (isIdentifierChar(Body[I]) && I + 1 != End) + ++I; const char *Begin = Body.data() + Pos + 1; StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; - for (; Index < NParameters; ++Index) - if (Parameters[Index].Name == Argument) - break; - if (Index == NParameters) { - if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') - Pos += 3; - else { - OS << '\\' << Argument; - Pos = I; - } + if (EnableAtPseudoVariable && Argument == "@") { + OS << AtPseudoVariableValue; + Pos += 2; } else { - bool VarargParameter = HasVararg && Index == (NParameters - 1); - for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), - ie = A[Index].end(); - it != ie; ++it) - // We expect no quotes around the string's contents when - // parsing for varargs. - if (it->getKind() != AsmToken::String || VarargParameter) - OS << it->getString(); - else - OS << it->getStringContents(); - - Pos += 1 + Argument.size(); + for (; Index < NParameters; ++Index) + if (Parameters[Index].Name == Argument) + break; + + if (Index == NParameters) { + if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') + Pos += 3; + else { + OS << '\\' << Argument; + Pos = I; + } + } else { + bool VarargParameter = HasVararg && Index == (NParameters - 1); + for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), + ie = A[Index].end(); + it != ie; ++it) + // We expect no quotes around the string's contents when + // parsing for varargs. + if (it->getKind() != AsmToken::String || VarargParameter) + OS << it->getString(); + else + OS << it->getStringContents(); + + Pos += 1 + Argument.size(); + } } } // Update the scan point. @@ -2096,10 +2115,18 @@ } void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) { + Macro.AtPseudoVariableValue = NumOfMacroDefs; + ++NumOfMacroDefs; + MacroMap.insert(std::make_pair(Name, std::move(Macro))); } -void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); } +void AsmParser::undefineMacro(StringRef Name) { + MacroMap.erase(Name); + + assert(NumOfMacroDefs > 0 && "There are no .macros to undefine!"); + --NumOfMacroDefs; +} bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate @@ -2117,7 +2144,8 @@ StringRef Body = M->Body; raw_svector_ostream OS(Buf); - if (expandMacro(OS, Body, M->Parameters, A, getTok().getLoc())) + if (expandMacro(OS, Body, M->Parameters, A, true, M->AtPseudoVariableValue, + getTok().getLoc())) return true; // We include the .endmacro in the buffer as our cue to exit the macro @@ -4378,7 +4406,7 @@ SmallString<256> Buf; raw_svector_ostream OS(Buf); while (Count--) { - if (expandMacro(OS, M->Body, None, None, getTok().getLoc())) + if (expandMacro(OS, M->Body, None, None, false, 0, getTok().getLoc())) return true; } instantiateMacroLikeBody(M, DirectiveLoc, OS); @@ -4417,7 +4445,7 @@ raw_svector_ostream OS(Buf); for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) { - if (expandMacro(OS, M->Body, Parameter, *i, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, *i, false, 0, getTok().getLoc())) return true; } @@ -4464,7 +4492,7 @@ MCAsmMacroArgument Arg; Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1))); - if (expandMacro(OS, M->Body, Parameter, Arg, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, Arg, false, 0, getTok().getLoc())) return true; } Index: test/MC/AsmParser/at-pseudo-variable-bad.s =================================================================== --- /dev/null +++ test/MC/AsmParser/at-pseudo-variable-bad.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc -triple i386-unknown-unknown < %s 2>&1 | FileCheck %s + +add $1\@, %eax +# CHECK: :[[@LINE-1]]:8: error: unexpected token in argument list + +.macro A @ + mov %eax, %eax +.endm +# CHECK: :[[@LINE-3]]:11: error: expected identifier in '.macro' directive Index: test/MC/AsmParser/at-pseudo-variable.s =================================================================== --- /dev/null +++ test/MC/AsmParser/at-pseudo-variable.s @@ -0,0 +1,20 @@ +# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +.macro A + mov $1\@, %eax +.endm + +.macro B + add $1\@, %eax +.endm + +.macro C + sub $1\@, %eax +.endm + + A +# CHECK: movl $10, %eax + B +# CHECK: addl $11, %eax + C +# CHECK: subl $12, %eax