75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
79struct MacroInstantiation {
81 SMLoc InstantiationLoc;
90 size_t CondStackDepth;
93struct ParseStatementInfo {
98 unsigned Opcode = ~0
U;
101 bool ParseError =
false;
104 std::optional<std::string> ExitValue;
106 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
108 ParseStatementInfo() =
delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
122 bool IsUnion =
false;
123 bool Initializable =
true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
128 std::vector<FieldInfo> Fields;
129 StringMap<size_t> FieldsByName;
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
134 StructInfo() =
default;
135 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
143struct StructInitializer;
147 IntFieldInfo() =
default;
151struct RealFieldInfo {
154 RealFieldInfo() =
default;
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
162 StructFieldInfo() =
default;
163 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
166class FieldInitializer {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
176 FieldInitializer(FieldType FT);
180 FieldInitializer(std::vector<StructInitializer> &&Initializers,
181 struct StructInfo Structure);
183 FieldInitializer(
const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
186 FieldInitializer &operator=(
const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
190struct StructInitializer {
191 std::vector<FieldInitializer> FieldInitializers;
202 unsigned LengthOf = 0;
207 FieldInitializer Contents;
209 FieldInfo(FieldType FT) : Contents(FT) {}
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
214 Initializers = std::move(V);
215 Structure = std::move(S);
218StructInfo::StructInfo(StringRef
StructName,
bool Union,
219 unsigned AlignmentValue)
222FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.
empty())
225 FieldsByName[FieldName.
lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &
Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
237FieldInitializer::~FieldInitializer() {
240 IntInfo.~IntFieldInfo();
243 RealInfo.~RealFieldInfo();
246 StructInfo.~StructFieldInfo();
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
254 new (&IntInfo) IntFieldInfo();
257 new (&RealInfo) RealFieldInfo();
260 new (&StructInfo) StructFieldInfo();
267 new (&IntInfo) IntFieldInfo(std::move(Values));
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
281FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312FieldInitializer::operator=(
const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
316 IntInfo.~IntFieldInfo();
319 RealInfo.~RealFieldInfo();
322 StructInfo.~StructFieldInfo();
329 IntInfo = Initializer.IntInfo;
332 RealInfo = Initializer.RealInfo;
335 StructInfo = Initializer.StructInfo;
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
345 IntInfo.~IntFieldInfo();
348 RealInfo.~RealFieldInfo();
351 StructInfo.~StructFieldInfo();
358 IntInfo = Initializer.IntInfo;
361 RealInfo = Initializer.RealInfo;
364 StructInfo = Initializer.StructInfo;
373class MasmParser :
public MCAsmParser {
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
386 BitVector EndStatementAtEOFStack;
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
401 RedefinableKind Redefinable = REDEFINABLE;
403 std::string TextValue;
405 StringMap<Variable> Variables;
411 StringMap<StructInfo> Structs;
414 StringMap<AsmTypeInfo> KnownType;
417 std::vector<MacroInstantiation*> ActiveMacros;
420 std::deque<MCAsmMacro> MacroLikeBodies;
423 unsigned NumOfMacroInstantiations;
426 struct CppHashInfoTy {
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
433 CppHashInfoTy CppHashInfo;
436 StringRef FirstCppHashFilename;
443 unsigned AssemblerDialect = 1U;
446 bool ParsingMSInlineAsm =
false;
449 unsigned AngleBracketDepth = 0
U;
452 uint16_t LocalCounter = 0;
455 MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
457 MasmParser(
const MasmParser &) =
delete;
458 MasmParser &operator=(
const MasmParser &) =
delete;
459 ~MasmParser()
override;
461 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler)
override {
465 ExtensionDirectiveMap[Directive] = std::move(Handler);
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
469 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
476 unsigned getAssemblerDialect()
override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
480 return AssemblerDialect;
482 void setAssemblerDialect(
unsigned i)
override {
483 AssemblerDialect = i;
486 void Note(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
487 bool Warning(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
488 bool printError(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
490 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
491 const AsmToken &Lex(ExpandKind ExpandNextToken);
492 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
494 void setParsingMSInlineAsm(
bool V)
override {
495 ParsingMSInlineAsm =
V;
498 Lexer.setLexMasmIntegers(V);
500 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
502 bool isParsingMasm()
const override {
return true; }
504 bool defineMacro(StringRef Name, StringRef
Value)
override;
506 bool lookUpField(StringRef Name, AsmFieldInfo &Info)
const override;
507 bool lookUpField(StringRef
Base, StringRef Member,
508 AsmFieldInfo &Info)
const override;
510 bool lookUpType(StringRef Name, AsmTypeInfo &Info)
const override;
512 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
514 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
515 SmallVectorImpl<std::string> &Constraints,
516 SmallVectorImpl<std::string> &Clobbers,
517 const MCInstrInfo *MII, MCInstPrinter *IP,
518 MCAsmParserSemaCallback &SI)
override;
520 bool parseExpression(
const MCExpr *&Res);
521 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
522 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
523 AsmTypeInfo *TypeInfo)
override;
524 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
525 bool parseAbsoluteExpression(int64_t &Res)
override;
529 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
533 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
534 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
535 bool parseIdentifier(StringRef &Res)
override {
536 return parseIdentifier(Res, StandardPosition);
538 void eatToEndOfStatement()
override;
540 bool checkForValidSection()
override;
546 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
548 bool parseStatement(ParseStatementInfo &Info,
549 MCAsmParserSemaCallback *SI);
550 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
551 bool parseCppHashLineFilenameComment(SMLoc L);
553 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
556 const std::vector<std::string> &Locals, SMLoc L);
559 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
565 bool handleMacroEntry(
566 const MCAsmMacro *M, SMLoc NameLoc,
573 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
576 void handleMacroExit();
580 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
585 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
588 void printMacroInstantiations();
590 bool expandStatement(SMLoc Loc);
593 SMRange
Range = {})
const {
599 bool lookUpField(
const StructInfo &Structure, StringRef Member,
600 AsmFieldInfo &Info)
const;
603 bool enterIncludeFile(
const std::string &
Filename);
611 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
612 bool EndStatementAtEOF =
true);
624 StringRef parseStringToEndOfStatement()
override;
626 bool parseTextItem(std::string &
Data);
631 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
632 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
633 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
638 DK_HANDLER_DIRECTIVE,
729 StringMap<DirectiveKind> DirectiveKindMap;
731 bool isMacroLikeDirective();
758 StringMap<BuiltinSymbol> BuiltinSymbolMap;
760 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
762 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
766 enum BuiltinFunction {
773 StringMap<BuiltinFunction> BuiltinFunctionMap;
775 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
779 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
782 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
783 bool parseScalarInitializer(
unsigned Size,
784 SmallVectorImpl<const MCExpr *> &Values,
785 unsigned StringPadLength = 0);
786 bool parseScalarInstList(
787 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
789 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
790 bool addIntegralField(StringRef Name,
unsigned Size);
791 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
792 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
793 StringRef Name, SMLoc NameLoc);
796 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
797 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
798 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
800 bool parseRealInstList(
801 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
803 bool parseDirectiveNamedRealValue(StringRef TypeName,
804 const fltSemantics &Semantics,
805 unsigned Size, StringRef Name,
808 bool parseOptionalAngleBracketOpen();
809 bool parseAngleBracketClose(
const Twine &Msg =
"expected '>'");
811 bool parseFieldInitializer(
const FieldInfo &
Field,
812 FieldInitializer &Initializer);
813 bool parseFieldInitializer(
const FieldInfo &
Field,
814 const IntFieldInfo &Contents,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(
const FieldInfo &
Field,
817 const RealFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(
const FieldInfo &
Field,
820 const StructFieldInfo &Contents,
821 FieldInitializer &Initializer);
823 bool parseStructInitializer(
const StructInfo &Structure,
824 StructInitializer &Initializer);
825 bool parseStructInstList(
826 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
829 bool emitFieldValue(
const FieldInfo &
Field);
830 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
831 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
832 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
834 bool emitFieldInitializer(
const FieldInfo &
Field,
835 const FieldInitializer &Initializer);
836 bool emitFieldInitializer(
const FieldInfo &
Field,
837 const IntFieldInfo &Contents,
838 const IntFieldInfo &Initializer);
839 bool emitFieldInitializer(
const FieldInfo &
Field,
840 const RealFieldInfo &Contents,
841 const RealFieldInfo &Initializer);
842 bool emitFieldInitializer(
const FieldInfo &
Field,
843 const StructFieldInfo &Contents,
844 const StructFieldInfo &Initializer);
846 bool emitStructInitializer(
const StructInfo &Structure,
847 const StructInitializer &Initializer);
850 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
851 bool addStructField(StringRef Name,
const StructInfo &Structure);
852 bool parseDirectiveStructValue(
const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc);
854 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
855 StringRef Directive, SMLoc DirLoc,
859 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
860 DirectiveKind DirKind, SMLoc NameLoc);
862 bool parseDirectiveOrg();
864 bool emitAlignTo(int64_t Alignment);
865 bool parseDirectiveAlign();
866 bool parseDirectiveEven();
869 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
870 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
872 bool parseDirectiveEndMacro(StringRef Directive);
873 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
875 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
876 StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
878 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
879 bool parseDirectiveNestedEnds();
881 bool parseDirectiveExtern();
887 bool parseDirectiveComm(
bool IsLocal);
889 bool parseDirectiveComment(SMLoc DirectiveLoc);
891 bool parseDirectiveInclude();
894 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
896 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
899 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
900 bool CaseInsensitive);
902 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
904 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
906 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
908 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
911 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
912 bool CaseInsensitive);
913 bool parseDirectiveElse(SMLoc DirectiveLoc);
914 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
915 bool parseEscapedString(std::string &
Data)
override;
916 bool parseAngleBracketString(std::string &
Data)
override;
919 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 raw_svector_ostream &OS);
922 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
923 SMLoc ExitLoc, raw_svector_ostream &OS);
924 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
926 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveWhile(SMLoc DirectiveLoc);
930 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
934 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
937 bool parseDirectiveEnd(SMLoc DirectiveLoc);
940 bool parseDirectiveError(SMLoc DirectiveLoc);
942 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
944 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
947 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
948 bool CaseInsensitive);
950 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
953 bool parseDirectiveRadix(SMLoc DirectiveLoc);
956 bool parseDirectiveEcho(SMLoc DirectiveLoc);
958 void initializeDirectiveKindMap();
959 void initializeBuiltinSymbolMaps();
972MasmParser::MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
973 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
974 : MCAsmParser(Ctx, Out,
SM, MAI), CurBuffer(CB ? CB :
SM.getMainFileID()),
978 SavedDiagHandler =
SrcMgr.getDiagHandler();
979 SavedDiagContext =
SrcMgr.getDiagContext();
982 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
983 EndStatementAtEOFStack.push_back(
true);
986 switch (Ctx.getObjectFileType()) {
987 case MCContext::IsCOFF:
988 PlatformParser.reset(createCOFFMasmParser());
991 report_fatal_error(
"llvm-ml currently supports only COFF output.");
995 initializeDirectiveKindMap();
996 PlatformParser->Initialize(*
this);
997 initializeBuiltinSymbolMaps();
999 NumOfMacroInstantiations = 0;
1002MasmParser::~MasmParser() {
1003 assert((HadError || ActiveMacros.empty()) &&
1004 "Unexpected active macro instantiation!");
1011void MasmParser::printMacroInstantiations() {
1013 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1014 it = ActiveMacros.rbegin(),
1015 ie = ActiveMacros.rend();
1018 "while in macro instantiation");
1021void MasmParser::Note(SMLoc L,
const Twine &Msg, SMRange
Range) {
1022 printPendingErrors();
1024 printMacroInstantiations();
1027bool MasmParser::Warning(SMLoc L,
const Twine &Msg, SMRange
Range) {
1028 if (getTargetParser().getTargetOptions().MCNoWarn)
1030 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1033 printMacroInstantiations();
1037bool MasmParser::printError(SMLoc L,
const Twine &Msg, SMRange
Range) {
1040 printMacroInstantiations();
1044bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1045 std::string IncludedFile;
1053 EndStatementAtEOFStack.push_back(
true);
1057void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1058 bool EndStatementAtEOF) {
1064bool MasmParser::expandMacros() {
1065 const AsmToken &Tok = getTok();
1068 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1071 const SMLoc MacroLoc = Tok.
getLoc();
1074 if (handleMacroInvocation(M, MacroLoc)) {
1081 std::optional<std::string> ExpandedValue;
1083 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1084 BuiltinIt != BuiltinSymbolMap.end()) {
1086 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1087 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1088 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1090 if (parseIdentifier(Name)) {
1094 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1097 ExpandedValue = Res;
1098 }
else if (
auto VarIt = Variables.
find(IDLower);
1099 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1100 ExpandedValue = VarIt->getValue().TextValue;
1105 std::unique_ptr<MemoryBuffer> Instantiation =
1113 EndStatementAtEOFStack.push_back(
false);
1118const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1120 Error(Lexer.getErrLoc(), Lexer.getErr());
1121 bool StartOfStatement =
false;
1126 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1129 StartOfStatement =
true;
1132 const AsmToken *tok = &Lexer.Lex();
1135 if (StartOfStatement) {
1138 size_t ReadCount = Lexer.peekTokens(Buf);
1170 if (ParentIncludeLoc != SMLoc()) {
1171 EndStatementAtEOFStack.pop_back();
1172 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1175 EndStatementAtEOFStack.pop_back();
1176 assert(EndStatementAtEOFStack.empty());
1182const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1186 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1188 if (ReadCount == 0) {
1192 if (ParentIncludeLoc != SMLoc()) {
1193 EndStatementAtEOFStack.pop_back();
1194 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1195 return peekTok(ShouldSkipSpace);
1197 EndStatementAtEOFStack.pop_back();
1198 assert(EndStatementAtEOFStack.empty());
1205bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1207 if (!NoInitialTextSection)
1214 AsmCond StartingCondState = TheCondState;
1224 ParseStatementInfo
Info(&AsmStrRewrites);
1225 bool HasError = parseStatement(Info,
nullptr);
1230 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1234 printPendingErrors();
1237 if (HasError && !getLexer().justConsumedEOL())
1238 eatToEndOfStatement();
1241 printPendingErrors();
1244 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1248 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1257 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1258 if (std::get<2>(LocSym)->isUndefined()) {
1261 CppHashInfo = std::get<1>(LocSym);
1262 printError(std::get<0>(LocSym),
"directional label undefined");
1269 if (!HadError && !NoFinalize)
1270 Out.
finish(Lexer.getLoc());
1275bool MasmParser::checkForValidSection() {
1276 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1277 getStreamer().getCurrentSectionOnly())) {
1279 return Error(getTok().getLoc(),
1280 "expected section directive before assembly directive");
1286void MasmParser::eatToEndOfStatement() {
1290 if (ParentIncludeLoc == SMLoc()) {
1294 EndStatementAtEOFStack.pop_back();
1295 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1306SmallVector<StringRef, 1>
1308 SmallVector<StringRef, 1> Refs;
1309 const char *
Start = getTok().getLoc().getPointer();
1310 while (Lexer.isNot(EndTok)) {
1313 if (ParentIncludeLoc == SMLoc()) {
1318 EndStatementAtEOFStack.pop_back();
1319 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1321 Start = getTok().getLoc().getPointer();
1331 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1333 for (StringRef S : Refs) {
1334 Str.append(S.str());
1339StringRef MasmParser::parseStringToEndOfStatement() {
1340 const char *
Start = getTok().getLoc().getPointer();
1345 const char *End = getTok().getLoc().getPointer();
1346 return StringRef(Start, End - Start);
1354bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1355 if (parseExpression(Res))
1357 EndLoc = Lexer.getTok().getEndLoc();
1358 return parseRParen();
1366bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1367 if (parseExpression(Res))
1369 EndLoc = getTok().getEndLoc();
1370 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1383bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1384 AsmTypeInfo *TypeInfo) {
1385 SMLoc FirstTokenLoc = getLexer().getLoc();
1387 switch (FirstTokenKind) {
1389 return TokError(
"unknown token in expression");
1395 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1403 if (parseIdentifier(Identifier)) {
1406 if (Lexer.getMAI().getDollarIsPC()) {
1413 EndLoc = FirstTokenLoc;
1416 return Error(FirstTokenLoc,
"invalid token in expression");
1421 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1429 bool Before =
Identifier.equals_insensitive(
"@b");
1432 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1442 return Error(getLexer().getLoc(),
"expected a symbol reference");
1447 if (
Split.second.empty()) {
1450 if (lookUpField(SymbolName,
Split.second, Info)) {
1451 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1452 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1453 lookUpField(
Base, Member, Info);
1464 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1465 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1467 : BuiltinIt->getValue();
1468 if (Symbol != BI_NO_SYMBOL) {
1469 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1479 if (VarIt != Variables.
end())
1490 DoInline = TV->inlineAssignedExpr();
1498 const MCExpr *SymRef =
1508 if (
Info.Type.Name.empty()) {
1510 if (TypeIt != KnownType.
end()) {
1511 Info.Type = TypeIt->second;
1515 *TypeInfo =
Info.Type;
1520 return TokError(
"literal value out of range for directive");
1522 int64_t
IntVal = getTok().getIntVal();
1524 EndLoc = Lexer.getTok().getEndLoc();
1530 SMLoc ValueLoc = getTok().getLoc();
1532 if (parseEscapedString(
Value))
1534 if (
Value.size() > 8)
1535 return Error(ValueLoc,
"literal value out of range");
1536 uint64_t IntValue = 0;
1537 for (
const unsigned char CharVal :
Value)
1538 IntValue = (IntValue << 8) | CharVal;
1543 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1544 uint64_t
IntVal = RealVal.bitcastToAPInt().getZExtValue();
1546 EndLoc = Lexer.getTok().getEndLoc();
1556 EndLoc = Lexer.getTok().getEndLoc();
1562 return parseParenExpr(Res, EndLoc);
1564 if (!PlatformParser->HasBracketExpressions())
1565 return TokError(
"brackets expression not supported on this target");
1567 return parseBracketExpr(Res, EndLoc);
1570 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1576 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1582 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1589bool MasmParser::parseExpression(
const MCExpr *&Res) {
1591 return parseExpression(Res, EndLoc);
1602 "Argument to the function cannot be a NULL value");
1604 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1605 (*CharPtr !=
'\0')) {
1606 if (*CharPtr ==
'!')
1610 if (*CharPtr ==
'>') {
1620 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1621 if (BracketContents[Pos] ==
'!')
1623 Res += BracketContents[Pos];
1638bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1641 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1642 parseBinOpRHS(1, Res, EndLoc))
1648 if (Res->evaluateAsAbsolute(
Value))
1654bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1656 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1659bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1662 SMLoc StartLoc = Lexer.getLoc();
1663 if (parseExpression(Expr))
1666 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1667 return Error(StartLoc,
"expected absolute expression");
1674 bool ShouldUseLogicalShr,
1675 bool EndExpressionAtGreater) {
1703 if (EndExpressionAtGreater)
1744 if (EndExpressionAtGreater)
1755 AngleBracketDepth > 0);
1760bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1762 SMLoc StartLoc = Lexer.getLoc();
1766 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1782 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1786 if (TokPrec < Precedence)
1793 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1799 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1800 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1813bool MasmParser::parseStatement(ParseStatementInfo &Info,
1814 MCAsmParserSemaCallback *SI) {
1815 assert(!hasPendingError() &&
"parseStatement started with pending error");
1821 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1822 getTok().getString().
front() ==
'\n')
1831 SMLoc ExpansionLoc = getTok().getLoc();
1838 AsmToken
ID = getTok();
1839 SMLoc IDLoc =
ID.getLoc();
1842 return parseCppHashLineFilenameComment(IDLoc);
1849 IDVal = getTok().getString();
1852 return Error(IDLoc,
"unexpected token at start of statement");
1853 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1854 if (!TheCondState.
Ignore) {
1856 return Error(IDLoc,
"unexpected token at start of statement");
1865 DirectiveKindMap.find(IDVal.
lower());
1866 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1868 : DirKindIt->getValue();
1874 return parseDirectiveIf(IDLoc, DirKind);
1876 return parseDirectiveIfb(IDLoc,
true);
1878 return parseDirectiveIfb(IDLoc,
false);
1880 return parseDirectiveIfdef(IDLoc,
true);
1882 return parseDirectiveIfdef(IDLoc,
false);
1884 return parseDirectiveIfidn(IDLoc,
false,
1887 return parseDirectiveIfidn(IDLoc,
false,
1890 return parseDirectiveIfidn(IDLoc,
true,
1893 return parseDirectiveIfidn(IDLoc,
true,
1897 return parseDirectiveElseIf(IDLoc, DirKind);
1899 return parseDirectiveElseIfb(IDLoc,
true);
1901 return parseDirectiveElseIfb(IDLoc,
false);
1903 return parseDirectiveElseIfdef(IDLoc,
true);
1905 return parseDirectiveElseIfdef(IDLoc,
false);
1907 return parseDirectiveElseIfidn(IDLoc,
false,
1910 return parseDirectiveElseIfidn(IDLoc,
false,
1913 return parseDirectiveElseIfidn(IDLoc,
true,
1916 return parseDirectiveElseIfidn(IDLoc,
true,
1919 return parseDirectiveElse(IDLoc);
1921 return parseDirectiveEndIf(IDLoc);
1926 if (TheCondState.
Ignore) {
1927 eatToEndOfStatement();
1937 if (checkForValidSection())
1945 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1953 if (ParsingMSInlineAsm && SI) {
1954 StringRef RewrittenLabel =
1955 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1957 "We should have an internal name here.");
1960 IDVal = RewrittenLabel;
1963 if (IDVal ==
"@@") {
1986 if (!getTargetParser().isParsingMSInlineAsm())
1996 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2001 if (DirKind != DK_NO_DIRECTIVE) {
2017 return parseDirectiveNestedEnds();
2022 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2025 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2031 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(
ID);
2033 "Should only return Failure iff there was an error");
2045 return parseDirectiveAscii(IDVal,
false);
2048 return parseDirectiveAscii(IDVal,
true);
2052 return parseDirectiveValue(IDVal, 1);
2056 return parseDirectiveValue(IDVal, 2);
2060 return parseDirectiveValue(IDVal, 4);
2063 return parseDirectiveValue(IDVal, 6);
2067 return parseDirectiveValue(IDVal, 8);
2069 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2071 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2073 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2076 return parseDirectiveNestedStruct(IDVal, DirKind);
2078 return parseDirectiveNestedEnds();
2080 return parseDirectiveAlign();
2082 return parseDirectiveEven();
2084 return parseDirectiveOrg();
2086 return parseDirectiveExtern();
2088 return parseDirectiveSymbolAttribute(
MCSA_Global);
2090 return parseDirectiveComm(
false);
2092 return parseDirectiveComment(IDLoc);
2094 return parseDirectiveInclude();
2096 return parseDirectiveRepeat(IDLoc, IDVal);
2098 return parseDirectiveWhile(IDLoc);
2100 return parseDirectiveFor(IDLoc, IDVal);
2102 return parseDirectiveForc(IDLoc, IDVal);
2104 Info.ExitValue =
"";
2105 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2107 Info.ExitValue =
"";
2108 return parseDirectiveEndMacro(IDVal);
2110 return parseDirectivePurgeMacro(IDLoc);
2112 return parseDirectiveEnd(IDLoc);
2114 return parseDirectiveError(IDLoc);
2116 return parseDirectiveErrorIfb(IDLoc,
true);
2118 return parseDirectiveErrorIfb(IDLoc,
false);
2120 return parseDirectiveErrorIfdef(IDLoc,
true);
2122 return parseDirectiveErrorIfdef(IDLoc,
false);
2124 return parseDirectiveErrorIfidn(IDLoc,
false,
2127 return parseDirectiveErrorIfidn(IDLoc,
false,
2130 return parseDirectiveErrorIfidn(IDLoc,
true,
2133 return parseDirectiveErrorIfidn(IDLoc,
true,
2136 return parseDirectiveErrorIfe(IDLoc,
true);
2138 return parseDirectiveErrorIfe(IDLoc,
false);
2140 return parseDirectiveRadix(IDLoc);
2142 return parseDirectiveEcho(IDLoc);
2145 return Error(IDLoc,
"unknown directive");
2149 auto IDIt = Structs.
find(IDVal.
lower());
2150 if (IDIt != Structs.
end())
2151 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2155 const AsmToken nextTok = getTok();
2156 const StringRef nextVal = nextTok.
getString();
2157 const SMLoc nextLoc = nextTok.
getLoc();
2159 const AsmToken afterNextTok = peekTok();
2170 getTargetParser().flushPendingInstructions(getStreamer());
2176 return parseDirectiveEnds(IDVal, IDLoc);
2181 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2183 if (Handler.first) {
2186 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2191 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2192 DirKind = (DirKindIt == DirectiveKindMap.end())
2194 : DirKindIt->getValue();
2202 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2213 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2224 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2235 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2245 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2256 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2259 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2263 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2267 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2272 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2275 return parseDirectiveEnds(IDVal, IDLoc);
2278 return parseDirectiveMacro(IDVal, IDLoc);
2282 auto NextIt = Structs.
find(nextVal.
lower());
2283 if (NextIt != Structs.
end()) {
2285 return parseDirectiveNamedStructValue(NextIt->getValue(),
2286 nextVal, nextLoc, IDVal);
2290 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2291 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2292 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2295 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2296 return parseDirectiveMSAlign(IDLoc, Info);
2298 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2300 if (checkForValidSection())
2304 std::string OpcodeStr = IDVal.
lower();
2305 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2306 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr,
ID,
2307 Info.ParsedOperands);
2308 Info.ParseError = ParseHadError;
2311 if (getShowParsedOperands()) {
2312 SmallString<256> Str;
2313 raw_svector_ostream OS(Str);
2314 OS <<
"parsed instruction: [";
2315 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2318 Info.ParsedOperands[i]->print(OS, MAI);
2326 if (hasPendingError() || ParseHadError)
2330 if (!ParseHadError) {
2332 if (getTargetParser().matchAndEmitInstruction(
2333 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2334 getTargetParser().isParsingMSInlineAsm()))
2341bool MasmParser::parseCurlyBlockScope(
2342 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2347 SMLoc StartLoc = Lexer.getLoc();
2360bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2365 "Lexing Cpp line comment: Expected Integer");
2366 int64_t LineNumber = getTok().getIntVal();
2369 "Lexing Cpp line comment: Expected String");
2370 StringRef
Filename = getTok().getString();
2378 CppHashInfo.Loc =
L;
2380 CppHashInfo.LineNumber = LineNumber;
2381 CppHashInfo.Buf = CurBuffer;
2382 if (FirstCppHashFilename.
empty())
2389void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2390 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2391 raw_ostream &OS =
errs();
2394 SMLoc DiagLoc = Diag.
getLoc();
2396 unsigned CppHashBuf =
2397 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2402 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2411 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2412 DiagBuf != CppHashBuf) {
2413 if (Parser->SavedDiagHandler)
2414 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2416 Diag.
print(
nullptr, OS);
2423 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2426 int CppHashLocLineNo =
2427 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2429 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2435 if (Parser->SavedDiagHandler)
2436 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2438 NewDiag.print(
nullptr, OS);
2444 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2447bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2450 const std::vector<std::string> &Locals, SMLoc L) {
2452 if (NParameters !=
A.size())
2453 return Error(L,
"Wrong number of arguments");
2454 StringMap<std::string> LocalSymbols;
2457 for (StringRef
Local : Locals) {
2458 raw_string_ostream LocalName(Name);
2465 std::optional<char> CurrentQuote;
2466 while (!Body.
empty()) {
2468 std::size_t End = Body.
size(), Pos = 0;
2469 std::size_t IdentifierPos = End;
2470 for (; Pos != End; ++Pos) {
2473 if (Body[Pos] ==
'&')
2478 if (IdentifierPos == End)
2479 IdentifierPos = Pos;
2481 IdentifierPos = End;
2485 if (!CurrentQuote) {
2486 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2487 CurrentQuote = Body[Pos];
2488 }
else if (Body[Pos] == CurrentQuote) {
2489 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2494 CurrentQuote.reset();
2498 if (IdentifierPos != End) {
2501 Pos = IdentifierPos;
2502 IdentifierPos = End;
2506 OS << Body.
slice(0, Pos);
2513 bool InitialAmpersand = (Body[
I] ==
'&');
2514 if (InitialAmpersand) {
2521 const char *Begin = Body.
data() + Pos;
2523 const std::string ArgumentLower =
Argument.lower();
2527 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2530 if (Index == NParameters) {
2531 if (InitialAmpersand)
2533 auto it = LocalSymbols.
find(ArgumentLower);
2534 if (it != LocalSymbols.
end())
2540 for (
const AsmToken &Token :
A[Index]) {
2550 OS << Token.getIntVal();
2552 OS << Token.getString();
2556 if (Pos < End && Body[Pos] ==
'&') {
2567bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2568 MCAsmMacroArgument &MA,
2571 if (Lexer.isNot(EndTok)) {
2572 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2573 for (StringRef S : Str) {
2580 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2582 const char *StrChar = StrLoc.
getPointer() + 1;
2583 const char *EndChar = EndLoc.
getPointer() - 1;
2584 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2591 unsigned ParenLevel = 0;
2595 return TokError(
"unexpected token");
2612 MA.push_back(getTok());
2616 if (ParenLevel != 0)
2617 return TokError(
"unbalanced parentheses in argument");
2619 if (MA.empty() && MP) {
2621 return TokError(
"missing value for required parameter '" + MP->
Name +
2631bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2632 MCAsmMacroArguments &
A,
2634 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2635 bool NamedParametersFound =
false;
2636 SmallVector<SMLoc, 4> FALocs;
2638 A.resize(NParameters);
2639 FALocs.
resize(NParameters);
2644 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2646 SMLoc IDLoc = Lexer.getLoc();
2647 MCAsmMacroParameter FA;
2650 if (parseIdentifier(FA.
Name))
2651 return Error(IDLoc,
"invalid argument identifier for formal argument");
2654 return TokError(
"expected '=' after formal parameter identifier");
2658 NamedParametersFound =
true;
2661 if (NamedParametersFound && FA.
Name.
empty())
2662 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2666 assert(M &&
"expected macro to be defined");
2668 for (FAI = 0; FAI < NParameters; ++FAI)
2669 if (
M->Parameters[FAI].Name == FA.
Name)
2672 if (FAI >= NParameters) {
2673 return Error(IDLoc,
"parameter named '" + FA.
Name +
2674 "' does not exist for macro '" +
M->Name +
"'");
2678 const MCAsmMacroParameter *MP =
nullptr;
2679 if (M && PI < NParameters)
2680 MP = &
M->Parameters[PI];
2682 SMLoc StrLoc = Lexer.getLoc();
2685 const MCExpr *AbsoluteExp;
2689 if (parseExpression(AbsoluteExp, EndLoc))
2691 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2692 getStreamer().getAssemblerPtr()))
2693 return Error(StrLoc,
"expected absolute expression");
2697 StringRef(StrChar, EndChar - StrChar),
Value);
2698 FA.
Value.push_back(newToken);
2699 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2701 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2706 if (!FA.
Value.empty()) {
2711 if (FALocs.
size() <= PI)
2714 FALocs[PI] = Lexer.getLoc();
2720 if (Lexer.is(EndTok)) {
2722 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2724 if (
M->Parameters[FAI].Required) {
2725 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2726 "missing value for required parameter "
2728 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2732 if (!
M->Parameters[FAI].Value.empty())
2733 A[FAI] =
M->Parameters[FAI].Value;
2743 return TokError(
"too many positional arguments");
2746bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2751 if (ActiveMacros.size() == MaxNestingDepth) {
2752 std::ostringstream MaxNestingDepthError;
2753 MaxNestingDepthError <<
"macros cannot be nested more than "
2754 << MaxNestingDepth <<
" levels deep."
2755 <<
" Use -asm-macro-max-nesting-depth to increase "
2757 return TokError(MaxNestingDepthError.str());
2760 MCAsmMacroArguments
A;
2761 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2766 SmallString<256> Buf;
2767 StringRef Body =
M->Body;
2768 raw_svector_ostream OS(Buf);
2770 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2777 std::unique_ptr<MemoryBuffer> Instantiation =
2782 MacroInstantiation *
MI =
new MacroInstantiation{
2783 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2784 ActiveMacros.push_back(
MI);
2786 ++NumOfMacroInstantiations;
2791 EndStatementAtEOFStack.push_back(
true);
2797void MasmParser::handleMacroExit() {
2799 EndStatementAtEOFStack.pop_back();
2800 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2801 EndStatementAtEOFStack.back());
2805 delete ActiveMacros.back();
2806 ActiveMacros.pop_back();
2809bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2811 return Error(NameLoc,
"cannot invoke macro procedure as function");
2814 "' requires arguments in parentheses") ||
2819 std::string ExitValue;
2822 ParseStatementInfo
Info(&AsmStrRewrites);
2823 bool HasError = parseStatement(Info,
nullptr);
2825 if (!HasError &&
Info.ExitValue) {
2826 ExitValue = std::move(*
Info.ExitValue);
2833 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2837 printPendingErrors();
2840 if (HasError && !getLexer().justConsumedEOL())
2841 eatToEndOfStatement();
2846 std::unique_ptr<MemoryBuffer> MacroValue =
2854 EndStatementAtEOFStack.push_back(
false);
2863bool MasmParser::parseIdentifier(StringRef &Res,
2864 IdentifierPositionKind Position) {
2871 SMLoc PrefixLoc = getLexer().getLoc();
2875 AsmToken nextTok = peekTok(
false);
2888 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2896 Res = getTok().getIdentifier();
2900 ExpandKind ExpandNextToken = ExpandMacros;
2901 if (Position == StartOfStatement &&
2902 StringSwitch<bool>(Res)
2903 .CaseLower(
"echo",
true)
2904 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2906 ExpandNextToken = DoNotExpandMacros;
2908 Lex(ExpandNextToken);
2918bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2919 DirectiveKind DirKind, SMLoc NameLoc) {
2920 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2921 if (BuiltinIt != BuiltinSymbolMap.end())
2922 return Error(NameLoc,
"cannot redefine a built-in symbol");
2925 if (Var.Name.empty()) {
2929 SMLoc StartLoc = Lexer.getLoc();
2930 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2933 std::string TextItem;
2934 if (!parseTextItem(TextItem)) {
2938 auto parseItem = [&]() ->
bool {
2939 if (parseTextItem(TextItem))
2940 return TokError(
"expected text item");
2945 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2947 if (!Var.IsText || Var.TextValue !=
Value) {
2948 switch (Var.Redefinable) {
2949 case Variable::NOT_REDEFINABLE:
2950 return Error(getTok().getLoc(),
"invalid variable redefinition");
2951 case Variable::WARN_ON_REDEFINITION:
2952 if (
Warning(NameLoc,
"redefining '" + Name +
2953 "', already defined on the command line")) {
2962 Var.TextValue =
Value;
2963 Var.Redefinable = Variable::REDEFINABLE;
2968 if (DirKind == DK_TEXTEQU)
2969 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2974 if (parseExpression(Expr, EndLoc))
2975 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2976 StringRef ExprAsString = StringRef(
2980 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2981 if (DirKind == DK_ASSIGN)
2984 "expected absolute expression; not all symbols have known values",
2985 {StartLoc, EndLoc});
2988 if (!Var.IsText || Var.TextValue != ExprAsString) {
2989 switch (Var.Redefinable) {
2990 case Variable::NOT_REDEFINABLE:
2991 return Error(getTok().getLoc(),
"invalid variable redefinition");
2992 case Variable::WARN_ON_REDEFINITION:
2993 if (
Warning(NameLoc,
"redefining '" + Name +
2994 "', already defined on the command line")) {
3004 Var.TextValue = ExprAsString.
str();
3005 Var.Redefinable = Variable::REDEFINABLE;
3010 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
3011 const MCConstantExpr *PrevValue =
3015 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
3016 switch (Var.Redefinable) {
3017 case Variable::NOT_REDEFINABLE:
3018 return Error(getTok().getLoc(),
"invalid variable redefinition");
3019 case Variable::WARN_ON_REDEFINITION:
3020 if (
Warning(NameLoc,
"redefining '" + Name +
3021 "', already defined on the command line")) {
3031 Var.TextValue.clear();
3032 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3035 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3037 Sym->setExternal(
false);
3042bool MasmParser::parseEscapedString(std::string &
Data) {
3047 char Quote = getTok().getString().front();
3048 StringRef Str = getTok().getStringContents();
3049 Data.reserve(Str.size());
3050 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3051 Data.push_back(Str[i]);
3052 if (Str[i] == Quote) {
3056 if (i + 1 == Str.size())
3057 return Error(getTok().getLoc(),
"missing quotation mark in string");
3058 if (Str[i + 1] == Quote)
3067bool MasmParser::parseAngleBracketString(std::string &
Data) {
3068 SMLoc EndLoc, StartLoc = getTok().getLoc();
3070 const char *StartChar = StartLoc.
getPointer() + 1;
3071 const char *EndChar = EndLoc.
getPointer() - 1;
3072 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3083bool MasmParser::parseTextItem(std::string &
Data) {
3084 switch (getTok().getKind()) {
3091 Data = std::to_string(Res);
3098 return parseAngleBracketString(
Data);
3102 SMLoc StartLoc = getTok().getLoc();
3103 if (parseIdentifier(
ID))
3107 bool Expanded =
false;
3110 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3111 if (BuiltinIt != BuiltinSymbolMap.end()) {
3112 std::optional<std::string> BuiltinText =
3113 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3118 Data = std::move(*BuiltinText);
3125 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3126 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3128 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(),
ID,
Data)) {
3137 auto VarIt = Variables.
find(
ID.lower());
3138 if (VarIt != Variables.
end()) {
3139 const Variable &Var = VarIt->getValue();
3144 Data = Var.TextValue;
3167bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3168 auto parseOp = [&]() ->
bool {
3170 if (checkForValidSection() || parseEscapedString(
Data))
3172 getStreamer().emitBytes(
Data);
3174 getStreamer().emitBytes(StringRef(
"\0", 1));
3178 if (parseMany(parseOp))
3179 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3183bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3187 int64_t IntValue = MCE->getValue();
3189 return Error(MCE->getLoc(),
"out of range literal value");
3190 getStreamer().emitIntValue(IntValue,
Size);
3195 getStreamer().emitIntValue(0,
Size);
3203bool MasmParser::parseScalarInitializer(
unsigned Size,
3204 SmallVectorImpl<const MCExpr *> &Values,
3205 unsigned StringPadLength) {
3208 if (parseEscapedString(
Value))
3211 for (
const unsigned char CharVal :
Value)
3215 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3218 const MCExpr *
Value;
3219 if (parseExpression(
Value))
3222 getTok().getString().equals_insensitive(
"dup")) {
3227 "cannot repeat value a non-constant number of times");
3228 const int64_t Repetitions = MCE->
getValue();
3229 if (Repetitions < 0)
3231 "cannot repeat value a negative number of times");
3235 "parentheses required for 'dup' contents") ||
3236 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3239 for (
int i = 0; i < Repetitions; ++i)
3248bool MasmParser::parseScalarInstList(
unsigned Size,
3249 SmallVectorImpl<const MCExpr *> &Values,
3251 while (getTok().
isNot(EndToken) &&
3254 parseScalarInitializer(
Size, Values);
3264bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3266 if (checkForValidSection() || parseScalarInstList(
Size, Values))
3269 for (
const auto *
Value : Values) {
3273 *
Count = Values.size();
3278bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3279 StructInfo &
Struct = StructInProgress.
back();
3281 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3285 if (parseScalarInstList(
Size, IntInfo.Values))
3288 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3289 Field.LengthOf = IntInfo.Values.size();
3292 Struct.NextOffset = FieldEnd;
3300bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3301 if (StructInProgress.
empty()) {
3303 if (emitIntegralValues(
Size))
3304 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3305 }
else if (addIntegralField(
"",
Size)) {
3306 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3314bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3315 StringRef Name, SMLoc NameLoc) {
3316 if (StructInProgress.
empty()) {
3319 getStreamer().emitLabel(Sym);
3322 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3330 }
else if (addIntegralField(Name,
Size)) {
3331 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3337bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3343 SignLoc = getLexer().getLoc();
3347 SignLoc = getLexer().getLoc();
3352 return TokError(Lexer.getErr());
3355 return TokError(
"unexpected token in directive");
3359 StringRef IDVal = getTok().getString();
3368 return TokError(
"invalid floating point literal");
3372 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3373 if (SizeInBits != (IDVal.
size() << 2))
3374 return TokError(
"invalid floating point literal");
3379 Res = APInt(SizeInBits, IDVal, 16);
3381 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3384 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3386 return TokError(
"invalid floating point literal");
3394 Res =
Value.bitcastToAPInt();
3399bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3400 SmallVectorImpl<APInt> &ValuesAsInt,
3402 while (getTok().
isNot(EndToken) ||
3405 const AsmToken NextTok = peekTok();
3408 const MCExpr *
Value;
3414 "cannot repeat value a non-constant number of times");
3415 const int64_t Repetitions = MCE->
getValue();
3416 if (Repetitions < 0)
3418 "cannot repeat value a negative number of times");
3422 "parentheses required for 'dup' contents") ||
3423 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3426 for (
int i = 0; i < Repetitions; ++i)
3427 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3430 if (parseRealValue(Semantics, AsInt))
3445bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3447 if (checkForValidSection())
3451 if (parseRealInstList(Semantics, ValuesAsInt))
3454 for (
const APInt &AsInt : ValuesAsInt) {
3455 getStreamer().emitIntValue(AsInt);
3458 *
Count = ValuesAsInt.size();
3463bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3465 StructInfo &
Struct = StructInProgress.
back();
3467 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3471 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3474 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3475 Field.LengthOf = RealInfo.AsIntValues.size();
3480 Struct.NextOffset = FieldEnd;
3488bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3489 const fltSemantics &Semantics,
3491 if (StructInProgress.
empty()) {
3493 if (emitRealValues(Semantics))
3494 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3495 }
else if (addRealField(
"", Semantics,
Size)) {
3496 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3503bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3504 const fltSemantics &Semantics,
3505 unsigned Size, StringRef Name,
3507 if (StructInProgress.
empty()) {
3510 getStreamer().emitLabel(Sym);
3512 if (emitRealValues(Semantics, &
Count))
3513 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3521 }
else if (addRealField(Name, Semantics,
Size)) {
3522 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3527bool MasmParser::parseOptionalAngleBracketOpen() {
3528 const AsmToken Tok = getTok();
3530 AngleBracketDepth++;
3534 AngleBracketDepth++;
3538 AngleBracketDepth++;
3545bool MasmParser::parseAngleBracketClose(
const Twine &Msg) {
3546 const AsmToken Tok = getTok();
3552 AngleBracketDepth--;
3556bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3557 const IntFieldInfo &Contents,
3558 FieldInitializer &Initializer) {
3559 SMLoc Loc = getTok().getLoc();
3564 return Error(Loc,
"Cannot initialize scalar field with array value");
3568 }
else if (parseOptionalAngleBracketOpen()) {
3570 return Error(Loc,
"Cannot initialize scalar field with array value");
3572 parseAngleBracketClose())
3574 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3575 return Error(Loc,
"Cannot initialize array field with scalar value");
3576 }
else if (parseScalarInitializer(
Field.Type, Values,
3582 return Error(Loc,
"Initializer too long for field; expected at most " +
3583 std::to_string(
Field.LengthOf) +
" elements, got " +
3584 std::to_string(Values.
size()));
3587 Values.
append(Contents.Values.begin() + Values.
size(), Contents.Values.end());
3589 Initializer = FieldInitializer(std::move(Values));
3593bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3594 const RealFieldInfo &Contents,
3595 FieldInitializer &Initializer) {
3596 const fltSemantics *Semantics;
3597 switch (
Field.Type) {
3599 Semantics = &APFloat::IEEEsingle();
3602 Semantics = &APFloat::IEEEdouble();
3605 Semantics = &APFloat::x87DoubleExtended();
3611 SMLoc Loc = getTok().getLoc();
3615 if (
Field.LengthOf == 1)
3616 return Error(Loc,
"Cannot initialize scalar field with array value");
3620 }
else if (parseOptionalAngleBracketOpen()) {
3621 if (
Field.LengthOf == 1)
3622 return Error(Loc,
"Cannot initialize scalar field with array value");
3624 parseAngleBracketClose())
3626 }
else if (
Field.LengthOf > 1) {
3627 return Error(Loc,
"Cannot initialize array field with scalar value");
3630 if (parseRealValue(*Semantics, AsIntValues.
back()))
3634 if (AsIntValues.
size() >
Field.LengthOf) {
3635 return Error(Loc,
"Initializer too long for field; expected at most " +
3636 std::to_string(
Field.LengthOf) +
" elements, got " +
3637 std::to_string(AsIntValues.
size()));
3640 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3641 Contents.AsIntValues.end());
3643 Initializer = FieldInitializer(std::move(AsIntValues));
3647bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3648 const StructFieldInfo &Contents,
3649 FieldInitializer &Initializer) {
3650 SMLoc Loc = getTok().getLoc();
3652 std::vector<StructInitializer> Initializers;
3653 if (
Field.LengthOf > 1) {
3655 if (parseStructInstList(Contents.Structure, Initializers,
3659 }
else if (parseOptionalAngleBracketOpen()) {
3660 if (parseStructInstList(Contents.Structure, Initializers,
3662 parseAngleBracketClose())
3665 return Error(Loc,
"Cannot initialize array field with scalar value");
3668 Initializers.emplace_back();
3669 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3673 if (Initializers.size() >
Field.LengthOf) {
3674 return Error(Loc,
"Initializer too long for field; expected at most " +
3675 std::to_string(
Field.LengthOf) +
" elements, got " +
3676 std::to_string(Initializers.size()));
3680 Initializers.size()));
3682 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3686bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3687 FieldInitializer &Initializer) {
3688 switch (
Field.Contents.FT) {
3690 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3692 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3694 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3699bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3700 StructInitializer &Initializer) {
3701 const AsmToken FirstToken = getTok();
3703 std::optional<AsmToken::TokenKind> EndToken;
3706 }
else if (parseOptionalAngleBracketOpen()) {
3708 AngleBracketDepth++;
3715 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3718 auto &FieldInitializers = Initializer.FieldInitializers;
3719 size_t FieldIndex = 0;
3722 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3723 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3727 FieldInitializers.push_back(
Field.Contents);
3731 FieldInitializers.emplace_back(
Field.Contents.FT);
3732 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3736 SMLoc CommaLoc = getTok().getLoc();
3739 if (FieldIndex == Structure.Fields.size())
3740 return Error(CommaLoc,
"'" + Structure.Name +
3741 "' initializer initializes too many fields");
3747 FieldInitializers.push_back(
Field.Contents);
3751 return parseAngleBracketClose();
3753 return parseToken(*EndToken);
3759bool MasmParser::parseStructInstList(
3760 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3762 while (getTok().
isNot(EndToken) ||
3765 const AsmToken NextTok = peekTok();
3768 const MCExpr *
Value;
3774 "cannot repeat value a non-constant number of times");
3775 const int64_t Repetitions = MCE->
getValue();
3776 if (Repetitions < 0)
3778 "cannot repeat value a negative number of times");
3780 std::vector<StructInitializer> DuplicatedValues;
3782 "parentheses required for 'dup' contents") ||
3783 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3786 for (
int i = 0; i < Repetitions; ++i)
3789 Initializers.emplace_back();
3790 if (parseStructInitializer(Structure, Initializers.back()))
3803bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3804 const IntFieldInfo &Contents) {
3806 for (
const MCExpr *
Value : Contents.Values) {
3813bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3814 const RealFieldInfo &Contents) {
3815 for (
const APInt &AsInt : Contents.AsIntValues) {
3822bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3823 const StructFieldInfo &Contents) {
3824 for (
const auto &Initializer : Contents.Initializers) {
3826 for (
const auto &SubField : Contents.Structure.Fields) {
3827 getStreamer().emitZeros(SubField.Offset -
Offset);
3828 Offset = SubField.Offset + SubField.SizeOf;
3829 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3835bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3836 switch (
Field.Contents.FT) {
3838 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3840 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3842 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3847bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3848 const IntFieldInfo &Contents,
3849 const IntFieldInfo &Initializer) {
3850 for (
const auto &
Value : Initializer.Values) {
3855 for (
const auto &
Value :
3863bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3864 const RealFieldInfo &Contents,
3865 const RealFieldInfo &Initializer) {
3866 for (
const auto &AsInt : Initializer.AsIntValues) {
3871 for (
const auto &AsInt :
3879bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3880 const StructFieldInfo &Contents,
3881 const StructFieldInfo &Initializer) {
3882 for (
const auto &Init : Initializer.Initializers) {
3883 if (emitStructInitializer(Contents.Structure, Init))
3888 Initializer.Initializers.size())) {
3889 if (emitStructInitializer(Contents.Structure, Init))
3895bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3896 const FieldInitializer &Initializer) {
3897 switch (
Field.Contents.FT) {
3899 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3900 Initializer.IntInfo);
3902 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3903 Initializer.RealInfo);
3905 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3906 Initializer.StructInfo);
3911bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3912 const StructInitializer &Initializer) {
3913 if (!Structure.Initializable)
3914 return Error(getLexer().getLoc(),
3915 "cannot initialize a value of type '" + Structure.Name +
3916 "'; 'org' was used in the type's declaration");
3918 for (
const auto &Init : Initializer.FieldInitializers) {
3919 const auto &
Field = Structure.Fields[
Index++];
3922 if (emitFieldInitializer(
Field, Init))
3927 Structure.Fields, Initializer.FieldInitializers.size())) {
3930 if (emitFieldValue(
Field))
3934 if (
Offset != Structure.Size)
3935 getStreamer().emitZeros(Structure.Size -
Offset);
3940bool MasmParser::emitStructValues(
const StructInfo &Structure,
3942 std::vector<StructInitializer> Initializers;
3943 if (parseStructInstList(Structure, Initializers))
3946 for (
const auto &Initializer : Initializers) {
3947 if (emitStructInitializer(Structure, Initializer))
3952 *
Count = Initializers.size();
3957bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3958 StructInfo &OwningStruct = StructInProgress.
back();
3960 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3961 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3963 StructInfo.Structure = Structure;
3964 Field.Type = Structure.Size;
3966 if (parseStructInstList(Structure, StructInfo.Initializers))
3969 Field.LengthOf = StructInfo.Initializers.size();
3973 if (!OwningStruct.IsUnion) {
3974 OwningStruct.NextOffset = FieldEnd;
3976 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3984bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3985 StringRef Directive, SMLoc DirLoc) {
3986 if (StructInProgress.
empty()) {
3987 if (emitStructValues(Structure))
3989 }
else if (addStructField(
"", Structure)) {
3990 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
3998bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
3999 StringRef Directive,
4000 SMLoc DirLoc, StringRef Name) {
4001 if (StructInProgress.
empty()) {
4004 getStreamer().emitLabel(Sym);
4006 if (emitStructValues(Structure, &
Count))
4009 Type.Name = Structure.Name;
4011 Type.ElementSize = Structure.Size;
4014 }
else if (addStructField(Name, Structure)) {
4015 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4027bool MasmParser::parseDirectiveStruct(StringRef Directive,
4028 DirectiveKind DirKind, StringRef Name,
4032 AsmToken NextTok = getTok();
4033 int64_t AlignmentValue = 1;
4036 parseAbsoluteExpression(AlignmentValue)) {
4037 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4041 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4042 std::to_string(AlignmentValue));
4048 QualifierLoc = getTok().getLoc();
4049 if (parseIdentifier(Qualifier))
4050 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4051 if (!
Qualifier.equals_insensitive(
"nonunique"))
4052 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4054 "' directive; expected none or NONUNIQUE");
4058 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4060 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4068bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4069 DirectiveKind DirKind) {
4070 if (StructInProgress.
empty())
4071 return TokError(
"missing name in top-level '" + Twine(Directive) +
4076 Name = getTok().getIdentifier();
4080 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4084 StructInProgress.
reserve(StructInProgress.
size() + 1);
4085 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4086 StructInProgress.
back().Alignment);
4090bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4091 if (StructInProgress.
empty())
4092 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4093 if (StructInProgress.
size() > 1)
4094 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4095 if (StructInProgress.
back().Name.compare_insensitive(Name))
4096 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4097 StructInProgress.
back().Name +
"'");
4098 StructInfo Structure = StructInProgress.
pop_back_val();
4102 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4103 Structs[
Name.lower()] = std::move(Structure);
4106 return addErrorSuffix(
" in ENDS directive");
4111bool MasmParser::parseDirectiveNestedEnds() {
4112 if (StructInProgress.
empty())
4113 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4114 if (StructInProgress.
size() == 1)
4115 return TokError(
"missing name in top-level ENDS directive");
4118 return addErrorSuffix(
" in nested ENDS directive");
4120 StructInfo Structure = StructInProgress.
pop_back_val();
4122 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4124 StructInfo &ParentStruct = StructInProgress.
back();
4125 if (Structure.Name.
empty()) {
4128 const size_t OldFields = ParentStruct.Fields.size();
4129 ParentStruct.Fields.insert(
4130 ParentStruct.Fields.end(),
4131 std::make_move_iterator(Structure.Fields.begin()),
4132 std::make_move_iterator(Structure.Fields.end()));
4133 for (
const auto &FieldByName : Structure.FieldsByName) {
4134 ParentStruct.FieldsByName[FieldByName.getKey()] =
4135 FieldByName.getValue() + OldFields;
4138 unsigned FirstFieldOffset = 0;
4139 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4141 ParentStruct.NextOffset,
4142 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4145 if (ParentStruct.IsUnion) {
4146 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4151 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4152 if (!ParentStruct.IsUnion) {
4153 ParentStruct.NextOffset = StructureEnd;
4155 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4158 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4159 Structure.AlignmentSize);
4160 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4161 Field.Type = Structure.Size;
4163 Field.SizeOf = Structure.Size;
4166 if (!ParentStruct.IsUnion) {
4167 ParentStruct.NextOffset = StructureEnd;
4169 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4171 StructInfo.Structure = Structure;
4172 StructInfo.Initializers.emplace_back();
4173 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4174 for (
const auto &SubField : Structure.Fields) {
4175 FieldInitializers.push_back(SubField.Contents);
4184bool MasmParser::parseDirectiveOrg() {
4186 SMLoc OffsetLoc = Lexer.getLoc();
4187 if (checkForValidSection() || parseExpression(
Offset))
4190 return addErrorSuffix(
" in 'org' directive");
4192 if (StructInProgress.
empty()) {
4194 if (checkForValidSection())
4195 return addErrorSuffix(
" in 'org' directive");
4197 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4200 StructInfo &Structure = StructInProgress.
back();
4202 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4203 return Error(OffsetLoc,
4204 "expected absolute expression in 'org' directive");
4208 "expected non-negative value in struct's 'org' directive; was " +
4209 std::to_string(OffsetRes));
4210 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4213 Structure.Initializable =
false;
4219bool MasmParser::emitAlignTo(int64_t Alignment) {
4220 if (StructInProgress.
empty()) {
4222 if (checkForValidSection())
4227 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4229 getStreamer().emitCodeAlignment(
Align(Alignment),
4230 &getTargetParser().getSTI(),
4234 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4240 StructInfo &Structure = StructInProgress.
back();
4241 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4249bool MasmParser::parseDirectiveAlign() {
4250 SMLoc AlignmentLoc = getLexer().getLoc();
4256 "align directive with no operand is ignored") &&
4259 if (parseAbsoluteExpression(Alignment) || parseEOL())
4260 return addErrorSuffix(
" in align directive");
4263 bool ReturnVal =
false;
4270 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4271 std::to_string(Alignment));
4273 if (emitAlignTo(Alignment))
4274 ReturnVal |= addErrorSuffix(
" in align directive");
4281bool MasmParser::parseDirectiveEven() {
4282 if (parseEOL() || emitAlignTo(2))
4283 return addErrorSuffix(
" in even directive");
4294bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4298 return Error(Lexer.getLoc(),
4299 "Vararg parameter '" +
Parameters.back().Name +
4300 "' should be last in the list of parameters");
4304 return TokError(
"expected identifier in 'macro' directive");
4307 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4308 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4309 return TokError(
"macro '" + Name +
"' has multiple parameters"
4319 ParamLoc = Lexer.getLoc();
4320 if (parseMacroArgument(
nullptr,
Parameter.Value))
4326 QualLoc = Lexer.getLoc();
4327 if (parseIdentifier(Qualifier))
4328 return Error(QualLoc,
"missing parameter qualifier for "
4330 Parameter.Name +
"' in macro '" + Name +
4333 if (
Qualifier.equals_insensitive(
"req"))
4335 else if (
Qualifier.equals_insensitive(
"vararg"))
4338 return Error(QualLoc,
4339 Qualifier +
" is not a valid parameter qualifier for '" +
4340 Parameter.Name +
"' in macro '" + Name +
"'");
4353 std::vector<std::string>
Locals;
4355 getTok().getIdentifier().equals_insensitive(
"local")) {
4360 if (parseIdentifier(
ID))
4372 AsmToken EndToken, StartToken = getTok();
4373 unsigned MacroDepth = 0;
4374 bool IsMacroFunction =
false;
4384 return Error(NameLoc,
"no matching 'endm' in definition");
4389 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4390 if (MacroDepth == 0) {
4391 EndToken = getTok();
4394 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4401 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4403 IsMacroFunction =
true;
4405 }
else if (isMacroLikeDirective()) {
4413 eatToEndOfStatement();
4417 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4422 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4423 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4433bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4434 StringRef Directive,
4435 std::string &
Value) {
4436 SMLoc EndLoc = getTok().getLoc();
4438 return Error(EndLoc,
4439 "unable to parse text item in '" + Directive +
"' directive");
4440 eatToEndOfStatement();
4442 if (!isInsideMacroInstantiation())
4443 return TokError(
"unexpected '" + Directive +
"' in file, "
4444 "no current macro definition");
4447 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4448 TheCondState = TheCondStack.back();
4449 TheCondStack.pop_back();
4458bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4460 return TokError(
"unexpected token in '" + Directive +
"' directive");
4464 if (isInsideMacroInstantiation()) {
4471 return TokError(
"unexpected '" + Directive +
"' in file, "
4472 "no current macro definition");
4477bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4481 if (parseTokenLoc(NameLoc) ||
4482 check(parseIdentifier(Name), NameLoc,
4483 "expected identifier in 'purge' directive"))
4487 <<
"Un-defining macro: " << Name <<
"\n");
4489 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4500bool MasmParser::parseDirectiveExtern() {
4502 auto parseOp = [&]() ->
bool {
4504 SMLoc NameLoc = getTok().getLoc();
4506 return Error(NameLoc,
"expected name");
4511 SMLoc TypeLoc = getTok().getLoc();
4512 if (parseIdentifier(TypeName))
4513 return Error(TypeLoc,
"expected type");
4514 if (!
TypeName.equals_insensitive(
"proc")) {
4516 if (lookUpType(TypeName,
Type))
4517 return Error(TypeLoc,
"unrecognized type");
4521 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4522 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4527 if (parseMany(parseOp))
4528 return addErrorSuffix(
" in directive 'extern'");
4534bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4535 auto parseOp = [&]() ->
bool {
4536 SMLoc Loc = getTok().getLoc();
4539 return Error(Loc,
"expected identifier");
4543 return Error(Loc,
"non-local symbol required");
4545 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4546 return Error(Loc,
"unable to emit symbol attribute");
4550 if (parseMany(parseOp))
4551 return addErrorSuffix(
" in directive");
4557bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4558 if (checkForValidSection())
4561 SMLoc IDLoc = getLexer().getLoc();
4564 return TokError(
"expected identifier in directive");
4567 return TokError(
"unexpected token in directive");
4571 SMLoc SizeLoc = getLexer().getLoc();
4572 if (parseAbsoluteExpression(
Size))
4575 int64_t Pow2Alignment = 0;
4576 SMLoc Pow2AlignmentLoc;
4579 Pow2AlignmentLoc = getLexer().getLoc();
4580 if (parseAbsoluteExpression(Pow2Alignment))
4585 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4588 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4591 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4592 Pow2Alignment =
Log2_64(Pow2Alignment);
4602 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4603 "be less than zero");
4608 if (Pow2Alignment < 0)
4609 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4610 "alignment, can't be less than zero");
4614 return Error(IDLoc,
"invalid symbol redefinition");
4618 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4619 Align(1ULL << Pow2Alignment));
4623 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4631bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4633 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4634 assert(DelimiterEnd != std::string::npos);
4635 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4636 if (Delimiter.
empty())
4637 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4640 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4650bool MasmParser::parseDirectiveInclude() {
4653 SMLoc IncludeLoc = getTok().getLoc();
4655 if (parseAngleBracketString(
Filename))
4657 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4659 "unexpected token in 'include' directive") ||
4662 check(enterIncludeFile(
Filename), IncludeLoc,
4663 "Could not find include file '" +
Filename +
"'"))
4671bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4672 TheCondStack.push_back(TheCondState);
4674 if (TheCondState.
Ignore) {
4675 eatToEndOfStatement();
4678 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4687 ExprValue = ExprValue == 0;
4691 TheCondState.
CondMet = ExprValue;
4700bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4701 TheCondStack.push_back(TheCondState);
4704 if (TheCondState.
Ignore) {
4705 eatToEndOfStatement();
4708 if (parseTextItem(Str))
4709 return TokError(
"expected text item parameter for 'ifb' directive");
4714 TheCondState.
CondMet = ExpectBlank == Str.empty();
4723bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4724 bool CaseInsensitive) {
4725 std::string String1, String2;
4727 if (parseTextItem(String1)) {
4729 return TokError(
"expected text item parameter for 'ifidn' directive");
4730 return TokError(
"expected text item parameter for 'ifdif' directive");
4736 "expected comma after first string for 'ifidn' directive");
4737 return TokError(
"expected comma after first string for 'ifdif' directive");
4741 if (parseTextItem(String2)) {
4743 return TokError(
"expected text item parameter for 'ifidn' directive");
4744 return TokError(
"expected text item parameter for 'ifdif' directive");
4747 TheCondStack.push_back(TheCondState);
4749 if (CaseInsensitive)
4751 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4753 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4762bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4763 TheCondStack.push_back(TheCondState);
4766 if (TheCondState.
Ignore) {
4767 eatToEndOfStatement();
4769 bool is_defined =
false;
4771 SMLoc StartLoc, EndLoc;
4773 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4776 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4780 if (BuiltinSymbolMap.contains(
Name.lower())) {
4790 TheCondState.
CondMet = (is_defined == expect_defined);
4799bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4800 DirectiveKind DirKind) {
4803 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4804 " .if or an .elseif");
4807 bool LastIgnoreState =
false;
4808 if (!TheCondStack.empty())
4809 LastIgnoreState = TheCondStack.back().Ignore;
4810 if (LastIgnoreState || TheCondState.
CondMet) {
4811 TheCondState.
Ignore =
true;
4812 eatToEndOfStatement();
4815 if (parseAbsoluteExpression(ExprValue))
4827 ExprValue = ExprValue == 0;
4831 TheCondState.
CondMet = ExprValue;
4840bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4843 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4844 " if or an elseif");
4847 bool LastIgnoreState =
false;
4848 if (!TheCondStack.empty())
4849 LastIgnoreState = TheCondStack.back().Ignore;
4850 if (LastIgnoreState || TheCondState.
CondMet) {
4851 TheCondState.
Ignore =
true;
4852 eatToEndOfStatement();
4855 if (parseTextItem(Str)) {
4857 return TokError(
"expected text item parameter for 'elseifb' directive");
4858 return TokError(
"expected text item parameter for 'elseifnb' directive");
4864 TheCondState.
CondMet = ExpectBlank == Str.empty();
4874bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4875 bool expect_defined) {
4878 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4879 " if or an elseif");
4882 bool LastIgnoreState =
false;
4883 if (!TheCondStack.empty())
4884 LastIgnoreState = TheCondStack.back().Ignore;
4885 if (LastIgnoreState || TheCondState.
CondMet) {
4886 TheCondState.
Ignore =
true;
4887 eatToEndOfStatement();
4889 bool is_defined =
false;
4891 SMLoc StartLoc, EndLoc;
4893 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4896 if (check(parseIdentifier(Name),
4897 "expected identifier after 'elseifdef'") ||
4901 if (BuiltinSymbolMap.contains(
Name.lower())) {
4911 TheCondState.
CondMet = (is_defined == expect_defined);
4920bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4921 bool CaseInsensitive) {
4924 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4925 " if or an elseif");
4928 bool LastIgnoreState =
false;
4929 if (!TheCondStack.empty())
4930 LastIgnoreState = TheCondStack.back().Ignore;
4931 if (LastIgnoreState || TheCondState.
CondMet) {
4932 TheCondState.
Ignore =
true;
4933 eatToEndOfStatement();
4935 std::string String1, String2;
4937 if (parseTextItem(String1)) {
4940 "expected text item parameter for 'elseifidn' directive");
4941 return TokError(
"expected text item parameter for 'elseifdif' directive");
4947 "expected comma after first string for 'elseifidn' directive");
4949 "expected comma after first string for 'elseifdif' directive");
4953 if (parseTextItem(String2)) {
4956 "expected text item parameter for 'elseifidn' directive");
4957 return TokError(
"expected text item parameter for 'elseifdif' directive");
4960 if (CaseInsensitive)
4962 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4964 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4973bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4979 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4982 bool LastIgnoreState =
false;
4983 if (!TheCondStack.empty())
4984 LastIgnoreState = TheCondStack.back().Ignore;
4985 if (LastIgnoreState || TheCondState.
CondMet)
4986 TheCondState.
Ignore =
true;
4988 TheCondState.
Ignore =
false;
4995bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5007bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5008 if (!TheCondStack.empty()) {
5009 if (TheCondStack.back().Ignore) {
5010 eatToEndOfStatement();
5015 std::string Message =
".err directive invoked in source file";
5020 return Error(DirectiveLoc, Message);
5025bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5026 if (!TheCondStack.empty()) {
5027 if (TheCondStack.back().Ignore) {
5028 eatToEndOfStatement();
5034 if (parseTextItem(
Text))
5035 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5037 std::string Message =
".errb directive invoked in source file";
5040 return addErrorSuffix(
" in '.errb' directive");
5045 if (
Text.empty() == ExpectBlank)
5046 return Error(DirectiveLoc, Message);
5052bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5053 bool ExpectDefined) {
5054 if (!TheCondStack.empty()) {
5055 if (TheCondStack.back().Ignore) {
5056 eatToEndOfStatement();
5061 bool IsDefined =
false;
5063 SMLoc StartLoc, EndLoc;
5065 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5068 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5071 if (BuiltinSymbolMap.contains(
Name.lower())) {
5081 std::string Message =
".errdef directive invoked in source file";
5084 return addErrorSuffix(
" in '.errdef' directive");
5089 if (IsDefined == ExpectDefined)
5090 return Error(DirectiveLoc, Message);
5096bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5097 bool CaseInsensitive) {
5098 if (!TheCondStack.empty()) {
5099 if (TheCondStack.back().Ignore) {
5100 eatToEndOfStatement();
5105 std::string String1, String2;
5107 if (parseTextItem(String1)) {
5109 return TokError(
"expected string parameter for '.erridn' directive");
5110 return TokError(
"expected string parameter for '.errdif' directive");
5116 "expected comma after first string for '.erridn' directive");
5118 "expected comma after first string for '.errdif' directive");
5122 if (parseTextItem(String2)) {
5124 return TokError(
"expected string parameter for '.erridn' directive");
5125 return TokError(
"expected string parameter for '.errdif' directive");
5128 std::string Message;
5130 Message =
".erridn directive invoked in source file";
5132 Message =
".errdif directive invoked in source file";
5135 return addErrorSuffix(
" in '.erridn' directive");
5140 if (CaseInsensitive)
5142 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5144 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5147 if ((CaseInsensitive &&
5148 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5149 (ExpectEqual == (String1 == String2)))
5150 return Error(DirectiveLoc, Message);
5156bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5157 if (!TheCondStack.empty()) {
5158 if (TheCondStack.back().Ignore) {
5159 eatToEndOfStatement();
5165 if (parseAbsoluteExpression(ExprValue))
5166 return addErrorSuffix(
" in '.erre' directive");
5168 std::string Message =
".erre directive invoked in source file";
5171 return addErrorSuffix(
" in '.erre' directive");
5176 if ((ExprValue == 0) == ExpectZero)
5177 return Error(DirectiveLoc, Message);
5183bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5188 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5190 if (!TheCondStack.empty()) {
5191 TheCondState = TheCondStack.back();
5192 TheCondStack.pop_back();
5198void MasmParser::initializeDirectiveKindMap() {
5199 DirectiveKindMap[
"="] = DK_ASSIGN;
5200 DirectiveKindMap[
"equ"] = DK_EQU;
5201 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5205 DirectiveKindMap[
"byte"] = DK_BYTE;
5206 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5207 DirectiveKindMap[
"word"] = DK_WORD;
5208 DirectiveKindMap[
"sword"] = DK_SWORD;
5209 DirectiveKindMap[
"dword"] = DK_DWORD;
5210 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5211 DirectiveKindMap[
"fword"] = DK_FWORD;
5212 DirectiveKindMap[
"qword"] = DK_QWORD;
5213 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5214 DirectiveKindMap[
"real4"] = DK_REAL4;
5215 DirectiveKindMap[
"real8"] = DK_REAL8;
5216 DirectiveKindMap[
"real10"] = DK_REAL10;
5217 DirectiveKindMap[
"align"] = DK_ALIGN;
5218 DirectiveKindMap[
"even"] = DK_EVEN;
5219 DirectiveKindMap[
"org"] = DK_ORG;
5220 DirectiveKindMap[
"extern"] = DK_EXTERN;
5221 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5222 DirectiveKindMap[
"public"] = DK_PUBLIC;
5224 DirectiveKindMap[
"comment"] = DK_COMMENT;
5225 DirectiveKindMap[
"include"] = DK_INCLUDE;
5226 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5227 DirectiveKindMap[
"rept"] = DK_REPEAT;
5228 DirectiveKindMap[
"while"] = DK_WHILE;
5229 DirectiveKindMap[
"for"] = DK_FOR;
5230 DirectiveKindMap[
"irp"] = DK_FOR;
5231 DirectiveKindMap[
"forc"] = DK_FORC;
5232 DirectiveKindMap[
"irpc"] = DK_FORC;
5233 DirectiveKindMap[
"if"] = DK_IF;
5234 DirectiveKindMap[
"ife"] = DK_IFE;
5235 DirectiveKindMap[
"ifb"] = DK_IFB;
5236 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5237 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5238 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5239 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5240 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5241 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5242 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5243 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5244 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5245 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5246 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5247 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5248 DirectiveKindMap[
"else"] = DK_ELSE;
5249 DirectiveKindMap[
"end"] = DK_END;
5250 DirectiveKindMap[
"endif"] = DK_ENDIF;
5294 DirectiveKindMap[
"macro"] = DK_MACRO;
5295 DirectiveKindMap[
"exitm"] = DK_EXITM;
5296 DirectiveKindMap[
"endm"] = DK_ENDM;
5297 DirectiveKindMap[
"purge"] = DK_PURGE;
5298 DirectiveKindMap[
".err"] = DK_ERR;
5299 DirectiveKindMap[
".errb"] = DK_ERRB;
5300 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5301 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5302 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5303 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5304 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5305 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5306 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5307 DirectiveKindMap[
".erre"] = DK_ERRE;
5308 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5309 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5310 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5311 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5312 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5313 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5314 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5315 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5316 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5317 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5318 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5319 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5320 DirectiveKindMap[
".radix"] = DK_RADIX;
5321 DirectiveKindMap[
"db"] = DK_DB;
5322 DirectiveKindMap[
"dd"] = DK_DD;
5323 DirectiveKindMap[
"df"] = DK_DF;
5324 DirectiveKindMap[
"dq"] = DK_DQ;
5325 DirectiveKindMap[
"dw"] = DK_DW;
5326 DirectiveKindMap[
"echo"] = DK_ECHO;
5327 DirectiveKindMap[
"struc"] = DK_STRUCT;
5328 DirectiveKindMap[
"struct"] = DK_STRUCT;
5329 DirectiveKindMap[
"union"] = DK_UNION;
5330 DirectiveKindMap[
"ends"] = DK_ENDS;
5333bool MasmParser::isMacroLikeDirective() {
5335 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5336 .CasesLower({
"repeat",
"rept"},
true)
5337 .CaseLower(
"while",
true)
5338 .CasesLower({
"for",
"irp"},
true)
5339 .CasesLower({
"forc",
"irpc"},
true)
5345 peekTok().getIdentifier().equals_insensitive(
"macro"))
5351MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5352 AsmToken EndToken, StartToken = getTok();
5354 unsigned NestLevel = 0;
5358 printError(DirectiveLoc,
"no matching 'endm' in definition");
5362 if (isMacroLikeDirective())
5367 getTok().getIdentifier().equals_insensitive(
"endm")) {
5368 if (NestLevel == 0) {
5369 EndToken = getTok();
5372 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5381 eatToEndOfStatement();
5386 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5390 return &MacroLikeBodies.back();
5393bool MasmParser::expandStatement(SMLoc Loc) {
5395 SMLoc EndLoc = getTok().getLoc();
5400 StringMap<std::string> BuiltinValues;
5401 for (
const auto &S : BuiltinSymbolMap) {
5402 const BuiltinSymbol &Sym = S.getValue();
5403 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5404 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5407 for (
const auto &
B : BuiltinValues) {
5408 MCAsmMacroParameter
P;
5409 MCAsmMacroArgument
A;
5410 P.Name =
B.getKey();
5418 for (
const auto &V : Variables) {
5421 MCAsmMacroParameter
P;
5422 MCAsmMacroArgument
A;
5431 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5432 MCAsmMacro
M = MacroLikeBodies.back();
5435 SmallString<80> Buf;
5436 raw_svector_ostream OS(Buf);
5437 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5439 std::unique_ptr<MemoryBuffer>
Expansion =
5445 EndStatementAtEOFStack.push_back(
false);
5450void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5451 raw_svector_ostream &OS) {
5452 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5454void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5456 raw_svector_ostream &OS) {
5459 std::unique_ptr<MemoryBuffer> Instantiation =
5464 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5465 ExitLoc, TheCondStack.size()};
5466 ActiveMacros.push_back(
MI);
5471 EndStatementAtEOFStack.push_back(
true);
5479bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5480 const MCExpr *CountExpr;
5481 SMLoc CountLoc = getTok().getLoc();
5482 if (parseExpression(CountExpr))
5486 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5487 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5490 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5494 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5500 SmallString<256> Buf;
5501 raw_svector_ostream OS(Buf);
5503 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5506 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5515bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5516 const MCExpr *CondExpr;
5517 SMLoc CondLoc = getTok().getLoc();
5518 if (parseExpression(CondExpr))
5522 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5528 SmallString<256> Buf;
5529 raw_svector_ostream OS(Buf);
5531 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5532 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5536 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5538 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5548bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5550 MCAsmMacroArguments
A;
5551 if (check(parseIdentifier(
Parameter.Name),
5552 "expected identifier in '" + Dir +
"' directive"))
5561 ParamLoc = Lexer.getLoc();
5562 if (parseMacroArgument(
nullptr,
Parameter.Value))
5568 QualLoc = Lexer.getLoc();
5569 if (parseIdentifier(Qualifier))
5570 return Error(QualLoc,
"missing parameter qualifier for "
5575 if (
Qualifier.equals_insensitive(
"req"))
5578 return Error(QualLoc,
5579 Qualifier +
" is not a valid parameter qualifier for '" +
5580 Parameter.Name +
"' in '" + Dir +
"' directive");
5585 "expected comma in '" + Dir +
"' directive") ||
5587 "values in '" + Dir +
5588 "' directive must be enclosed in angle brackets"))
5594 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5603 "values in '" + Dir +
5604 "' directive must be enclosed in angle brackets") ||
5609 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5615 SmallString<256> Buf;
5616 raw_svector_ostream OS(Buf);
5618 for (
const MCAsmMacroArgument &Arg :
A) {
5619 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5623 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5632bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5636 if (check(parseIdentifier(
Parameter.Name),
5637 "expected identifier in '" + Directive +
"' directive") ||
5639 "expected comma in '" + Directive +
"' directive"))
5641 if (parseAngleBracketString(Argument)) {
5649 for (; End <
Argument.size(); ++End) {
5659 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5665 SmallString<256> Buf;
5666 raw_svector_ostream OS(Buf);
5668 StringRef Values(Argument);
5669 for (std::size_t
I = 0, End = Values.
size();
I != End; ++
I) {
5670 MCAsmMacroArgument Arg;
5673 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5677 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5682bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5684 const MCExpr *
Value;
5685 SMLoc ExprLoc = getLexer().getLoc();
5686 if (parseExpression(
Value))
5690 return Error(ExprLoc,
"unexpected expression in _emit");
5691 uint64_t IntValue = MCE->
getValue();
5693 return Error(ExprLoc,
"literal value out of range for directive");
5699bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5700 const MCExpr *
Value;
5701 SMLoc ExprLoc = getLexer().getLoc();
5702 if (parseExpression(
Value))
5706 return Error(ExprLoc,
"unexpected expression in align");
5707 uint64_t IntValue = MCE->
getValue();
5709 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5715bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5716 const SMLoc Loc = getLexer().getLoc();
5718 StringRef RadixString = StringRef(RadixStringRaw).trim();
5722 "radix must be a decimal number in the range 2 to 16; was " +
5725 if (Radix < 2 || Radix > 16)
5726 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5727 std::to_string(Radix));
5728 getLexer().setMasmDefaultRadix(Radix);
5734bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5737 if (!StringRef(Message).ends_with(
"\n"))
5765bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5767 if (Var.Name.empty()) {
5769 }
else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5770 return Error(SMLoc(),
"invalid variable redefinition");
5771 }
else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5772 Warning(SMLoc(),
"redefining '" + Name +
5773 "', already defined on the command line")) {
5776 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5778 Var.TextValue =
Value.str();
5782bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5783 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5784 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5785 return lookUpField(
Base, Member, Info);
5788bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5789 AsmFieldInfo &Info)
const {
5793 AsmFieldInfo BaseInfo;
5794 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5797 auto StructIt = Structs.
find(
Base.lower());
5798 auto TypeIt = KnownType.
find(
Base.lower());
5799 if (TypeIt != KnownType.
end()) {
5800 StructIt = Structs.
find(TypeIt->second.Name.lower());
5802 if (StructIt != Structs.
end())
5803 return lookUpField(StructIt->second, Member, Info);
5808bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5809 AsmFieldInfo &Info)
const {
5811 Info.Type.Name = Structure.Name;
5812 Info.Type.Size = Structure.Size;
5813 Info.Type.ElementSize = Structure.Size;
5814 Info.Type.Length = 1;
5818 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5819 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5821 auto StructIt = Structs.
find(FieldName.
lower());
5822 if (StructIt != Structs.
end())
5823 return lookUpField(StructIt->second, FieldMember, Info);
5825 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5826 if (FieldIt == Structure.FieldsByName.
end())
5829 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5830 if (FieldMember.empty()) {
5835 if (
Field.Contents.FT == FT_STRUCT)
5836 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5838 Info.Type.Name =
"";
5842 if (
Field.Contents.FT != FT_STRUCT)
5844 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5846 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5853bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5854 unsigned Size = StringSwitch<unsigned>(Name)
5855 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5856 .CasesLower({
"word",
"dw",
"sword"}, 2)
5857 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5858 .CasesLower({
"fword",
"df"}, 6)
5859 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5860 .CaseLower(
"real4", 4)
5861 .CaseLower(
"real8", 8)
5862 .CaseLower(
"real10", 10)
5872 auto StructIt = Structs.
find(
Name.lower());
5873 if (StructIt != Structs.
end()) {
5874 const StructInfo &Structure = StructIt->second;
5876 Info.ElementSize = Structure.Size;
5878 Info.Size = Structure.Size;
5885bool MasmParser::parseMSInlineAsm(
5886 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5887 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5888 SmallVectorImpl<std::string> &Constraints,
5889 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5890 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5891 SmallVector<void *, 4> InputDecls;
5892 SmallVector<void *, 4> OutputDecls;
5895 SmallVector<std::string, 4> InputConstraints;
5896 SmallVector<std::string, 4> OutputConstraints;
5905 unsigned InputIdx = 0;
5906 unsigned OutputIdx = 0;
5909 if (parseCurlyBlockScope(AsmStrRewrites))
5912 ParseStatementInfo
Info(&AsmStrRewrites);
5913 bool StatementErr = parseStatement(Info, &SI);
5915 if (StatementErr ||
Info.ParseError) {
5917 printPendingErrors();
5922 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5924 if (
Info.Opcode == ~0U)
5930 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5931 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5935 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5936 unsigned NumDefs =
Desc.getNumDefs();
5945 if (SymName.
empty())
5953 if (Operand.
isImm()) {
5961 bool isOutput = (i == 1) &&
Desc.mayStore();
5967 OutputConstraints.
push_back((
"=" + Constraint).str());
5973 if (
Desc.operands()[i - 1].isBranchTarget())
5985 NumOutputs = OutputDecls.
size();
5986 NumInputs = InputDecls.
size();
5991 Clobbers.
assign(ClobberRegs.
size(), std::string());
5992 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5993 raw_string_ostream OS(Clobbers[
I]);
5998 if (NumOutputs || NumInputs) {
5999 unsigned NumExprs = NumOutputs + NumInputs;
6000 OpDecls.resize(NumExprs);
6001 Constraints.
resize(NumExprs);
6002 for (
unsigned i = 0; i < NumOutputs; ++i) {
6003 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6004 Constraints[i] = OutputConstraints[i];
6006 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6007 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6008 Constraints[
j] = InputConstraints[i];
6013 std::string AsmStringIR;
6014 raw_string_ostream OS(AsmStringIR);
6015 StringRef ASMString =
6017 const char *AsmStart = ASMString.
begin();
6018 const char *AsmEnd = ASMString.
end();
6020 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6021 const AsmRewrite &AR = *
I;
6028 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6031 if (
unsigned Len = Loc - AsmStart)
6032 OS << StringRef(AsmStart, Len);
6036 AsmStart = Loc + AR.
Len;
6040 unsigned AdditionalSkip = 0;
6062 size_t OffsetLen = OffsetName.
size();
6063 auto rewrite_it = std::find_if(
6064 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6065 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6066 (FusingAR.Kind == AOK_Input ||
6067 FusingAR.Kind == AOK_CallInput);
6069 if (rewrite_it == AsmStrRewrites.
end()) {
6070 OS <<
"offset " << OffsetName;
6072 OS <<
"${" << InputIdx++ <<
":P}";
6073 rewrite_it->Done =
true;
6075 OS <<
'$' << InputIdx++;
6076 rewrite_it->Done =
true;
6088 OS <<
'$' << InputIdx++;
6091 OS <<
"${" << InputIdx++ <<
":P}";
6094 OS <<
'$' << OutputIdx++;
6099 case 8: OS <<
"byte ptr ";
break;
6100 case 16: OS <<
"word ptr ";
break;
6101 case 32: OS <<
"dword ptr ";
break;
6102 case 64: OS <<
"qword ptr ";
break;
6103 case 80: OS <<
"xword ptr ";
break;
6104 case 128: OS <<
"xmmword ptr ";
break;
6105 case 256: OS <<
"ymmword ptr ";
break;
6115 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6120 unsigned Val = AR.
Val;
6122 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6123 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6135 AsmStart = Loc + AR.
Len + AdditionalSkip;
6139 if (AsmStart != AsmEnd)
6140 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6142 AsmString = OS.
str();
6146void MasmParser::initializeBuiltinSymbolMaps() {
6148 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6149 BuiltinSymbolMap[
"@line"] = BI_LINE;
6150 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6153 BuiltinSymbolMap[
"@date"] = BI_DATE;
6154 BuiltinSymbolMap[
"@time"] = BI_TIME;
6155 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6156 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6157 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6160 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6163 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6181const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6191 if (ActiveMacros.empty())
6195 ActiveMacros.front()->ExitBuffer);
6198 case BI_UNWINDVERSION:
6205std::optional<std::string>
6206MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6212 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6213 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6214 return std::string(TmpBuffer, Len);
6218 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6219 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6220 return std::string(TmpBuffer, Len);
6225 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6233 return getStreamer().getCurrentSectionOnly()->getName().str();
6238bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6242 "' requires arguments in parentheses")) {
6253 MCAsmMacro
M(Name,
"",
P, {},
true);
6255 MCAsmMacroArguments
A;
6264 for (
const MCAsmMacroArgument &Arg :
A) {
6265 for (
const AsmToken &Tok : Arg) {
6283 struct tm TM,
unsigned CB) {
6284 return new MasmParser(
SM,
C, Out, MAI, TM, CB);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
AMDGPU Lower Kernel Arguments
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
static constexpr unsigned SM(unsigned Version)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
bool shouldUseLogicalShr() const
StringRef getInternalSymbolPrefix() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo & getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
Context & getContext() const
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI SourceMgr SrcMgr
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.