Skip to content

Commit 7a3028e

Browse files
committed
[ms] [llvm-ml] Allow optional parenthesized arguments for macros
We match ML64.EXE, which allows optional parentheses around a macro's arguments.
1 parent 04d4314 commit 7a3028e

File tree

2 files changed

+98
-12
lines changed

2 files changed

+98
-12
lines changed

llvm/lib/MC/MCParser/MasmParser.cpp

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,19 @@ class MasmParser : public MCAsmParser {
778778
std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
779779
SMLoc StartLoc);
780780

781+
// Generic (target and platform independent) directive parsing.
782+
enum BuiltinFunction {
783+
BI_NO_FUNCTION, // Placeholder
784+
BI_CATSTR,
785+
};
786+
787+
/// Maps builtin name --> BuiltinFunction enum, for builtins handled by this
788+
/// class.
789+
StringMap<BuiltinFunction> BuiltinFunctionMap;
790+
791+
bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
792+
std::string &Res);
793+
781794
// ".ascii", ".asciz", ".string"
782795
bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
783796

@@ -959,7 +972,7 @@ class MasmParser : public MCAsmParser {
959972
bool parseDirectiveEcho(SMLoc DirectiveLoc);
960973

961974
void initializeDirectiveKindMap();
962-
void initializeBuiltinSymbolMap();
975+
void initializeBuiltinSymbolMaps();
963976
};
964977

965978
} // end anonymous namespace
@@ -999,7 +1012,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
9991012

10001013
initializeDirectiveKindMap();
10011014
PlatformParser->Initialize(*this);
1002-
initializeBuiltinSymbolMap();
1015+
initializeBuiltinSymbolMaps();
10031016

10041017
NumOfMacroInstantiations = 0;
10051018
}
@@ -1084,15 +1097,25 @@ bool MasmParser::expandMacros() {
10841097
}
10851098

10861099
std::optional<std::string> ExpandedValue;
1087-
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1088-
if (BuiltinIt != BuiltinSymbolMap.end()) {
1100+
1101+
if (auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1102+
BuiltinIt != BuiltinSymbolMap.end()) {
10891103
ExpandedValue =
10901104
evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1091-
} else {
1092-
auto VarIt = Variables.find(IDLower);
1093-
if (VarIt != Variables.end() && VarIt->getValue().IsText) {
1094-
ExpandedValue = VarIt->getValue().TextValue;
1105+
} else if (auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1106+
BuiltinFuncIt != BuiltinFunctionMap.end()) {
1107+
StringRef Name;
1108+
if (parseIdentifier(Name)) {
1109+
return true;
1110+
}
1111+
std::string Res;
1112+
if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1113+
return true;
10951114
}
1115+
ExpandedValue = Res;
1116+
} else if (auto VarIt = Variables.find(IDLower);
1117+
VarIt != Variables.end() && VarIt->getValue().IsText) {
1118+
ExpandedValue = VarIt->getValue().TextValue;
10961119
}
10971120

10981121
if (!ExpandedValue)
@@ -3199,6 +3222,18 @@ bool MasmParser::parseTextItem(std::string &Data) {
31993222
continue;
32003223
}
32013224

3225+
// Try to resolve as a built-in macro function
3226+
auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower());
3227+
if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3228+
Data.clear();
3229+
if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) {
3230+
return true;
3231+
}
3232+
ID = StringRef(Data);
3233+
Expanded = true;
3234+
continue;
3235+
}
3236+
32023237
// Try to resolve as a variable text macro
32033238
auto VarIt = Variables.find(ID.lower());
32043239
if (VarIt != Variables.end()) {
@@ -6206,7 +6241,7 @@ bool MasmParser::parseMSInlineAsm(
62066241
return false;
62076242
}
62086243

6209-
void MasmParser::initializeBuiltinSymbolMap() {
6244+
void MasmParser::initializeBuiltinSymbolMaps() {
62106245
// Numeric built-ins (supported in all versions)
62116246
BuiltinSymbolMap["@version"] = BI_VERSION;
62126247
BuiltinSymbolMap["@line"] = BI_LINE;
@@ -6218,6 +6253,9 @@ void MasmParser::initializeBuiltinSymbolMap() {
62186253
BuiltinSymbolMap["@filename"] = BI_FILENAME;
62196254
BuiltinSymbolMap["@curseg"] = BI_CURSEG;
62206255

6256+
// Function built-ins (supported in all versions)
6257+
BuiltinFunctionMap["@catstr"] = BI_CATSTR;
6258+
62216259
// Some built-ins exist only for MASM32 (32-bit x86)
62226260
if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
62236261
Triple::x86) {
@@ -6291,6 +6329,48 @@ MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
62916329
llvm_unreachable("unhandled built-in symbol");
62926330
}
62936331

6332+
bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6333+
StringRef Name,
6334+
std::string &Res) {
6335+
if (parseToken(AsmToken::LParen, "invoking macro function '" + Name +
6336+
"' requires arguments in parentheses")) {
6337+
return true;
6338+
}
6339+
6340+
MCAsmMacroParameters P;
6341+
switch (Function) {
6342+
default:
6343+
return true;
6344+
case BI_CATSTR:
6345+
break;
6346+
}
6347+
MCAsmMacro M(Name, "", P, {}, true);
6348+
6349+
MCAsmMacroArguments A;
6350+
if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) {
6351+
return true;
6352+
}
6353+
6354+
switch (Function) {
6355+
default:
6356+
llvm_unreachable("unhandled built-in function");
6357+
case BI_CATSTR: {
6358+
for (const MCAsmMacroArgument &Arg : A) {
6359+
for (const AsmToken &Tok : Arg) {
6360+
if (Tok.is(AsmToken::String)) {
6361+
Res.append(Tok.getStringContents());
6362+
} else {
6363+
Res.append(Tok.getString());
6364+
}
6365+
}
6366+
}
6367+
return false;
6368+
}
6369+
}
6370+
llvm_unreachable("unhandled built-in function");
6371+
return true;
6372+
}
6373+
62946374
/// Create an MCAsmParser instance.
62956375
MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
62966376
MCStreamer &Out, const MCAsmInfo &MAI,

llvm/test/tools/llvm-ml/macro_function.asm

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,20 @@ expr_recursive_test PROC
103103
ret
104104
expr_recursive_test ENDP
105105

106+
expand_as_directive_test @CatStr(P, RO, C)
107+
; CHECK-LABEL: expand_as_directive_test:
108+
109+
ret
110+
expand_as_directive_test ENDP
111+
106112
custom_strcat MACRO arg1, arg2
107113
EXITM <arg1&arg2>
108114
ENDM
109115

110-
expand_as_directive_test custom_strcat(P, ROC)
111-
; CHECK-LABEL: expand_as_directive_test:
116+
expand_as_directive_custom_test custom_strcat(P, ROC)
117+
; CHECK-LABEL: expand_as_directive_custom_test:
112118

113119
ret
114-
expand_as_directive_test ENDP
120+
expand_as_directive_custom_test ENDP
115121

116122
end

0 commit comments

Comments
 (0)