[llvm] [ms] [llvm-ml] Allow optional parenthesized arguments for macros (PR #129891)
Eric Astor via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 5 07:32:17 PST 2025
https://github.com/ericastor created https://github.com/llvm/llvm-project/pull/129891
We match ML64.EXE, which allows optional parentheses around a macro's arguments.
>From 7a3028ec7161637a187d86f2f22802905f0440c9 Mon Sep 17 00:00:00 2001
From: Eric Astor <epastor at google.com>
Date: Wed, 5 Mar 2025 15:26:52 +0000
Subject: [PATCH] [ms] [llvm-ml] Allow optional parenthesized arguments for
macros
We match ML64.EXE, which allows optional parentheses around a macro's arguments.
---
llvm/lib/MC/MCParser/MasmParser.cpp | 98 ++++++++++++++++++++--
llvm/test/tools/llvm-ml/macro_function.asm | 12 ++-
2 files changed, 98 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index 4ef781c54f11d..743807ff90c05 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<std::string> 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<BuiltinFunction> 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<std::string> 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)
@@ -3199,6 +3222,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()) {
@@ -6206,7 +6241,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;
@@ -6218,6 +6253,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) {
@@ -6291,6 +6329,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 <arg1&arg2>
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
More information about the llvm-commits
mailing list