Skip to content

Commit 0ab330b

Browse files
authored
[ms] [llvm-ml] Add support for @CatStr built-in function symbol (#130781)
MASM supports some built-in macro-type functions. We start our support for these with `@CatStr`, one of the more commonly used.
1 parent c7fbaba commit 0ab330b

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
@@ -765,6 +765,19 @@ class MasmParser : public MCAsmParser {
765765
std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
766766
SMLoc StartLoc);
767767

768+
// Generic (target and platform independent) directive parsing.
769+
enum BuiltinFunction {
770+
BI_NO_FUNCTION, // Placeholder
771+
BI_CATSTR,
772+
};
773+
774+
/// Maps builtin name --> BuiltinFunction enum, for builtins handled by this
775+
/// class.
776+
StringMap<BuiltinFunction> BuiltinFunctionMap;
777+
778+
bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
779+
std::string &Res);
780+
768781
// ".ascii", ".asciz", ".string"
769782
bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
770783

@@ -946,7 +959,7 @@ class MasmParser : public MCAsmParser {
946959
bool parseDirectiveEcho(SMLoc DirectiveLoc);
947960

948961
void initializeDirectiveKindMap();
949-
void initializeBuiltinSymbolMap();
962+
void initializeBuiltinSymbolMaps();
950963
};
951964

952965
} // end anonymous namespace
@@ -986,7 +999,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
986999

9871000
initializeDirectiveKindMap();
9881001
PlatformParser->Initialize(*this);
989-
initializeBuiltinSymbolMap();
1002+
initializeBuiltinSymbolMaps();
9901003

9911004
NumOfMacroInstantiations = 0;
9921005
}
@@ -1071,15 +1084,25 @@ bool MasmParser::expandMacros() {
10711084
}
10721085

10731086
std::optional<std::string> ExpandedValue;
1074-
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1075-
if (BuiltinIt != BuiltinSymbolMap.end()) {
1087+
1088+
if (auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1089+
BuiltinIt != BuiltinSymbolMap.end()) {
10761090
ExpandedValue =
10771091
evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1078-
} else {
1079-
auto VarIt = Variables.find(IDLower);
1080-
if (VarIt != Variables.end() && VarIt->getValue().IsText) {
1081-
ExpandedValue = VarIt->getValue().TextValue;
1092+
} else if (auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1093+
BuiltinFuncIt != BuiltinFunctionMap.end()) {
1094+
StringRef Name;
1095+
if (parseIdentifier(Name)) {
1096+
return true;
1097+
}
1098+
std::string Res;
1099+
if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1100+
return true;
10821101
}
1102+
ExpandedValue = Res;
1103+
} else if (auto VarIt = Variables.find(IDLower);
1104+
VarIt != Variables.end() && VarIt->getValue().IsText) {
1105+
ExpandedValue = VarIt->getValue().TextValue;
10831106
}
10841107

10851108
if (!ExpandedValue)
@@ -3104,6 +3127,18 @@ bool MasmParser::parseTextItem(std::string &Data) {
31043127
continue;
31053128
}
31063129

3130+
// Try to resolve as a built-in macro function
3131+
auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower());
3132+
if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3133+
Data.clear();
3134+
if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) {
3135+
return true;
3136+
}
3137+
ID = StringRef(Data);
3138+
Expanded = true;
3139+
continue;
3140+
}
3141+
31073142
// Try to resolve as a variable text macro
31083143
auto VarIt = Variables.find(ID.lower());
31093144
if (VarIt != Variables.end()) {
@@ -6110,7 +6145,7 @@ bool MasmParser::parseMSInlineAsm(
61106145
return false;
61116146
}
61126147

6113-
void MasmParser::initializeBuiltinSymbolMap() {
6148+
void MasmParser::initializeBuiltinSymbolMaps() {
61146149
// Numeric built-ins (supported in all versions)
61156150
BuiltinSymbolMap["@version"] = BI_VERSION;
61166151
BuiltinSymbolMap["@line"] = BI_LINE;
@@ -6122,6 +6157,9 @@ void MasmParser::initializeBuiltinSymbolMap() {
61226157
BuiltinSymbolMap["@filename"] = BI_FILENAME;
61236158
BuiltinSymbolMap["@curseg"] = BI_CURSEG;
61246159

6160+
// Function built-ins (supported in all versions)
6161+
BuiltinFunctionMap["@catstr"] = BI_CATSTR;
6162+
61256163
// Some built-ins exist only for MASM32 (32-bit x86)
61266164
if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
61276165
Triple::x86) {
@@ -6195,6 +6233,48 @@ MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
61956233
llvm_unreachable("unhandled built-in symbol");
61966234
}
61976235

6236+
bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6237+
StringRef Name,
6238+
std::string &Res) {
6239+
if (parseToken(AsmToken::LParen, "invoking macro function '" + Name +
6240+
"' requires arguments in parentheses")) {
6241+
return true;
6242+
}
6243+
6244+
MCAsmMacroParameters P;
6245+
switch (Function) {
6246+
default:
6247+
return true;
6248+
case BI_CATSTR:
6249+
break;
6250+
}
6251+
MCAsmMacro M(Name, "", P, {}, true);
6252+
6253+
MCAsmMacroArguments A;
6254+
if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) {
6255+
return true;
6256+
}
6257+
6258+
switch (Function) {
6259+
default:
6260+
llvm_unreachable("unhandled built-in function");
6261+
case BI_CATSTR: {
6262+
for (const MCAsmMacroArgument &Arg : A) {
6263+
for (const AsmToken &Tok : Arg) {
6264+
if (Tok.is(AsmToken::String)) {
6265+
Res.append(Tok.getStringContents());
6266+
} else {
6267+
Res.append(Tok.getString());
6268+
}
6269+
}
6270+
}
6271+
return false;
6272+
}
6273+
}
6274+
llvm_unreachable("unhandled built-in function");
6275+
return true;
6276+
}
6277+
61986278
/// Create an MCAsmParser instance.
61996279
MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
62006280
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)