diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp index c1a451a7119d5..e6123e6e74e43 100644 --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -778,6 +778,19 @@ class MasmParser : public MCAsmParser { std::optional evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc); + // Generic (target and platform independent) directive parsing. + enum BuiltinFunction { + BI_NO_FUNCTION, // Placeholder + BI_CATSTR, + }; + + /// Maps builtin name --> BuiltinFunction enum, for builtins handled by this + /// class. + StringMap BuiltinFunctionMap; + + bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name, + std::string &Res); + // ".ascii", ".asciz", ".string" bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); @@ -959,7 +972,7 @@ class MasmParser : public MCAsmParser { bool parseDirectiveEcho(SMLoc DirectiveLoc); void initializeDirectiveKindMap(); - void initializeBuiltinSymbolMap(); + void initializeBuiltinSymbolMaps(); }; } // end anonymous namespace @@ -999,7 +1012,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, initializeDirectiveKindMap(); PlatformParser->Initialize(*this); - initializeBuiltinSymbolMap(); + initializeBuiltinSymbolMaps(); NumOfMacroInstantiations = 0; } @@ -1084,15 +1097,25 @@ bool MasmParser::expandMacros() { } std::optional ExpandedValue; - auto BuiltinIt = BuiltinSymbolMap.find(IDLower); - if (BuiltinIt != BuiltinSymbolMap.end()) { + + if (auto BuiltinIt = BuiltinSymbolMap.find(IDLower); + BuiltinIt != BuiltinSymbolMap.end()) { ExpandedValue = evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc()); - } else { - auto VarIt = Variables.find(IDLower); - if (VarIt != Variables.end() && VarIt->getValue().IsText) { - ExpandedValue = VarIt->getValue().TextValue; + } else if (auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower); + BuiltinFuncIt != BuiltinFunctionMap.end()) { + StringRef Name; + if (parseIdentifier(Name)) { + return true; + } + std::string Res; + if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) { + return true; } + ExpandedValue = Res; + } else if (auto VarIt = Variables.find(IDLower); + VarIt != Variables.end() && VarIt->getValue().IsText) { + ExpandedValue = VarIt->getValue().TextValue; } if (!ExpandedValue) @@ -3197,6 +3220,18 @@ bool MasmParser::parseTextItem(std::string &Data) { continue; } + // Try to resolve as a built-in macro function + auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower()); + if (BuiltinFuncIt != BuiltinFunctionMap.end()) { + Data.clear(); + if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) { + return true; + } + ID = StringRef(Data); + Expanded = true; + continue; + } + // Try to resolve as a variable text macro auto VarIt = Variables.find(ID.lower()); if (VarIt != Variables.end()) { @@ -6204,7 +6239,7 @@ bool MasmParser::parseMSInlineAsm( return false; } -void MasmParser::initializeBuiltinSymbolMap() { +void MasmParser::initializeBuiltinSymbolMaps() { // Numeric built-ins (supported in all versions) BuiltinSymbolMap["@version"] = BI_VERSION; BuiltinSymbolMap["@line"] = BI_LINE; @@ -6216,6 +6251,9 @@ void MasmParser::initializeBuiltinSymbolMap() { BuiltinSymbolMap["@filename"] = BI_FILENAME; BuiltinSymbolMap["@curseg"] = BI_CURSEG; + // Function built-ins (supported in all versions) + BuiltinFunctionMap["@catstr"] = BI_CATSTR; + // Some built-ins exist only for MASM32 (32-bit x86) if (getContext().getSubtargetInfo()->getTargetTriple().getArch() == Triple::x86) { @@ -6289,6 +6327,48 @@ MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) { llvm_unreachable("unhandled built-in symbol"); } +bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function, + StringRef Name, + std::string &Res) { + if (parseToken(AsmToken::LParen, "invoking macro function '" + Name + + "' requires arguments in parentheses")) { + return true; + } + + MCAsmMacroParameters P; + switch (Function) { + default: + return true; + case BI_CATSTR: + break; + } + MCAsmMacro M(Name, "", P, {}, true); + + MCAsmMacroArguments A; + if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) { + return true; + } + + switch (Function) { + default: + llvm_unreachable("unhandled built-in function"); + case BI_CATSTR: { + for (const MCAsmMacroArgument &Arg : A) { + for (const AsmToken &Tok : Arg) { + if (Tok.is(AsmToken::String)) { + Res.append(Tok.getStringContents()); + } else { + Res.append(Tok.getString()); + } + } + } + return false; + } + } + llvm_unreachable("unhandled built-in function"); + return true; +} + /// Create an MCAsmParser instance. MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C, MCStreamer &Out, const MCAsmInfo &MAI, diff --git a/llvm/test/tools/llvm-ml/macro_function.asm b/llvm/test/tools/llvm-ml/macro_function.asm index c28d7c8c6222c..475c8b52dce79 100644 --- a/llvm/test/tools/llvm-ml/macro_function.asm +++ b/llvm/test/tools/llvm-ml/macro_function.asm @@ -103,14 +103,20 @@ expr_recursive_test PROC ret expr_recursive_test ENDP +expand_as_directive_test @CatStr(P, RO, C) +; CHECK-LABEL: expand_as_directive_test: + + ret +expand_as_directive_test ENDP + custom_strcat MACRO arg1, arg2 EXITM ENDM -expand_as_directive_test custom_strcat(P, ROC) -; CHECK-LABEL: expand_as_directive_test: +expand_as_directive_custom_test custom_strcat(P, ROC) +; CHECK-LABEL: expand_as_directive_custom_test: ret -expand_as_directive_test ENDP +expand_as_directive_custom_test ENDP end