diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 03b004ecfac..4f7734153ac 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -1937,39 +1937,80 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) { const unsigned NParameters = M ? M->Parameters.size() : 0; + A.resize(NParameters); + for (unsigned PI = 0; PI < NParameters; ++PI) + if (!M->Parameters[PI].second.empty()) + A[PI] = M->Parameters[PI].second; + + bool NamedParametersFound = false; + // Parse two kinds of macro invocations: // - macros defined without any parameters accept an arbitrary number of them // - macros defined with parameters accept at most that many of them for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; ++Parameter) { - MCAsmMacroArgument MA; + MCAsmMacroParameter FA; + SMLoc L; - if (parseMacroArgument(MA)) + if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) { + L = Lexer.getLoc(); + if (parseIdentifier(FA.first)) { + Error(L, "invalid argument identifier for formal argument"); + eatToEndOfStatement(); + return true; + } + + if (!Lexer.is(AsmToken::Equal)) { + TokError("expected '=' after formal parameter identifier"); + eatToEndOfStatement(); + return true; + } + Lex(); + + NamedParametersFound = true; + } + + if (NamedParametersFound && FA.first.empty()) { + Error(Lexer.getLoc(), "cannot mix positional and keyword arguments"); + eatToEndOfStatement(); + return true; + } + + if (parseMacroArgument(FA.second)) return true; - if (!MA.empty() || (!NParameters && !Lexer.is(AsmToken::EndOfStatement))) - A.push_back(MA); - else if (NParameters) { - if (!M->Parameters[Parameter].second.empty()) - A.push_back(M->Parameters[Parameter].second); - else - A.push_back(MA); + unsigned PI = Parameter; + if (!FA.first.empty()) { + unsigned FAI = 0; + for (FAI = 0; FAI < NParameters; ++FAI) + if (M->Parameters[FAI].first == FA.first) + break; + if (FAI >= NParameters) { + Error(L, + "parameter named '" + FA.first + "' does not exist for macro '" + + M->Name + "'"); + return true; + } + PI = FAI; + } + + if (!FA.second.empty()) { + if (A.size() <= PI) + A.resize(PI + 1); + A[PI] = FA.second; } // At the end of the statement, fill in remaining arguments that have // default values. If there aren't any, then the next argument is // required but missing - if (Lexer.is(AsmToken::EndOfStatement)) { - if (NParameters && Parameter < NParameters - 1) { - continue; - } + if (Lexer.is(AsmToken::EndOfStatement)) return false; - } if (Lexer.is(AsmToken::Comma)) Lex(); } - return TokError("Too many arguments"); + + return TokError("too many positional arguments"); } const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) { diff --git a/test/MC/AsmParser/macro-err1.s b/test/MC/AsmParser/macro-err1.s index 924deb0cf6e..bd9c837d8be 100644 --- a/test/MC/AsmParser/macro-err1.s +++ b/test/MC/AsmParser/macro-err1.s @@ -7,4 +7,4 @@ foo 42, 42 -// CHECK: Too many arguments +// CHECK: too many positional arguments diff --git a/test/MC/AsmParser/macros-argument-parsing-diagnostics.s b/test/MC/AsmParser/macros-argument-parsing-diagnostics.s new file mode 100644 index 00000000000..a1970e0c9d5 --- /dev/null +++ b/test/MC/AsmParser/macros-argument-parsing-diagnostics.s @@ -0,0 +1,24 @@ +# RUN: not llvm-mc -triple i386 -filetype asm -o /dev/null %s 2>&1 | FileCheck %s + + .macro double first = -1, second = -1 + # begin entry + .long \first + .long \second + # end entry + .endm + + double 0, 1, 2 +# CHECK: error: too many positional arguments +# CHECK: double 0, 1, 2 +# CHECK: ^ + + double second = 1, 2 +# CHECK: error: cannot mix positional and keyword arguments +# CHECK: double second = 1, 2 +# CHECK: ^ + + double third = 0 +# CHECK: error: parameter named 'third' does not exist for macro 'double' +# CHECK: double third = 0 +# CHECK: ^ + diff --git a/test/MC/AsmParser/macros-argument-parsing.s b/test/MC/AsmParser/macros-argument-parsing.s index 097a2702a06..11da298e00e 100644 --- a/test/MC/AsmParser/macros-argument-parsing.s +++ b/test/MC/AsmParser/macros-argument-parsing.s @@ -8,3 +8,54 @@ # CHECK: .long 1 + .macro double first = -1, second = -1 + # begin entry + .long \first + .long \second + # end entry + .endm + + double +# CHECK: .long -1 +# CHECK: .long -1 + + double 1 +# CHECK: .long 1 +# CHECK: .long -1 + + double 2, 3 +# CHECK: .long 2 +# CHECK: .long 3 + + double , 4 +# CHECK: .long -1 +# CHECK: .long 4 + + double 5, second = 6 +# CHECK: .long 5 +# CHECK: .long 6 + + double first = 7 +# CHECK: .long 7 +# CHECK: .long -1 + + double second = 8 +# CHECK: .long -1 +# CHECK: .long 8 + + double second = 9, first = 10 +# CHECK: .long 10 +# CHECK: .long 9 + + double second + 11 +# CHECK: .long second+11 +# CHECK: .long -1 + + double , second + 12 +# CHECK: .long -1 +# CHECK: .long second+12 + + double second +# CHECK: .long second +# CHECK: .long -1 +