@@ -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.
61996279MCAsmParser *llvm::createMCMasmParser (SourceMgr &SM, MCContext &C,
62006280 MCStreamer &Out, const MCAsmInfo &MAI,
0 commit comments