diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -917,7 +917,8 @@ // macro directives bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); - bool parseDirectiveExitMacro(StringRef Directive, std::string &Value); + bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive, + std::string &Value); bool parseDirectiveEndMacro(StringRef Directive); bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc); // alternate macro mode directives @@ -2302,7 +2303,7 @@ return parseDirectiveCFIWindowSave(); case DK_EXITM: Info.ExitValue = ""; - return parseDirectiveExitMacro(IDVal, *Info.ExitValue); + return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue); case DK_ENDM: Info.ExitValue = ""; return parseDirectiveEndMacro(IDVal); @@ -3202,7 +3203,7 @@ // Accept a text-list, not just one text-item. auto parseItem = [&]() -> bool { if (parseTextItem(Value)) - return true; + return TokError("expected text item"); Var.TextValue += Value; return false; }; @@ -3279,8 +3280,38 @@ /// textItem ::= textLiteral | textMacroID | % constExpr bool MasmParser::parseTextItem(std::string &Data) { - // TODO(epastor): Support textMacroID and % expansion of expressions. - return parseAngleBracketString(Data); + switch (getTok().getKind()) { + default: + return true; + case AsmToken::Percent: { + int64_t Res; + if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res)) + return true; + Data = std::to_string(Res); + return false; + } + case AsmToken::Less: + case AsmToken::LessEqual: + case AsmToken::LessLess: + case AsmToken::LessGreater: + return parseAngleBracketString(Data); + case AsmToken::Identifier: { + StringRef ID; + if (parseIdentifier(ID)) + return true; + + auto it = Variables.find(ID); + if (it == Variables.end()) + return true; + + const Variable &Var = it->second; + if (!Var.IsText) + return true; + Data = Var.TextValue; + return false; + } + } + llvm_unreachable("unhandled token kind"); } /// parseDirectiveAscii: @@ -5517,11 +5548,13 @@ /// parseDirectiveExitMacro /// ::= "exitm" [textitem] -bool MasmParser::parseDirectiveExitMacro(StringRef Directive, +bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc, + StringRef Directive, std::string &Value) { - if (getTok().isNot(AsmToken::EndOfStatement)) { - parseTextItem(Value); - } + SMLoc EndLoc = getTok().getLoc(); + if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value)) + return Error(EndLoc, + "unable to parse text item in '" + Directive + "' directive"); eatToEndOfStatement(); if (!isInsideMacroInstantiation()) @@ -5754,7 +5787,7 @@ } /// parseDirectiveIfb -/// ::= .ifb string +/// ::= .ifb textitem bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -5764,7 +5797,7 @@ } else { std::string Str; if (parseTextItem(Str)) - return TokError("expected string parameter for 'ifb' directive"); + return TokError("expected text item parameter for 'ifb' directive"); if (parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifb' directive")) @@ -5778,14 +5811,16 @@ } /// parseDirectiveIfidn -/// ::= ifidn string1, string2 -bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, bool CaseInsensitive) { +/// ::= ifidn textitem, textitem +bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, + bool CaseInsensitive) { std::string String1, String2; if (parseTextItem(String1)) { if (ExpectEqual) - return TokError("expected string parameter for 'ifidn' directive"); - return TokError("expected string parameter for 'ifdif' directive"); + return TokError("expected text item parameter for 'ifidn' directive"); + else + return TokError("expected text item parameter for 'ifdif' directive"); } if (Lexer.isNot(AsmToken::Comma)) { @@ -5798,8 +5833,9 @@ if (parseTextItem(String2)) { if (ExpectEqual) - return TokError("expected string parameter for 'ifidn' directive"); - return TokError("expected string parameter for 'ifdif' directive"); + return TokError("expected text item parameter for 'ifidn' directive"); + else + return TokError("expected text item parameter for 'ifdif' directive"); } TheCondStack.push_back(TheCondState); @@ -5893,7 +5929,7 @@ } /// parseDirectiveElseIfb -/// ::= elseifb expression +/// ::= elseifb textitem bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) @@ -5909,8 +5945,13 @@ eatToEndOfStatement(); } else { std::string Str; - if (parseTextItem(Str)) - return TokError("expected string parameter for 'elseifb' directive"); + if (parseTextItem(Str)) { + if (ExpectBlank) + return TokError("expected text item parameter for 'elseifb' directive"); + else + return TokError( + "expected text item parameter for 'elseifnb' directive"); + } if (parseToken(AsmToken::EndOfStatement, "unexpected token in 'elseifb' directive")) @@ -5970,7 +6011,7 @@ } /// parseDirectiveElseIfidn -/// ::= elseifidn string1, string2 +/// ::= elseifidn textitem, textitem bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual, bool CaseInsensitive) { if (TheCondState.TheCond != AsmCond::IfCond && @@ -5990,23 +6031,30 @@ if (parseTextItem(String1)) { if (ExpectEqual) - return TokError("expected string parameter for 'elseifidn' directive"); - return TokError("expected string parameter for 'elseifdif' directive"); + return TokError( + "expected text item parameter for 'elseifidn' directive"); + else + return TokError( + "expected text item parameter for 'elseifdif' directive"); } if (Lexer.isNot(AsmToken::Comma)) { if (ExpectEqual) return TokError( "expected comma after first string for 'elseifidn' directive"); - return TokError( - "expected comma after first string for 'elseifdif' directive"); + else + return TokError( + "expected comma after first string for 'elseifdif' directive"); } Lex(); if (parseTextItem(String2)) { if (ExpectEqual) - return TokError("expected string parameter for 'elseifidn' directive"); - return TokError("expected string parameter for 'elseifdif' directive"); + return TokError( + "expected text item parameter for 'elseifidn' directive"); + else + return TokError( + "expected text item parameter for 'elseifdif' directive"); } if (CaseInsensitive) @@ -6144,7 +6192,7 @@ } /// parseDirectiveErrorIfidn -/// ::= .erridn textitem1, textitem2[, message] +/// ::= .erridn textitem, textitem[, message] bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual, bool CaseInsensitive) { if (!TheCondStack.empty()) { @@ -6159,22 +6207,25 @@ if (parseTextItem(String1)) { if (ExpectEqual) return TokError("expected string parameter for '.erridn' directive"); - return TokError("expected string parameter for '.errdif' directive"); + else + return TokError("expected string parameter for '.errdif' directive"); } if (Lexer.isNot(AsmToken::Comma)) { if (ExpectEqual) return TokError( "expected comma after first string for '.erridn' directive"); - return TokError( - "expected comma after first string for '.errdif' directive"); + else + return TokError( + "expected comma after first string for '.errdif' directive"); } Lex(); if (parseTextItem(String2)) { if (ExpectEqual) return TokError("expected string parameter for '.erridn' directive"); - return TokError("expected string parameter for '.errdif' directive"); + else + return TokError("expected string parameter for '.errdif' directive"); } StringRef Message; diff --git a/llvm/test/tools/llvm-ml/macro_function.test b/llvm/test/tools/llvm-ml/macro_function.test --- a/llvm/test/tools/llvm-ml/macro_function.test +++ b/llvm/test/tools/llvm-ml/macro_function.test @@ -73,25 +73,34 @@ ENDIF ENDM +string_recursive_test PROC +; CHECK-LABEL: string_recursive_test: + + mov eax, factorial(5) +; CHECK: mov eax, 120 + mov eax, factorial2(4) +; CHECK: mov eax, 24 + mov eax, 11 + factorial(6) - 11 +; CHECK: mov eax, 720 + + ret +string_recursive_test ENDP + fibonacci MACRO n IF n LE 2 - EXITM <(1)> + EXITM %1 ELSE - EXITM <(fibonacci(n-1)+fibonacci(n-2))> + EXITM %fibonacci(n-1)+fibonacci(n-2) ENDIF ENDM -recursive_test PROC -; CHECK-LABEL: recursive_test: +expr_recursive_test PROC +; CHECK-LABEL: expr_recursive_test: - mov eax, factorial(5) -; CHECK: mov eax, 120 - mov eax, factorial2(4) -; CHECK: mov eax, 24 - mov eax, 11 + fibonacci(7) - 11 -; CHECK: mov eax, 13 + mov eax, fibonacci(10) +; CHECK: mov eax, 55 ret -recursive_test ENDP +expr_recursive_test ENDP end