Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -261,6 +261,7 @@ bool expandMacro(raw_svector_ostream &OS, StringRef Body, ArrayRef Parameters, ArrayRef A, + const StringRef *VarargString, const SMLoc &L); /// \brief Are macros enabled in the parser? @@ -293,10 +294,11 @@ void handleMacroExit(); /// \brief Extract AsmTokens for a macro argument. - bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg); + bool parseMacroArgument(MCAsmMacroArgument &MA); /// \brief Parse all macro arguments for a given macro. - bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); + bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A, + StringRef *VarargString); void printMacroInstantiations(); void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, @@ -1738,10 +1740,15 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, ArrayRef Parameters, - ArrayRef A, const SMLoc &L) { + ArrayRef A, + const StringRef *VarargString, + const SMLoc &L) { unsigned NParameters = Parameters.size(); bool HasVararg = NParameters ? Parameters.back().Vararg : false; - if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) + + if ((!IsDarwin || NParameters != 0) && + ((HasVararg && A.size() < NParameters) || + (!HasVararg && A.size() != NParameters))) return Error(L, "Wrong number of arguments"); // A macro without parameters is handled differently on Darwin: @@ -1822,17 +1829,28 @@ 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(); + bool VarargParameter = HasVararg && Index == (NParameters - 1); + assert((!VarargParameter || VarargString) && + "Got vararg substitution request without vararg-string?"); + + // If vararg substitution has been requested: + // 1. Print VarargString contents, if it is not empty. + // 2. If VarargString is empty, fall through to A[Index] print, + // since it should contain default value. + if (VarargParameter && !VarargString->empty()) { + OS << *VarargString; + } else { + 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) + OS << it->getString(); + else + OS << it->getStringContents(); + } Pos += 1 + Argument.size(); } } @@ -1895,15 +1913,7 @@ }; } -bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { - - if (Vararg) { - if (Lexer.isNot(AsmToken::EndOfStatement)) { - StringRef Str = parseStringToEndOfStatement(); - MA.push_back(AsmToken(AsmToken::String, Str)); - } - return false; - } +bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) { unsigned ParenLevel = 0; unsigned AddTokens = 0; @@ -1963,8 +1973,8 @@ } // Parse the macro instantiation arguments. -bool AsmParser::parseMacroArguments(const MCAsmMacro *M, - MCAsmMacroArguments &A) { +bool AsmParser::parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A, + StringRef *VarargString) { const unsigned NParameters = M ? M->Parameters.size() : 0; bool NamedParametersFound = false; SmallVector FALocs; @@ -1976,7 +1986,9 @@ // - macros defined without any parameters accept an arbitrary number of them // - macros defined with parameters accept at most that many of them bool HasVararg = NParameters ? M->Parameters.back().Vararg : false; - for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; + const char *VarargStart = 0; + for (unsigned Parameter = 0; + !NParameters || Parameter < NParameters || HasVararg; ++Parameter) { SMLoc IDLoc = Lexer.getLoc(); MCAsmMacroParameter FA; @@ -2004,8 +2016,11 @@ return true; } - bool Vararg = HasVararg && Parameter == (NParameters - 1); - if (parseMacroArgument(FA.Value, Vararg)) + // Also handle all vararg values as single string. + if (HasVararg && Parameter == (NParameters - 1)) + VarargStart = getTok().getLoc().getPointer(); + + if (parseMacroArgument(FA.Value)) return true; unsigned PI = Parameter; @@ -2054,6 +2069,15 @@ A[FAI] = M->Parameters[FAI].Value; } } + + if (!Failure && HasVararg && VarargStart) { + assert(VarargString && + "VarargString could be NULL, if you %100 you considering " + "non-vararg case."); + const char *VarargEnd = getTok().getLoc().getPointer(); + *VarargString = StringRef(VarargStart, VarargEnd - VarargStart); + } + return Failure; } @@ -2088,7 +2112,8 @@ return TokError("macros cannot be nested more than 20 levels deep"); MCAsmMacroArguments A; - if (parseMacroArguments(M, A)) + StringRef VarargString; + if (parseMacroArguments(M, A, &VarargString)) return true; // Macro instantiation is lexical, unfortunately. We construct a new buffer @@ -2097,7 +2122,7 @@ 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, &VarargString, getTok().getLoc())) return true; // We include the .endmacro in the buffer as our cue to exit the macro @@ -3279,9 +3304,11 @@ if (Qualifier == "req") Parameter.Required = true; - else if (Qualifier == "vararg" && !IsDarwin) + else if (Qualifier == "vararg") { + if (IsDarwin) + Warning(QualLoc, Qualifier + " is experimental in darwin."); Parameter.Vararg = true; - else + } else return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " "for '" + Parameter.Name + "' in macro '" + Name + "'"); } @@ -3292,7 +3319,7 @@ SMLoc ParamLoc; ParamLoc = Lexer.getLoc(); - if (parseMacroArgument(Parameter.Value, /*Vararg=*/false )) + if (parseMacroArgument(Parameter.Value)) return true; if (Parameter.Required) @@ -4262,7 +4289,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, nullptr, getTok().getLoc())) return true; } instantiateMacroLikeBody(M, DirectiveLoc, OS); @@ -4284,7 +4311,7 @@ Lex(); MCAsmMacroArguments A; - if (parseMacroArguments(nullptr, A)) + if (parseMacroArguments(nullptr, A, nullptr)) return true; // Eat the end of statement. @@ -4301,7 +4328,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, nullptr, getTok().getLoc())) return true; } @@ -4324,7 +4351,7 @@ Lex(); MCAsmMacroArguments A; - if (parseMacroArguments(nullptr, A)) + if (parseMacroArguments(nullptr, A, nullptr)) return true; if (A.size() != 1 || A.front().size() != 1) @@ -4348,7 +4375,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, nullptr, getTok().getLoc())) return true; } Index: test/MC/AsmParser/macros-darwin-vararg.s =================================================================== --- test/MC/AsmParser/macros-darwin-vararg.s +++ test/MC/AsmParser/macros-darwin-vararg.s @@ -1,8 +1,11 @@ -// RUN: not llvm-mc -triple i386-apple-darwin10 %s 2>&1 | FileCheck %s +// RUN: llvm-mc -triple i386-apple-darwin10 %s 2>&1 | FileCheck %s -// CHECK: error: vararg is not a valid parameter qualifier for 'arg' in macro 'abc' -// CHECK: .macro abc arg:vararg +// CHECK: warning: vararg is experimental in darwin +// CHECK: .macro abc a b:vararg -.macro abc arg:vararg - \arg +.macro abc a b:vararg +.globl "\a, \b" .endm + +// CHECK: .globl "zed0, zed1, zed2" +abc zed0, zed1, zed2