@@ -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)
@@ -3197,6 +3220,18 @@ bool MasmParser::parseTextItem(std::string &Data) {
31973220 continue ;
31983221 }
31993222
3223+ // Try to resolve as a built-in macro function
3224+ auto BuiltinFuncIt = BuiltinFunctionMap.find (ID.lower ());
3225+ if (BuiltinFuncIt != BuiltinFunctionMap.end ()) {
3226+ Data.clear ();
3227+ if (evaluateBuiltinMacroFunction (BuiltinFuncIt->getValue (), ID, Data)) {
3228+ return true ;
3229+ }
3230+ ID = StringRef (Data);
3231+ Expanded = true ;
3232+ continue ;
3233+ }
3234+
32003235 // Try to resolve as a variable text macro
32013236 auto VarIt = Variables.find (ID.lower ());
32023237 if (VarIt != Variables.end ()) {
@@ -6204,7 +6239,7 @@ bool MasmParser::parseMSInlineAsm(
62046239 return false ;
62056240}
62066241
6207- void MasmParser::initializeBuiltinSymbolMap () {
6242+ void MasmParser::initializeBuiltinSymbolMaps () {
62086243 // Numeric built-ins (supported in all versions)
62096244 BuiltinSymbolMap[" @version" ] = BI_VERSION;
62106245 BuiltinSymbolMap[" @line" ] = BI_LINE;
@@ -6216,6 +6251,9 @@ void MasmParser::initializeBuiltinSymbolMap() {
62166251 BuiltinSymbolMap[" @filename" ] = BI_FILENAME;
62176252 BuiltinSymbolMap[" @curseg" ] = BI_CURSEG;
62186253
6254+ // Function built-ins (supported in all versions)
6255+ BuiltinFunctionMap[" @catstr" ] = BI_CATSTR;
6256+
62196257 // Some built-ins exist only for MASM32 (32-bit x86)
62206258 if (getContext ().getSubtargetInfo ()->getTargetTriple ().getArch () ==
62216259 Triple::x86) {
@@ -6289,6 +6327,48 @@ MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
62896327 llvm_unreachable (" unhandled built-in symbol" );
62906328}
62916329
6330+ bool MasmParser::evaluateBuiltinMacroFunction (BuiltinFunction Function,
6331+ StringRef Name,
6332+ std::string &Res) {
6333+ if (parseToken (AsmToken::LParen, " invoking macro function '" + Name +
6334+ " ' requires arguments in parentheses" )) {
6335+ return true ;
6336+ }
6337+
6338+ MCAsmMacroParameters P;
6339+ switch (Function) {
6340+ default :
6341+ return true ;
6342+ case BI_CATSTR:
6343+ break ;
6344+ }
6345+ MCAsmMacro M (Name, " " , P, {}, true );
6346+
6347+ MCAsmMacroArguments A;
6348+ if (parseMacroArguments (&M, A, AsmToken::RParen) || parseRParen ()) {
6349+ return true ;
6350+ }
6351+
6352+ switch (Function) {
6353+ default :
6354+ llvm_unreachable (" unhandled built-in function" );
6355+ case BI_CATSTR: {
6356+ for (const MCAsmMacroArgument &Arg : A) {
6357+ for (const AsmToken &Tok : Arg) {
6358+ if (Tok.is (AsmToken::String)) {
6359+ Res.append (Tok.getStringContents ());
6360+ } else {
6361+ Res.append (Tok.getString ());
6362+ }
6363+ }
6364+ }
6365+ return false ;
6366+ }
6367+ }
6368+ llvm_unreachable (" unhandled built-in function" );
6369+ return true ;
6370+ }
6371+
62926372// / Create an MCAsmParser instance.
62936373MCAsmParser *llvm::createMCMasmParser (SourceMgr &SM, MCContext &C,
62946374 MCStreamer &Out, const MCAsmInfo &MAI,
0 commit comments