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);
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] = 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 = std::nullopt)
override;
487 bool Warning(SMLoc L,
const Twine &Msg,
488 SMRange
Range = std::nullopt)
override;
489 bool printError(SMLoc L,
const Twine &Msg,
490 SMRange
Range = std::nullopt)
override;
492 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
493 const AsmToken &Lex(ExpandKind ExpandNextToken);
494 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
496 void setParsingMSInlineAsm(
bool V)
override {
497 ParsingMSInlineAsm =
V;
500 Lexer.setLexMasmIntegers(V);
502 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
504 bool isParsingMasm()
const override {
return true; }
506 bool defineMacro(StringRef Name, StringRef
Value)
override;
508 bool lookUpField(StringRef Name, AsmFieldInfo &
Info)
const override;
509 bool lookUpField(StringRef
Base, StringRef Member,
510 AsmFieldInfo &
Info)
const override;
512 bool lookUpType(StringRef Name, AsmTypeInfo &
Info)
const override;
514 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
516 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
517 SmallVectorImpl<std::string> &Constraints,
518 SmallVectorImpl<std::string> &Clobbers,
519 const MCInstrInfo *MII, MCInstPrinter *IP,
520 MCAsmParserSemaCallback &SI)
override;
522 bool parseExpression(
const MCExpr *&Res);
523 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
524 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
525 AsmTypeInfo *TypeInfo)
override;
526 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
527 bool parseAbsoluteExpression(int64_t &Res)
override;
531 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
535 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
536 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
537 bool parseIdentifier(StringRef &Res)
override {
538 return parseIdentifier(Res, StandardPosition);
540 void eatToEndOfStatement()
override;
542 bool checkForValidSection()
override;
548 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
550 bool parseStatement(ParseStatementInfo &
Info,
551 MCAsmParserSemaCallback *SI);
552 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
553 bool parseCppHashLineFilenameComment(SMLoc L);
555 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
558 const std::vector<std::string> &Locals, SMLoc L);
561 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
567 bool handleMacroEntry(
568 const MCAsmMacro *M, SMLoc NameLoc,
575 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
578 void handleMacroExit();
582 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
587 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
590 void printMacroInstantiations();
592 bool expandStatement(SMLoc Loc);
595 SMRange
Range = std::nullopt)
const {
601 bool lookUpField(
const StructInfo &Structure, StringRef Member,
602 AsmFieldInfo &
Info)
const;
605 bool enterIncludeFile(
const std::string &Filename);
613 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
614 bool EndStatementAtEOF =
true);
626 StringRef parseStringToEndOfStatement()
override;
628 bool parseTextItem(std::string &
Data);
633 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
634 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
635 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
640 DK_HANDLER_DIRECTIVE,
730 StringMap<DirectiveKind> DirectiveKindMap;
732 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();
974MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
975 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
976 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
980 SavedDiagHandler =
SrcMgr.getDiagHandler();
981 SavedDiagContext =
SrcMgr.getDiagContext();
984 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
985 EndStatementAtEOFStack.push_back(
true);
988 switch (Ctx.getObjectFileType()) {
989 case MCContext::IsCOFF:
990 PlatformParser.reset(createCOFFMasmParser());
993 report_fatal_error(
"llvm-ml currently supports only COFF output.");
997 initializeDirectiveKindMap();
998 PlatformParser->Initialize(*
this);
999 initializeBuiltinSymbolMaps();
1001 NumOfMacroInstantiations = 0;
1004MasmParser::~MasmParser() {
1005 assert((HadError || ActiveMacros.empty()) &&
1006 "Unexpected active macro instantiation!");
1013void MasmParser::printMacroInstantiations() {
1015 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1016 it = ActiveMacros.rbegin(),
1017 ie = ActiveMacros.rend();
1020 "while in macro instantiation");
1023void MasmParser::Note(SMLoc L,
const Twine &Msg, SMRange
Range) {
1024 printPendingErrors();
1026 printMacroInstantiations();
1029bool MasmParser::Warning(SMLoc L,
const Twine &Msg, SMRange
Range) {
1030 if (getTargetParser().getTargetOptions().MCNoWarn)
1032 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1035 printMacroInstantiations();
1039bool MasmParser::printError(SMLoc L,
const Twine &Msg, SMRange
Range) {
1042 printMacroInstantiations();
1046bool MasmParser::enterIncludeFile(
const std::string &Filename) {
1047 std::string IncludedFile;
1055 EndStatementAtEOFStack.push_back(
true);
1059void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1060 bool EndStatementAtEOF) {
1066bool MasmParser::expandMacros() {
1067 const AsmToken &Tok = getTok();
1070 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1073 const SMLoc MacroLoc = Tok.
getLoc();
1076 if (handleMacroInvocation(M, MacroLoc)) {
1083 std::optional<std::string> ExpandedValue;
1085 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1086 BuiltinIt != BuiltinSymbolMap.end()) {
1088 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1089 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1090 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1092 if (parseIdentifier(Name)) {
1096 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1099 ExpandedValue = Res;
1100 }
else if (
auto VarIt = Variables.
find(IDLower);
1101 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1102 ExpandedValue = VarIt->getValue().TextValue;
1107 std::unique_ptr<MemoryBuffer> Instantiation =
1115 EndStatementAtEOFStack.push_back(
false);
1120const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1122 Error(Lexer.getErrLoc(), Lexer.getErr());
1123 bool StartOfStatement =
false;
1128 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1131 StartOfStatement =
true;
1134 const AsmToken *tok = &Lexer.Lex();
1137 if (StartOfStatement) {
1140 size_t ReadCount = Lexer.peekTokens(Buf);
1172 if (ParentIncludeLoc != SMLoc()) {
1173 EndStatementAtEOFStack.pop_back();
1174 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1177 EndStatementAtEOFStack.pop_back();
1178 assert(EndStatementAtEOFStack.empty());
1184const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1188 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1190 if (ReadCount == 0) {
1194 if (ParentIncludeLoc != SMLoc()) {
1195 EndStatementAtEOFStack.pop_back();
1196 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1197 return peekTok(ShouldSkipSpace);
1199 EndStatementAtEOFStack.pop_back();
1200 assert(EndStatementAtEOFStack.empty());
1207bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1209 if (!NoInitialTextSection)
1216 AsmCond StartingCondState = TheCondState;
1226 ParseStatementInfo
Info(&AsmStrRewrites);
1227 bool HasError = parseStatement(
Info,
nullptr);
1232 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1236 printPendingErrors();
1239 if (HasError && !getLexer().justConsumedEOL())
1240 eatToEndOfStatement();
1243 printPendingErrors();
1246 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1250 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1259 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1260 if (std::get<2>(LocSym)->isUndefined()) {
1263 CppHashInfo = std::get<1>(LocSym);
1264 printError(std::get<0>(LocSym),
"directional label undefined");
1271 if (!HadError && !NoFinalize)
1272 Out.
finish(Lexer.getLoc());
1277bool MasmParser::checkForValidSection() {
1278 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1279 getStreamer().getCurrentSectionOnly())) {
1281 return Error(getTok().getLoc(),
1282 "expected section directive before assembly directive");
1288void MasmParser::eatToEndOfStatement() {
1292 if (ParentIncludeLoc == SMLoc()) {
1296 EndStatementAtEOFStack.pop_back();
1297 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1308SmallVector<StringRef, 1>
1310 SmallVector<StringRef, 1> Refs;
1311 const char *
Start = getTok().getLoc().getPointer();
1312 while (Lexer.isNot(EndTok)) {
1315 if (ParentIncludeLoc == SMLoc()) {
1318 Refs.
emplace_back(Start, getTok().getLoc().getPointer() - Start);
1320 EndStatementAtEOFStack.pop_back();
1321 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1323 Start = getTok().getLoc().getPointer();
1328 Refs.
emplace_back(Start, getTok().getLoc().getPointer() - Start);
1333 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1335 for (StringRef S : Refs) {
1336 Str.append(S.str());
1341StringRef MasmParser::parseStringToEndOfStatement() {
1342 const char *
Start = getTok().getLoc().getPointer();
1347 const char *End = getTok().getLoc().getPointer();
1348 return StringRef(Start, End - Start);
1356bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1357 if (parseExpression(Res))
1359 EndLoc = Lexer.getTok().getEndLoc();
1360 return parseRParen();
1368bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1369 if (parseExpression(Res))
1371 EndLoc = getTok().getEndLoc();
1372 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1385bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1386 AsmTypeInfo *TypeInfo) {
1387 SMLoc FirstTokenLoc = getLexer().getLoc();
1389 switch (FirstTokenKind) {
1391 return TokError(
"unknown token in expression");
1397 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1405 if (parseIdentifier(Identifier)) {
1408 if (Lexer.getMAI().getDollarIsPC()) {
1415 EndLoc = FirstTokenLoc;
1418 return Error(FirstTokenLoc,
"invalid token in expression");
1423 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1431 bool Before =
Identifier.equals_insensitive(
"@b");
1434 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1444 return Error(getLexer().getLoc(),
"expected a symbol reference");
1449 if (
Split.second.empty()) {
1452 if (lookUpField(SymbolName,
Split.second,
Info)) {
1453 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1454 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1466 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1467 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1469 : BuiltinIt->getValue();
1470 if (Symbol != BI_NO_SYMBOL) {
1471 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1481 if (VarIt != Variables.
end())
1492 DoInline = TV->inlineAssignedExpr();
1500 const MCExpr *SymRef =
1510 if (
Info.Type.Name.empty()) {
1512 if (TypeIt != KnownType.
end()) {
1513 Info.Type = TypeIt->second;
1517 *TypeInfo =
Info.Type;
1522 return TokError(
"literal value out of range for directive");
1524 int64_t
IntVal = getTok().getIntVal();
1526 EndLoc = Lexer.getTok().getEndLoc();
1532 SMLoc ValueLoc = getTok().getLoc();
1534 if (parseEscapedString(
Value))
1536 if (
Value.size() > 8)
1537 return Error(ValueLoc,
"literal value out of range");
1538 uint64_t IntValue = 0;
1539 for (
const unsigned char CharVal :
Value)
1540 IntValue = (IntValue << 8) | CharVal;
1545 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1546 uint64_t
IntVal = RealVal.bitcastToAPInt().getZExtValue();
1548 EndLoc = Lexer.getTok().getEndLoc();
1558 EndLoc = Lexer.getTok().getEndLoc();
1564 return parseParenExpr(Res, EndLoc);
1566 if (!PlatformParser->HasBracketExpressions())
1567 return TokError(
"brackets expression not supported on this target");
1569 return parseBracketExpr(Res, EndLoc);
1572 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1578 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1584 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1591bool MasmParser::parseExpression(
const MCExpr *&Res) {
1593 return parseExpression(Res, EndLoc);
1604 "Argument to the function cannot be a NULL value");
1606 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1607 (*CharPtr !=
'\0')) {
1608 if (*CharPtr ==
'!')
1612 if (*CharPtr ==
'>') {
1622 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1623 if (BracketContents[Pos] ==
'!')
1625 Res += BracketContents[Pos];
1640bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1643 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1644 parseBinOpRHS(1, Res, EndLoc))
1650 if (Res->evaluateAsAbsolute(
Value))
1656bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1658 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1661bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1664 SMLoc StartLoc = Lexer.getLoc();
1665 if (parseExpression(Expr))
1668 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1669 return Error(StartLoc,
"expected absolute expression");
1676 bool ShouldUseLogicalShr,
1677 bool EndExpressionAtGreater) {
1705 if (EndExpressionAtGreater)
1746 if (EndExpressionAtGreater)
1757 AngleBracketDepth > 0);
1762bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1764 SMLoc StartLoc = Lexer.getLoc();
1768 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1784 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1788 if (TokPrec < Precedence)
1795 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1801 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1802 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1815bool MasmParser::parseStatement(ParseStatementInfo &
Info,
1816 MCAsmParserSemaCallback *SI) {
1817 assert(!hasPendingError() &&
"parseStatement started with pending error");
1823 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1824 getTok().getString().
front() ==
'\n')
1833 SMLoc ExpansionLoc = getTok().getLoc();
1840 AsmToken
ID = getTok();
1841 SMLoc IDLoc =
ID.getLoc();
1844 return parseCppHashLineFilenameComment(IDLoc);
1851 IDVal = getTok().getString();
1854 return Error(IDLoc,
"unexpected token at start of statement");
1855 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1856 if (!TheCondState.
Ignore) {
1858 return Error(IDLoc,
"unexpected token at start of statement");
1867 DirectiveKindMap.find(IDVal.
lower());
1868 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1870 : DirKindIt->getValue();
1876 return parseDirectiveIf(IDLoc, DirKind);
1878 return parseDirectiveIfb(IDLoc,
true);
1880 return parseDirectiveIfb(IDLoc,
false);
1882 return parseDirectiveIfdef(IDLoc,
true);
1884 return parseDirectiveIfdef(IDLoc,
false);
1886 return parseDirectiveIfidn(IDLoc,
false,
1889 return parseDirectiveIfidn(IDLoc,
false,
1892 return parseDirectiveIfidn(IDLoc,
true,
1895 return parseDirectiveIfidn(IDLoc,
true,
1899 return parseDirectiveElseIf(IDLoc, DirKind);
1901 return parseDirectiveElseIfb(IDLoc,
true);
1903 return parseDirectiveElseIfb(IDLoc,
false);
1905 return parseDirectiveElseIfdef(IDLoc,
true);
1907 return parseDirectiveElseIfdef(IDLoc,
false);
1909 return parseDirectiveElseIfidn(IDLoc,
false,
1912 return parseDirectiveElseIfidn(IDLoc,
false,
1915 return parseDirectiveElseIfidn(IDLoc,
true,
1918 return parseDirectiveElseIfidn(IDLoc,
true,
1921 return parseDirectiveElse(IDLoc);
1923 return parseDirectiveEndIf(IDLoc);
1928 if (TheCondState.
Ignore) {
1929 eatToEndOfStatement();
1939 if (checkForValidSection())
1947 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1955 if (ParsingMSInlineAsm && SI) {
1956 StringRef RewrittenLabel =
1957 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1959 "We should have an internal name here.");
1962 IDVal = RewrittenLabel;
1965 if (IDVal ==
"@@") {
1988 if (!getTargetParser().isParsingMSInlineAsm())
1998 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2003 if (DirKind != DK_NO_DIRECTIVE) {
2019 return parseDirectiveNestedEnds();
2024 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2027 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2033 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(
ID);
2035 "Should only return Failure iff there was an error");
2047 return parseDirectiveAscii(IDVal,
false);
2050 return parseDirectiveAscii(IDVal,
true);
2054 return parseDirectiveValue(IDVal, 1);
2058 return parseDirectiveValue(IDVal, 2);
2062 return parseDirectiveValue(IDVal, 4);
2065 return parseDirectiveValue(IDVal, 6);
2069 return parseDirectiveValue(IDVal, 8);
2071 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2073 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2075 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2078 return parseDirectiveNestedStruct(IDVal, DirKind);
2080 return parseDirectiveNestedEnds();
2082 return parseDirectiveAlign();
2084 return parseDirectiveEven();
2086 return parseDirectiveOrg();
2088 return parseDirectiveExtern();
2090 return parseDirectiveSymbolAttribute(
MCSA_Global);
2092 return parseDirectiveComm(
false);
2094 return parseDirectiveComment(IDLoc);
2096 return parseDirectiveInclude();
2098 return parseDirectiveRepeat(IDLoc, IDVal);
2100 return parseDirectiveWhile(IDLoc);
2102 return parseDirectiveFor(IDLoc, IDVal);
2104 return parseDirectiveForc(IDLoc, IDVal);
2106 Info.ExitValue =
"";
2107 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2109 Info.ExitValue =
"";
2110 return parseDirectiveEndMacro(IDVal);
2112 return parseDirectivePurgeMacro(IDLoc);
2114 return parseDirectiveEnd(IDLoc);
2116 return parseDirectiveError(IDLoc);
2118 return parseDirectiveErrorIfb(IDLoc,
true);
2120 return parseDirectiveErrorIfb(IDLoc,
false);
2122 return parseDirectiveErrorIfdef(IDLoc,
true);
2124 return parseDirectiveErrorIfdef(IDLoc,
false);
2126 return parseDirectiveErrorIfidn(IDLoc,
false,
2129 return parseDirectiveErrorIfidn(IDLoc,
false,
2132 return parseDirectiveErrorIfidn(IDLoc,
true,
2135 return parseDirectiveErrorIfidn(IDLoc,
true,
2138 return parseDirectiveErrorIfe(IDLoc,
true);
2140 return parseDirectiveErrorIfe(IDLoc,
false);
2142 return parseDirectiveRadix(IDLoc);
2144 return parseDirectiveEcho(IDLoc);
2147 return Error(IDLoc,
"unknown directive");
2151 auto IDIt = Structs.
find(IDVal.
lower());
2152 if (IDIt != Structs.
end())
2153 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2157 const AsmToken nextTok = getTok();
2158 const StringRef nextVal = nextTok.
getString();
2159 const SMLoc nextLoc = nextTok.
getLoc();
2161 const AsmToken afterNextTok = peekTok();
2172 getTargetParser().flushPendingInstructions(getStreamer());
2178 return parseDirectiveEnds(IDVal, IDLoc);
2183 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2185 if (Handler.first) {
2188 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2193 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2194 DirKind = (DirKindIt == DirectiveKindMap.end())
2196 : DirKindIt->getValue();
2204 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2215 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2226 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2237 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2247 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2258 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2261 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2265 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2269 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2274 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2277 return parseDirectiveEnds(IDVal, IDLoc);
2280 return parseDirectiveMacro(IDVal, IDLoc);
2284 auto NextIt = Structs.
find(nextVal.
lower());
2285 if (NextIt != Structs.
end()) {
2287 return parseDirectiveNamedStructValue(NextIt->getValue(),
2288 nextVal, nextLoc, IDVal);
2292 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2293 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2294 return parseDirectiveMSEmit(IDLoc,
Info, IDVal.
size());
2297 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2298 return parseDirectiveMSAlign(IDLoc,
Info);
2300 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2302 if (checkForValidSection())
2306 std::string OpcodeStr = IDVal.
lower();
2307 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2308 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr,
ID,
2309 Info.ParsedOperands);
2310 Info.ParseError = ParseHadError;
2313 if (getShowParsedOperands()) {
2314 SmallString<256> Str;
2315 raw_svector_ostream OS(Str);
2316 OS <<
"parsed instruction: [";
2317 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2320 Info.ParsedOperands[i]->print(OS, MAI);
2328 if (hasPendingError() || ParseHadError)
2332 if (!ParseHadError) {
2334 if (getTargetParser().matchAndEmitInstruction(
2335 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2336 getTargetParser().isParsingMSInlineAsm()))
2343bool MasmParser::parseCurlyBlockScope(
2344 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2349 SMLoc StartLoc = Lexer.getLoc();
2362bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2367 "Lexing Cpp line comment: Expected Integer");
2368 int64_t LineNumber = getTok().getIntVal();
2371 "Lexing Cpp line comment: Expected String");
2372 StringRef
Filename = getTok().getString();
2380 CppHashInfo.Loc =
L;
2382 CppHashInfo.LineNumber = LineNumber;
2383 CppHashInfo.Buf = CurBuffer;
2384 if (FirstCppHashFilename.
empty())
2391void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2392 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2393 raw_ostream &OS =
errs();
2396 SMLoc DiagLoc = Diag.
getLoc();
2398 unsigned CppHashBuf =
2399 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2404 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2413 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2414 DiagBuf != CppHashBuf) {
2415 if (Parser->SavedDiagHandler)
2416 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2418 Diag.
print(
nullptr, OS);
2425 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2428 int CppHashLocLineNo =
2429 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2431 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2437 if (Parser->SavedDiagHandler)
2438 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2440 NewDiag.print(
nullptr, OS);
2446 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2449bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2452 const std::vector<std::string> &Locals, SMLoc L) {
2454 if (NParameters !=
A.size())
2455 return Error(L,
"Wrong number of arguments");
2456 StringMap<std::string> LocalSymbols;
2459 for (StringRef
Local : Locals) {
2460 raw_string_ostream LocalName(Name);
2467 std::optional<char> CurrentQuote;
2468 while (!Body.
empty()) {
2470 std::size_t End = Body.
size(), Pos = 0;
2471 std::size_t IdentifierPos = End;
2472 for (; Pos != End; ++Pos) {
2475 if (Body[Pos] ==
'&')
2480 if (IdentifierPos == End)
2481 IdentifierPos = Pos;
2483 IdentifierPos = End;
2487 if (!CurrentQuote) {
2488 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2489 CurrentQuote = Body[Pos];
2490 }
else if (Body[Pos] == CurrentQuote) {
2491 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2496 CurrentQuote.reset();
2500 if (IdentifierPos != End) {
2503 Pos = IdentifierPos;
2504 IdentifierPos = End;
2508 OS << Body.
slice(0, Pos);
2515 bool InitialAmpersand = (Body[
I] ==
'&');
2516 if (InitialAmpersand) {
2523 const char *Begin = Body.
data() + Pos;
2525 const std::string ArgumentLower =
Argument.lower();
2529 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2532 if (Index == NParameters) {
2533 if (InitialAmpersand)
2535 auto it = LocalSymbols.
find(ArgumentLower);
2536 if (it != LocalSymbols.
end())
2542 for (
const AsmToken &Token :
A[Index]) {
2552 OS << Token.getIntVal();
2554 OS << Token.getString();
2558 if (Pos < End && Body[Pos] ==
'&') {
2569bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2570 MCAsmMacroArgument &MA,
2573 if (Lexer.isNot(EndTok)) {
2574 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2575 for (StringRef S : Str) {
2582 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2584 const char *StrChar = StrLoc.
getPointer() + 1;
2585 const char *EndChar = EndLoc.
getPointer() - 1;
2586 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2593 unsigned ParenLevel = 0;
2597 return TokError(
"unexpected token");
2614 MA.push_back(getTok());
2618 if (ParenLevel != 0)
2619 return TokError(
"unbalanced parentheses in argument");
2621 if (MA.empty() && MP) {
2623 return TokError(
"missing value for required parameter '" + MP->
Name +
2633bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2634 MCAsmMacroArguments &
A,
2636 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2637 bool NamedParametersFound =
false;
2638 SmallVector<SMLoc, 4> FALocs;
2640 A.resize(NParameters);
2641 FALocs.
resize(NParameters);
2646 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2648 SMLoc IDLoc = Lexer.getLoc();
2649 MCAsmMacroParameter FA;
2652 if (parseIdentifier(FA.
Name))
2653 return Error(IDLoc,
"invalid argument identifier for formal argument");
2656 return TokError(
"expected '=' after formal parameter identifier");
2660 NamedParametersFound =
true;
2663 if (NamedParametersFound && FA.
Name.
empty())
2664 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2668 assert(M &&
"expected macro to be defined");
2670 for (FAI = 0; FAI < NParameters; ++FAI)
2671 if (
M->Parameters[FAI].Name == FA.
Name)
2674 if (FAI >= NParameters) {
2675 return Error(IDLoc,
"parameter named '" + FA.
Name +
2676 "' does not exist for macro '" +
M->Name +
"'");
2680 const MCAsmMacroParameter *MP =
nullptr;
2681 if (M && PI < NParameters)
2682 MP = &
M->Parameters[PI];
2684 SMLoc StrLoc = Lexer.getLoc();
2687 const MCExpr *AbsoluteExp;
2691 if (parseExpression(AbsoluteExp, EndLoc))
2693 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2694 getStreamer().getAssemblerPtr()))
2695 return Error(StrLoc,
"expected absolute expression");
2699 StringRef(StrChar, EndChar - StrChar),
Value);
2700 FA.
Value.push_back(newToken);
2701 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2703 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2708 if (!FA.
Value.empty()) {
2713 if (FALocs.
size() <= PI)
2716 FALocs[PI] = Lexer.getLoc();
2722 if (Lexer.is(EndTok)) {
2724 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2726 if (
M->Parameters[FAI].Required) {
2727 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2728 "missing value for required parameter "
2730 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2734 if (!
M->Parameters[FAI].Value.empty())
2735 A[FAI] =
M->Parameters[FAI].Value;
2745 return TokError(
"too many positional arguments");
2748bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2753 if (ActiveMacros.size() == MaxNestingDepth) {
2754 std::ostringstream MaxNestingDepthError;
2755 MaxNestingDepthError <<
"macros cannot be nested more than "
2756 << MaxNestingDepth <<
" levels deep."
2757 <<
" Use -asm-macro-max-nesting-depth to increase "
2759 return TokError(MaxNestingDepthError.str());
2762 MCAsmMacroArguments
A;
2763 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2768 SmallString<256> Buf;
2769 StringRef Body =
M->Body;
2770 raw_svector_ostream OS(Buf);
2772 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2779 std::unique_ptr<MemoryBuffer> Instantiation =
2784 MacroInstantiation *
MI =
new MacroInstantiation{
2785 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2786 ActiveMacros.push_back(
MI);
2788 ++NumOfMacroInstantiations;
2793 EndStatementAtEOFStack.push_back(
true);
2799void MasmParser::handleMacroExit() {
2801 EndStatementAtEOFStack.pop_back();
2802 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2803 EndStatementAtEOFStack.back());
2807 delete ActiveMacros.back();
2808 ActiveMacros.pop_back();
2811bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2813 return Error(NameLoc,
"cannot invoke macro procedure as function");
2816 "' requires arguments in parentheses") ||
2821 std::string ExitValue;
2824 ParseStatementInfo
Info(&AsmStrRewrites);
2825 bool HasError = parseStatement(
Info,
nullptr);
2827 if (!HasError &&
Info.ExitValue) {
2828 ExitValue = std::move(*
Info.ExitValue);
2835 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2839 printPendingErrors();
2842 if (HasError && !getLexer().justConsumedEOL())
2843 eatToEndOfStatement();
2848 std::unique_ptr<MemoryBuffer> MacroValue =
2856 EndStatementAtEOFStack.push_back(
false);
2865bool MasmParser::parseIdentifier(StringRef &Res,
2866 IdentifierPositionKind Position) {
2873 SMLoc PrefixLoc = getLexer().getLoc();
2877 AsmToken nextTok = peekTok(
false);
2890 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2898 Res = getTok().getIdentifier();
2902 ExpandKind ExpandNextToken = ExpandMacros;
2903 if (Position == StartOfStatement &&
2904 StringSwitch<bool>(Res)
2905 .CaseLower(
"echo",
true)
2906 .CasesLower(
"ifdef",
"ifndef",
"elseifdef",
"elseifndef",
true)
2908 ExpandNextToken = DoNotExpandMacros;
2910 Lex(ExpandNextToken);
2920bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2921 DirectiveKind DirKind, SMLoc NameLoc) {
2922 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2923 if (BuiltinIt != BuiltinSymbolMap.end())
2924 return Error(NameLoc,
"cannot redefine a built-in symbol");
2927 if (Var.Name.empty()) {
2931 SMLoc StartLoc = Lexer.getLoc();
2932 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2935 std::string TextItem;
2936 if (!parseTextItem(TextItem)) {
2940 auto parseItem = [&]() ->
bool {
2941 if (parseTextItem(TextItem))
2942 return TokError(
"expected text item");
2947 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2949 if (!Var.IsText || Var.TextValue !=
Value) {
2950 switch (Var.Redefinable) {
2951 case Variable::NOT_REDEFINABLE:
2952 return Error(getTok().getLoc(),
"invalid variable redefinition");
2953 case Variable::WARN_ON_REDEFINITION:
2954 if (
Warning(NameLoc,
"redefining '" + Name +
2955 "', already defined on the command line")) {
2964 Var.TextValue =
Value;
2965 Var.Redefinable = Variable::REDEFINABLE;
2970 if (DirKind == DK_TEXTEQU)
2971 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2976 if (parseExpression(Expr, EndLoc))
2977 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2978 StringRef ExprAsString = StringRef(
2982 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2983 if (DirKind == DK_ASSIGN)
2986 "expected absolute expression; not all symbols have known values",
2987 {StartLoc, EndLoc});
2990 if (!Var.IsText || Var.TextValue != ExprAsString) {
2991 switch (Var.Redefinable) {
2992 case Variable::NOT_REDEFINABLE:
2993 return Error(getTok().getLoc(),
"invalid variable redefinition");
2994 case Variable::WARN_ON_REDEFINITION:
2995 if (
Warning(NameLoc,
"redefining '" + Name +
2996 "', already defined on the command line")) {
3006 Var.TextValue = ExprAsString.
str();
3007 Var.Redefinable = Variable::REDEFINABLE;
3012 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
3013 const MCConstantExpr *PrevValue =
3017 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
3018 switch (Var.Redefinable) {
3019 case Variable::NOT_REDEFINABLE:
3020 return Error(getTok().getLoc(),
"invalid variable redefinition");
3021 case Variable::WARN_ON_REDEFINITION:
3022 if (
Warning(NameLoc,
"redefining '" + Name +
3023 "', already defined on the command line")) {
3033 Var.TextValue.clear();
3034 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3037 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3039 Sym->setExternal(
false);
3044bool MasmParser::parseEscapedString(std::string &
Data) {
3049 char Quote = getTok().getString().front();
3050 StringRef Str = getTok().getStringContents();
3051 Data.reserve(Str.size());
3052 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3053 Data.push_back(Str[i]);
3054 if (Str[i] == Quote) {
3058 if (i + 1 == Str.size())
3059 return Error(getTok().getLoc(),
"missing quotation mark in string");
3060 if (Str[i + 1] == Quote)
3069bool MasmParser::parseAngleBracketString(std::string &
Data) {
3070 SMLoc EndLoc, StartLoc = getTok().getLoc();
3072 const char *StartChar = StartLoc.
getPointer() + 1;
3073 const char *EndChar = EndLoc.
getPointer() - 1;
3074 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3085bool MasmParser::parseTextItem(std::string &
Data) {
3086 switch (getTok().getKind()) {
3093 Data = std::to_string(Res);
3100 return parseAngleBracketString(
Data);
3104 SMLoc StartLoc = getTok().getLoc();
3105 if (parseIdentifier(
ID))
3109 bool Expanded =
false;
3112 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3113 if (BuiltinIt != BuiltinSymbolMap.end()) {
3114 std::optional<std::string> BuiltinText =
3115 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3120 Data = std::move(*BuiltinText);
3127 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3128 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3130 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(),
ID,
Data)) {
3139 auto VarIt = Variables.
find(
ID.lower());
3140 if (VarIt != Variables.
end()) {
3141 const Variable &Var = VarIt->getValue();
3146 Data = Var.TextValue;
3169bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3170 auto parseOp = [&]() ->
bool {
3172 if (checkForValidSection() || parseEscapedString(
Data))
3174 getStreamer().emitBytes(
Data);
3176 getStreamer().emitBytes(StringRef(
"\0", 1));
3180 if (parseMany(parseOp))
3181 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3185bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3189 int64_t IntValue = MCE->getValue();
3191 return Error(MCE->getLoc(),
"out of range literal value");
3192 getStreamer().emitIntValue(IntValue,
Size);
3197 getStreamer().emitIntValue(0,
Size);
3205bool MasmParser::parseScalarInitializer(
unsigned Size,
3206 SmallVectorImpl<const MCExpr *> &Values,
3207 unsigned StringPadLength) {
3210 if (parseEscapedString(
Value))
3213 for (
const unsigned char CharVal :
Value)
3217 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3220 const MCExpr *
Value;
3221 if (parseExpression(
Value))
3224 getTok().getString().equals_insensitive(
"dup")) {
3229 "cannot repeat value a non-constant number of times");
3230 const int64_t Repetitions = MCE->
getValue();
3231 if (Repetitions < 0)
3233 "cannot repeat value a negative number of times");
3237 "parentheses required for 'dup' contents") ||
3238 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3241 for (
int i = 0; i < Repetitions; ++i)
3250bool MasmParser::parseScalarInstList(
unsigned Size,
3251 SmallVectorImpl<const MCExpr *> &Values,
3253 while (getTok().
isNot(EndToken) &&
3256 parseScalarInitializer(
Size, Values);
3266bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3268 if (checkForValidSection() || parseScalarInstList(
Size, Values))
3271 for (
const auto *
Value : Values) {
3275 *
Count = Values.size();
3280bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3281 StructInfo &
Struct = StructInProgress.
back();
3283 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3287 if (parseScalarInstList(
Size, IntInfo.Values))
3290 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3291 Field.LengthOf = IntInfo.Values.size();
3294 Struct.NextOffset = FieldEnd;
3302bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3303 if (StructInProgress.
empty()) {
3305 if (emitIntegralValues(
Size))
3306 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3307 }
else if (addIntegralField(
"",
Size)) {
3308 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3316bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3317 StringRef Name, SMLoc NameLoc) {
3318 if (StructInProgress.
empty()) {
3321 getStreamer().emitLabel(Sym);
3324 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3332 }
else if (addIntegralField(Name,
Size)) {
3333 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3339bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3345 SignLoc = getLexer().getLoc();
3349 SignLoc = getLexer().getLoc();
3354 return TokError(Lexer.getErr());
3357 return TokError(
"unexpected token in directive");
3361 StringRef IDVal = getTok().getString();
3370 return TokError(
"invalid floating point literal");
3374 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3375 if (SizeInBits != (IDVal.
size() << 2))
3376 return TokError(
"invalid floating point literal");
3381 Res = APInt(SizeInBits, IDVal, 16);
3383 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3386 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3388 return TokError(
"invalid floating point literal");
3396 Res =
Value.bitcastToAPInt();
3401bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3402 SmallVectorImpl<APInt> &ValuesAsInt,
3404 while (getTok().
isNot(EndToken) ||
3407 const AsmToken NextTok = peekTok();
3410 const MCExpr *
Value;
3416 "cannot repeat value a non-constant number of times");
3417 const int64_t Repetitions = MCE->
getValue();
3418 if (Repetitions < 0)
3420 "cannot repeat value a negative number of times");
3424 "parentheses required for 'dup' contents") ||
3425 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3428 for (
int i = 0; i < Repetitions; ++i)
3429 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3432 if (parseRealValue(Semantics, AsInt))
3447bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3449 if (checkForValidSection())
3453 if (parseRealInstList(Semantics, ValuesAsInt))
3456 for (
const APInt &AsInt : ValuesAsInt) {
3457 getStreamer().emitIntValue(AsInt);
3460 *
Count = ValuesAsInt.size();
3465bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3467 StructInfo &
Struct = StructInProgress.
back();
3469 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3473 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3476 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3477 Field.LengthOf = RealInfo.AsIntValues.size();
3482 Struct.NextOffset = FieldEnd;
3490bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3491 const fltSemantics &Semantics,
3493 if (StructInProgress.
empty()) {
3495 if (emitRealValues(Semantics))
3496 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3497 }
else if (addRealField(
"", Semantics,
Size)) {
3498 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3505bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3506 const fltSemantics &Semantics,
3507 unsigned Size, StringRef Name,
3509 if (StructInProgress.
empty()) {
3512 getStreamer().emitLabel(Sym);
3514 if (emitRealValues(Semantics, &
Count))
3515 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3523 }
else if (addRealField(Name, Semantics,
Size)) {
3524 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3529bool MasmParser::parseOptionalAngleBracketOpen() {
3530 const AsmToken Tok = getTok();
3532 AngleBracketDepth++;
3536 AngleBracketDepth++;
3540 AngleBracketDepth++;
3547bool MasmParser::parseAngleBracketClose(
const Twine &Msg) {
3548 const AsmToken Tok = getTok();
3554 AngleBracketDepth--;
3558bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3559 const IntFieldInfo &Contents,
3560 FieldInitializer &Initializer) {
3561 SMLoc Loc = getTok().getLoc();
3566 return Error(Loc,
"Cannot initialize scalar field with array value");
3570 }
else if (parseOptionalAngleBracketOpen()) {
3572 return Error(Loc,
"Cannot initialize scalar field with array value");
3574 parseAngleBracketClose())
3576 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3577 return Error(Loc,
"Cannot initialize array field with scalar value");
3578 }
else if (parseScalarInitializer(
Field.Type, Values,
3584 return Error(Loc,
"Initializer too long for field; expected at most " +
3585 std::to_string(
Field.LengthOf) +
" elements, got " +
3586 std::to_string(Values.
size()));
3589 Values.
append(Contents.Values.begin() + Values.
size(), Contents.Values.end());
3591 Initializer = FieldInitializer(std::move(Values));
3595bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3596 const RealFieldInfo &Contents,
3597 FieldInitializer &Initializer) {
3598 const fltSemantics *Semantics;
3599 switch (
Field.Type) {
3601 Semantics = &APFloat::IEEEsingle();
3604 Semantics = &APFloat::IEEEdouble();
3607 Semantics = &APFloat::x87DoubleExtended();
3613 SMLoc Loc = getTok().getLoc();
3617 if (
Field.LengthOf == 1)
3618 return Error(Loc,
"Cannot initialize scalar field with array value");
3622 }
else if (parseOptionalAngleBracketOpen()) {
3623 if (
Field.LengthOf == 1)
3624 return Error(Loc,
"Cannot initialize scalar field with array value");
3626 parseAngleBracketClose())
3628 }
else if (
Field.LengthOf > 1) {
3629 return Error(Loc,
"Cannot initialize array field with scalar value");
3632 if (parseRealValue(*Semantics, AsIntValues.
back()))
3636 if (AsIntValues.
size() >
Field.LengthOf) {
3637 return Error(Loc,
"Initializer too long for field; expected at most " +
3638 std::to_string(
Field.LengthOf) +
" elements, got " +
3639 std::to_string(AsIntValues.
size()));
3642 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3643 Contents.AsIntValues.end());
3645 Initializer = FieldInitializer(std::move(AsIntValues));
3649bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3650 const StructFieldInfo &Contents,
3651 FieldInitializer &Initializer) {
3652 SMLoc Loc = getTok().getLoc();
3654 std::vector<StructInitializer> Initializers;
3655 if (
Field.LengthOf > 1) {
3657 if (parseStructInstList(Contents.Structure, Initializers,
3661 }
else if (parseOptionalAngleBracketOpen()) {
3662 if (parseStructInstList(Contents.Structure, Initializers,
3664 parseAngleBracketClose())
3667 return Error(Loc,
"Cannot initialize array field with scalar value");
3670 Initializers.emplace_back();
3671 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3675 if (Initializers.size() >
Field.LengthOf) {
3676 return Error(Loc,
"Initializer too long for field; expected at most " +
3677 std::to_string(
Field.LengthOf) +
" elements, got " +
3678 std::to_string(Initializers.size()));
3682 Initializers.size()));
3684 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3688bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3689 FieldInitializer &Initializer) {
3690 switch (
Field.Contents.FT) {
3692 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3694 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3696 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3701bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3702 StructInitializer &Initializer) {
3703 const AsmToken FirstToken = getTok();
3705 std::optional<AsmToken::TokenKind> EndToken;
3708 }
else if (parseOptionalAngleBracketOpen()) {
3710 AngleBracketDepth++;
3717 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3720 auto &FieldInitializers = Initializer.FieldInitializers;
3721 size_t FieldIndex = 0;
3724 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3725 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3729 FieldInitializers.push_back(
Field.Contents);
3733 FieldInitializers.emplace_back(
Field.Contents.FT);
3734 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3738 SMLoc CommaLoc = getTok().getLoc();
3741 if (FieldIndex == Structure.Fields.size())
3742 return Error(CommaLoc,
"'" + Structure.Name +
3743 "' initializer initializes too many fields");
3749 FieldInitializers.push_back(
Field.Contents);
3753 return parseAngleBracketClose();
3755 return parseToken(*EndToken);
3761bool MasmParser::parseStructInstList(
3762 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3764 while (getTok().
isNot(EndToken) ||
3767 const AsmToken NextTok = peekTok();
3770 const MCExpr *
Value;
3776 "cannot repeat value a non-constant number of times");
3777 const int64_t Repetitions = MCE->
getValue();
3778 if (Repetitions < 0)
3780 "cannot repeat value a negative number of times");
3782 std::vector<StructInitializer> DuplicatedValues;
3784 "parentheses required for 'dup' contents") ||
3785 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3788 for (
int i = 0; i < Repetitions; ++i)
3791 Initializers.emplace_back();
3792 if (parseStructInitializer(Structure, Initializers.back()))
3805bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3806 const IntFieldInfo &Contents) {
3808 for (
const MCExpr *
Value : Contents.Values) {
3815bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3816 const RealFieldInfo &Contents) {
3817 for (
const APInt &AsInt : Contents.AsIntValues) {
3824bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3825 const StructFieldInfo &Contents) {
3826 for (
const auto &Initializer : Contents.Initializers) {
3828 for (
const auto &SubField : Contents.Structure.Fields) {
3829 getStreamer().emitZeros(SubField.Offset -
Offset);
3830 Offset = SubField.Offset + SubField.SizeOf;
3831 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3837bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3838 switch (
Field.Contents.FT) {
3840 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3842 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3844 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3849bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3850 const IntFieldInfo &Contents,
3851 const IntFieldInfo &Initializer) {
3852 for (
const auto &
Value : Initializer.Values) {
3857 for (
const auto &
Value :
3865bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3866 const RealFieldInfo &Contents,
3867 const RealFieldInfo &Initializer) {
3868 for (
const auto &AsInt : Initializer.AsIntValues) {
3873 for (
const auto &AsInt :
3881bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3882 const StructFieldInfo &Contents,
3883 const StructFieldInfo &Initializer) {
3884 for (
const auto &Init : Initializer.Initializers) {
3885 if (emitStructInitializer(Contents.Structure, Init))
3890 Initializer.Initializers.size())) {
3891 if (emitStructInitializer(Contents.Structure, Init))
3897bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3898 const FieldInitializer &Initializer) {
3899 switch (
Field.Contents.FT) {
3901 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3902 Initializer.IntInfo);
3904 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3905 Initializer.RealInfo);
3907 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3908 Initializer.StructInfo);
3913bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3914 const StructInitializer &Initializer) {
3915 if (!Structure.Initializable)
3916 return Error(getLexer().getLoc(),
3917 "cannot initialize a value of type '" + Structure.Name +
3918 "'; 'org' was used in the type's declaration");
3920 for (
const auto &Init : Initializer.FieldInitializers) {
3921 const auto &
Field = Structure.Fields[
Index++];
3924 if (emitFieldInitializer(
Field, Init))
3929 Structure.Fields, Initializer.FieldInitializers.size())) {
3932 if (emitFieldValue(
Field))
3936 if (
Offset != Structure.Size)
3937 getStreamer().emitZeros(Structure.Size -
Offset);
3942bool MasmParser::emitStructValues(
const StructInfo &Structure,
3944 std::vector<StructInitializer> Initializers;
3945 if (parseStructInstList(Structure, Initializers))
3948 for (
const auto &Initializer : Initializers) {
3949 if (emitStructInitializer(Structure, Initializer))
3954 *
Count = Initializers.size();
3959bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3960 StructInfo &OwningStruct = StructInProgress.
back();
3962 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3963 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3965 StructInfo.Structure = Structure;
3966 Field.Type = Structure.Size;
3968 if (parseStructInstList(Structure, StructInfo.Initializers))
3971 Field.LengthOf = StructInfo.Initializers.size();
3975 if (!OwningStruct.IsUnion) {
3976 OwningStruct.NextOffset = FieldEnd;
3978 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3986bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3987 StringRef Directive, SMLoc DirLoc) {
3988 if (StructInProgress.
empty()) {
3989 if (emitStructValues(Structure))
3991 }
else if (addStructField(
"", Structure)) {
3992 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4000bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
4001 StringRef Directive,
4002 SMLoc DirLoc, StringRef Name) {
4003 if (StructInProgress.
empty()) {
4006 getStreamer().emitLabel(Sym);
4008 if (emitStructValues(Structure, &
Count))
4011 Type.Name = Structure.Name;
4013 Type.ElementSize = Structure.Size;
4016 }
else if (addStructField(Name, Structure)) {
4017 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4029bool MasmParser::parseDirectiveStruct(StringRef Directive,
4030 DirectiveKind DirKind, StringRef Name,
4034 AsmToken NextTok = getTok();
4035 int64_t AlignmentValue = 1;
4038 parseAbsoluteExpression(AlignmentValue)) {
4039 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4043 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4044 std::to_string(AlignmentValue));
4050 QualifierLoc = getTok().getLoc();
4051 if (parseIdentifier(Qualifier))
4052 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4053 if (!
Qualifier.equals_insensitive(
"nonunique"))
4054 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4056 "' directive; expected none or NONUNIQUE");
4060 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4062 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4070bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4071 DirectiveKind DirKind) {
4072 if (StructInProgress.
empty())
4073 return TokError(
"missing name in top-level '" + Twine(Directive) +
4078 Name = getTok().getIdentifier();
4082 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4086 StructInProgress.
reserve(StructInProgress.
size() + 1);
4087 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4088 StructInProgress.
back().Alignment);
4092bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4093 if (StructInProgress.
empty())
4094 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4095 if (StructInProgress.
size() > 1)
4096 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4097 if (StructInProgress.
back().Name.compare_insensitive(Name))
4098 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4099 StructInProgress.
back().Name +
"'");
4100 StructInfo Structure = StructInProgress.
pop_back_val();
4104 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4105 Structs[
Name.lower()] = Structure;
4108 return addErrorSuffix(
" in ENDS directive");
4113bool MasmParser::parseDirectiveNestedEnds() {
4114 if (StructInProgress.
empty())
4115 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4116 if (StructInProgress.
size() == 1)
4117 return TokError(
"missing name in top-level ENDS directive");
4120 return addErrorSuffix(
" in nested ENDS directive");
4122 StructInfo Structure = StructInProgress.
pop_back_val();
4124 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4126 StructInfo &ParentStruct = StructInProgress.
back();
4127 if (Structure.Name.
empty()) {
4130 const size_t OldFields = ParentStruct.Fields.size();
4131 ParentStruct.Fields.insert(
4132 ParentStruct.Fields.end(),
4133 std::make_move_iterator(Structure.Fields.begin()),
4134 std::make_move_iterator(Structure.Fields.end()));
4135 for (
const auto &FieldByName : Structure.FieldsByName) {
4136 ParentStruct.FieldsByName[FieldByName.getKey()] =
4137 FieldByName.getValue() + OldFields;
4140 unsigned FirstFieldOffset = 0;
4141 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4143 ParentStruct.NextOffset,
4144 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4147 if (ParentStruct.IsUnion) {
4148 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4153 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4154 if (!ParentStruct.IsUnion) {
4155 ParentStruct.NextOffset = StructureEnd;
4157 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4160 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4161 Structure.AlignmentSize);
4162 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4163 Field.Type = Structure.Size;
4165 Field.SizeOf = Structure.Size;
4168 if (!ParentStruct.IsUnion) {
4169 ParentStruct.NextOffset = StructureEnd;
4171 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4173 StructInfo.Structure = Structure;
4174 StructInfo.Initializers.emplace_back();
4175 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4176 for (
const auto &SubField : Structure.Fields) {
4177 FieldInitializers.push_back(SubField.Contents);
4186bool MasmParser::parseDirectiveOrg() {
4188 SMLoc OffsetLoc = Lexer.getLoc();
4189 if (checkForValidSection() || parseExpression(
Offset))
4192 return addErrorSuffix(
" in 'org' directive");
4194 if (StructInProgress.
empty()) {
4196 if (checkForValidSection())
4197 return addErrorSuffix(
" in 'org' directive");
4199 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4202 StructInfo &Structure = StructInProgress.
back();
4204 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4205 return Error(OffsetLoc,
4206 "expected absolute expression in 'org' directive");
4210 "expected non-negative value in struct's 'org' directive; was " +
4211 std::to_string(OffsetRes));
4212 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4215 Structure.Initializable =
false;
4221bool MasmParser::emitAlignTo(int64_t Alignment) {
4222 if (StructInProgress.
empty()) {
4224 if (checkForValidSection())
4229 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4231 getStreamer().emitCodeAlignment(
Align(Alignment),
4232 &getTargetParser().getSTI(),
4236 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4242 StructInfo &Structure = StructInProgress.
back();
4243 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4251bool MasmParser::parseDirectiveAlign() {
4252 SMLoc AlignmentLoc = getLexer().getLoc();
4258 "align directive with no operand is ignored") &&
4261 if (parseAbsoluteExpression(Alignment) || parseEOL())
4262 return addErrorSuffix(
" in align directive");
4265 bool ReturnVal =
false;
4272 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4273 std::to_string(Alignment));
4275 if (emitAlignTo(Alignment))
4276 ReturnVal |= addErrorSuffix(
" in align directive");
4283bool MasmParser::parseDirectiveEven() {
4284 if (parseEOL() || emitAlignTo(2))
4285 return addErrorSuffix(
" in even directive");
4296bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4300 return Error(Lexer.getLoc(),
4301 "Vararg parameter '" +
Parameters.back().Name +
4302 "' should be last in the list of parameters");
4306 return TokError(
"expected identifier in 'macro' directive");
4309 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4310 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4311 return TokError(
"macro '" + Name +
"' has multiple parameters"
4321 ParamLoc = Lexer.getLoc();
4322 if (parseMacroArgument(
nullptr,
Parameter.Value))
4328 QualLoc = Lexer.getLoc();
4329 if (parseIdentifier(Qualifier))
4330 return Error(QualLoc,
"missing parameter qualifier for "
4332 Parameter.Name +
"' in macro '" + Name +
4335 if (
Qualifier.equals_insensitive(
"req"))
4337 else if (
Qualifier.equals_insensitive(
"vararg"))
4340 return Error(QualLoc,
4341 Qualifier +
" is not a valid parameter qualifier for '" +
4342 Parameter.Name +
"' in macro '" + Name +
"'");
4355 std::vector<std::string>
Locals;
4357 getTok().getIdentifier().equals_insensitive(
"local")) {
4362 if (parseIdentifier(
ID))
4374 AsmToken EndToken, StartToken = getTok();
4375 unsigned MacroDepth = 0;
4376 bool IsMacroFunction =
false;
4386 return Error(NameLoc,
"no matching 'endm' in definition");
4391 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4392 if (MacroDepth == 0) {
4393 EndToken = getTok();
4396 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4403 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4405 IsMacroFunction =
true;
4407 }
else if (isMacroLikeDirective()) {
4415 eatToEndOfStatement();
4419 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4424 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4425 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4435bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4436 StringRef Directive,
4437 std::string &
Value) {
4438 SMLoc EndLoc = getTok().getLoc();
4440 return Error(EndLoc,
4441 "unable to parse text item in '" + Directive +
"' directive");
4442 eatToEndOfStatement();
4444 if (!isInsideMacroInstantiation())
4445 return TokError(
"unexpected '" + Directive +
"' in file, "
4446 "no current macro definition");
4449 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4450 TheCondState = TheCondStack.back();
4451 TheCondStack.pop_back();
4460bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4462 return TokError(
"unexpected token in '" + Directive +
"' directive");
4466 if (isInsideMacroInstantiation()) {
4473 return TokError(
"unexpected '" + Directive +
"' in file, "
4474 "no current macro definition");
4479bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4483 if (parseTokenLoc(NameLoc) ||
4484 check(parseIdentifier(Name), NameLoc,
4485 "expected identifier in 'purge' directive"))
4489 <<
"Un-defining macro: " << Name <<
"\n");
4491 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4502bool MasmParser::parseDirectiveExtern() {
4504 auto parseOp = [&]() ->
bool {
4506 SMLoc NameLoc = getTok().getLoc();
4508 return Error(NameLoc,
"expected name");
4513 SMLoc TypeLoc = getTok().getLoc();
4514 if (parseIdentifier(TypeName))
4515 return Error(TypeLoc,
"expected type");
4516 if (!
TypeName.equals_insensitive(
"proc")) {
4518 if (lookUpType(TypeName,
Type))
4519 return Error(TypeLoc,
"unrecognized type");
4523 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4524 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4529 if (parseMany(parseOp))
4530 return addErrorSuffix(
" in directive 'extern'");
4536bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4537 auto parseOp = [&]() ->
bool {
4538 SMLoc Loc = getTok().getLoc();
4541 return Error(Loc,
"expected identifier");
4545 return Error(Loc,
"non-local symbol required");
4547 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4548 return Error(Loc,
"unable to emit symbol attribute");
4552 if (parseMany(parseOp))
4553 return addErrorSuffix(
" in directive");
4559bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4560 if (checkForValidSection())
4563 SMLoc IDLoc = getLexer().getLoc();
4566 return TokError(
"expected identifier in directive");
4569 return TokError(
"unexpected token in directive");
4573 SMLoc SizeLoc = getLexer().getLoc();
4574 if (parseAbsoluteExpression(
Size))
4577 int64_t Pow2Alignment = 0;
4578 SMLoc Pow2AlignmentLoc;
4581 Pow2AlignmentLoc = getLexer().getLoc();
4582 if (parseAbsoluteExpression(Pow2Alignment))
4587 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4590 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4593 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4594 Pow2Alignment =
Log2_64(Pow2Alignment);
4604 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4605 "be less than zero");
4610 if (Pow2Alignment < 0)
4611 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4612 "alignment, can't be less than zero");
4616 return Error(IDLoc,
"invalid symbol redefinition");
4620 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4621 Align(1ULL << Pow2Alignment));
4625 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4633bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4635 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4636 assert(DelimiterEnd != std::string::npos);
4637 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4638 if (Delimiter.
empty())
4639 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4642 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4652bool MasmParser::parseDirectiveInclude() {
4655 SMLoc IncludeLoc = getTok().getLoc();
4657 if (parseAngleBracketString(Filename))
4659 if (check(
Filename.empty(),
"missing filename in 'include' directive") ||
4661 "unexpected token in 'include' directive") ||
4664 check(enterIncludeFile(Filename), IncludeLoc,
4665 "Could not find include file '" + Filename +
"'"))
4673bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4674 TheCondStack.push_back(TheCondState);
4676 if (TheCondState.
Ignore) {
4677 eatToEndOfStatement();
4680 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4689 ExprValue = ExprValue == 0;
4693 TheCondState.
CondMet = ExprValue;
4702bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4703 TheCondStack.push_back(TheCondState);
4706 if (TheCondState.
Ignore) {
4707 eatToEndOfStatement();
4710 if (parseTextItem(Str))
4711 return TokError(
"expected text item parameter for 'ifb' directive");
4716 TheCondState.
CondMet = ExpectBlank == Str.empty();
4725bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4726 bool CaseInsensitive) {
4727 std::string String1, String2;
4729 if (parseTextItem(String1)) {
4731 return TokError(
"expected text item parameter for 'ifidn' directive");
4732 return TokError(
"expected text item parameter for 'ifdif' directive");
4738 "expected comma after first string for 'ifidn' directive");
4739 return TokError(
"expected comma after first string for 'ifdif' directive");
4743 if (parseTextItem(String2)) {
4745 return TokError(
"expected text item parameter for 'ifidn' directive");
4746 return TokError(
"expected text item parameter for 'ifdif' directive");
4749 TheCondStack.push_back(TheCondState);
4751 if (CaseInsensitive)
4753 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4755 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4764bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4765 TheCondStack.push_back(TheCondState);
4768 if (TheCondState.
Ignore) {
4769 eatToEndOfStatement();
4771 bool is_defined =
false;
4773 SMLoc StartLoc, EndLoc;
4775 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4778 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4782 if (BuiltinSymbolMap.contains(
Name.lower())) {
4792 TheCondState.
CondMet = (is_defined == expect_defined);
4801bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4802 DirectiveKind DirKind) {
4805 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4806 " .if or an .elseif");
4809 bool LastIgnoreState =
false;
4810 if (!TheCondStack.empty())
4811 LastIgnoreState = TheCondStack.back().Ignore;
4812 if (LastIgnoreState || TheCondState.
CondMet) {
4813 TheCondState.
Ignore =
true;
4814 eatToEndOfStatement();
4817 if (parseAbsoluteExpression(ExprValue))
4829 ExprValue = ExprValue == 0;
4833 TheCondState.
CondMet = ExprValue;
4842bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4845 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4846 " if or an elseif");
4849 bool LastIgnoreState =
false;
4850 if (!TheCondStack.empty())
4851 LastIgnoreState = TheCondStack.back().Ignore;
4852 if (LastIgnoreState || TheCondState.
CondMet) {
4853 TheCondState.
Ignore =
true;
4854 eatToEndOfStatement();
4857 if (parseTextItem(Str)) {
4859 return TokError(
"expected text item parameter for 'elseifb' directive");
4860 return TokError(
"expected text item parameter for 'elseifnb' directive");
4866 TheCondState.
CondMet = ExpectBlank == Str.empty();
4876bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4877 bool expect_defined) {
4880 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4881 " if or an elseif");
4884 bool LastIgnoreState =
false;
4885 if (!TheCondStack.empty())
4886 LastIgnoreState = TheCondStack.back().Ignore;
4887 if (LastIgnoreState || TheCondState.
CondMet) {
4888 TheCondState.
Ignore =
true;
4889 eatToEndOfStatement();
4891 bool is_defined =
false;
4893 SMLoc StartLoc, EndLoc;
4895 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4898 if (check(parseIdentifier(Name),
4899 "expected identifier after 'elseifdef'") ||
4903 if (BuiltinSymbolMap.contains(
Name.lower())) {
4913 TheCondState.
CondMet = (is_defined == expect_defined);
4922bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4923 bool CaseInsensitive) {
4926 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4927 " if or an elseif");
4930 bool LastIgnoreState =
false;
4931 if (!TheCondStack.empty())
4932 LastIgnoreState = TheCondStack.back().Ignore;
4933 if (LastIgnoreState || TheCondState.
CondMet) {
4934 TheCondState.
Ignore =
true;
4935 eatToEndOfStatement();
4937 std::string String1, String2;
4939 if (parseTextItem(String1)) {
4942 "expected text item parameter for 'elseifidn' directive");
4943 return TokError(
"expected text item parameter for 'elseifdif' directive");
4949 "expected comma after first string for 'elseifidn' directive");
4951 "expected comma after first string for 'elseifdif' directive");
4955 if (parseTextItem(String2)) {
4958 "expected text item parameter for 'elseifidn' directive");
4959 return TokError(
"expected text item parameter for 'elseifdif' directive");
4962 if (CaseInsensitive)
4964 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4966 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4975bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4981 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4984 bool LastIgnoreState =
false;
4985 if (!TheCondStack.empty())
4986 LastIgnoreState = TheCondStack.back().Ignore;
4987 if (LastIgnoreState || TheCondState.
CondMet)
4988 TheCondState.
Ignore =
true;
4990 TheCondState.
Ignore =
false;
4997bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5009bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5010 if (!TheCondStack.empty()) {
5011 if (TheCondStack.back().Ignore) {
5012 eatToEndOfStatement();
5017 std::string Message =
".err directive invoked in source file";
5022 return Error(DirectiveLoc, Message);
5027bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5028 if (!TheCondStack.empty()) {
5029 if (TheCondStack.back().Ignore) {
5030 eatToEndOfStatement();
5036 if (parseTextItem(Text))
5037 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5039 std::string Message =
".errb directive invoked in source file";
5042 return addErrorSuffix(
" in '.errb' directive");
5047 if (
Text.empty() == ExpectBlank)
5048 return Error(DirectiveLoc, Message);
5054bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5055 bool ExpectDefined) {
5056 if (!TheCondStack.empty()) {
5057 if (TheCondStack.back().Ignore) {
5058 eatToEndOfStatement();
5063 bool IsDefined =
false;
5065 SMLoc StartLoc, EndLoc;
5067 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5070 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5073 if (BuiltinSymbolMap.contains(
Name.lower())) {
5083 std::string Message =
".errdef directive invoked in source file";
5086 return addErrorSuffix(
" in '.errdef' directive");
5091 if (IsDefined == ExpectDefined)
5092 return Error(DirectiveLoc, Message);
5098bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5099 bool CaseInsensitive) {
5100 if (!TheCondStack.empty()) {
5101 if (TheCondStack.back().Ignore) {
5102 eatToEndOfStatement();
5107 std::string String1, String2;
5109 if (parseTextItem(String1)) {
5111 return TokError(
"expected string parameter for '.erridn' directive");
5112 return TokError(
"expected string parameter for '.errdif' directive");
5118 "expected comma after first string for '.erridn' directive");
5120 "expected comma after first string for '.errdif' directive");
5124 if (parseTextItem(String2)) {
5126 return TokError(
"expected string parameter for '.erridn' directive");
5127 return TokError(
"expected string parameter for '.errdif' directive");
5130 std::string Message;
5132 Message =
".erridn directive invoked in source file";
5134 Message =
".errdif directive invoked in source file";
5137 return addErrorSuffix(
" in '.erridn' directive");
5142 if (CaseInsensitive)
5144 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5146 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5149 if ((CaseInsensitive &&
5150 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5151 (ExpectEqual == (String1 == String2)))
5152 return Error(DirectiveLoc, Message);
5158bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5159 if (!TheCondStack.empty()) {
5160 if (TheCondStack.back().Ignore) {
5161 eatToEndOfStatement();
5167 if (parseAbsoluteExpression(ExprValue))
5168 return addErrorSuffix(
" in '.erre' directive");
5170 std::string Message =
".erre directive invoked in source file";
5173 return addErrorSuffix(
" in '.erre' directive");
5178 if ((ExprValue == 0) == ExpectZero)
5179 return Error(DirectiveLoc, Message);
5185bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5190 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5192 if (!TheCondStack.empty()) {
5193 TheCondState = TheCondStack.back();
5194 TheCondStack.pop_back();
5200void MasmParser::initializeDirectiveKindMap() {
5201 DirectiveKindMap[
"="] = DK_ASSIGN;
5202 DirectiveKindMap[
"equ"] = DK_EQU;
5203 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5207 DirectiveKindMap[
"byte"] = DK_BYTE;
5208 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5209 DirectiveKindMap[
"word"] = DK_WORD;
5210 DirectiveKindMap[
"sword"] = DK_SWORD;
5211 DirectiveKindMap[
"dword"] = DK_DWORD;
5212 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5213 DirectiveKindMap[
"fword"] = DK_FWORD;
5214 DirectiveKindMap[
"qword"] = DK_QWORD;
5215 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5216 DirectiveKindMap[
"real4"] = DK_REAL4;
5217 DirectiveKindMap[
"real8"] = DK_REAL8;
5218 DirectiveKindMap[
"real10"] = DK_REAL10;
5219 DirectiveKindMap[
"align"] = DK_ALIGN;
5220 DirectiveKindMap[
"even"] = DK_EVEN;
5221 DirectiveKindMap[
"org"] = DK_ORG;
5222 DirectiveKindMap[
"extern"] = DK_EXTERN;
5223 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5224 DirectiveKindMap[
"public"] = DK_PUBLIC;
5226 DirectiveKindMap[
"comment"] = DK_COMMENT;
5227 DirectiveKindMap[
"include"] = DK_INCLUDE;
5228 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5229 DirectiveKindMap[
"rept"] = DK_REPEAT;
5230 DirectiveKindMap[
"while"] = DK_WHILE;
5231 DirectiveKindMap[
"for"] = DK_FOR;
5232 DirectiveKindMap[
"irp"] = DK_FOR;
5233 DirectiveKindMap[
"forc"] = DK_FORC;
5234 DirectiveKindMap[
"irpc"] = DK_FORC;
5235 DirectiveKindMap[
"if"] = DK_IF;
5236 DirectiveKindMap[
"ife"] = DK_IFE;
5237 DirectiveKindMap[
"ifb"] = DK_IFB;
5238 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5239 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5240 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5241 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5242 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5243 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5244 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5245 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5246 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5247 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5248 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5249 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5250 DirectiveKindMap[
"else"] = DK_ELSE;
5251 DirectiveKindMap[
"end"] = DK_END;
5252 DirectiveKindMap[
"endif"] = DK_ENDIF;
5292 DirectiveKindMap[
"macro"] = DK_MACRO;
5293 DirectiveKindMap[
"exitm"] = DK_EXITM;
5294 DirectiveKindMap[
"endm"] = DK_ENDM;
5295 DirectiveKindMap[
"purge"] = DK_PURGE;
5296 DirectiveKindMap[
".err"] = DK_ERR;
5297 DirectiveKindMap[
".errb"] = DK_ERRB;
5298 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5299 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5300 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5301 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5302 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5303 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5304 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5305 DirectiveKindMap[
".erre"] = DK_ERRE;
5306 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5307 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5308 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5309 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5310 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5311 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5312 DirectiveKindMap[
".radix"] = DK_RADIX;
5313 DirectiveKindMap[
"db"] = DK_DB;
5314 DirectiveKindMap[
"dd"] = DK_DD;
5315 DirectiveKindMap[
"df"] = DK_DF;
5316 DirectiveKindMap[
"dq"] = DK_DQ;
5317 DirectiveKindMap[
"dw"] = DK_DW;
5318 DirectiveKindMap[
"echo"] = DK_ECHO;
5319 DirectiveKindMap[
"struc"] = DK_STRUCT;
5320 DirectiveKindMap[
"struct"] = DK_STRUCT;
5321 DirectiveKindMap[
"union"] = DK_UNION;
5322 DirectiveKindMap[
"ends"] = DK_ENDS;
5325bool MasmParser::isMacroLikeDirective() {
5327 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5328 .CasesLower(
"repeat",
"rept",
true)
5329 .CaseLower(
"while",
true)
5330 .CasesLower(
"for",
"irp",
true)
5331 .CasesLower(
"forc",
"irpc",
true)
5337 peekTok().getIdentifier().equals_insensitive(
"macro"))
5343MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5344 AsmToken EndToken, StartToken = getTok();
5346 unsigned NestLevel = 0;
5350 printError(DirectiveLoc,
"no matching 'endm' in definition");
5354 if (isMacroLikeDirective())
5359 getTok().getIdentifier().equals_insensitive(
"endm")) {
5360 if (NestLevel == 0) {
5361 EndToken = getTok();
5364 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5373 eatToEndOfStatement();
5378 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5382 return &MacroLikeBodies.back();
5385bool MasmParser::expandStatement(SMLoc Loc) {
5387 SMLoc EndLoc = getTok().getLoc();
5392 StringMap<std::string> BuiltinValues;
5393 for (
const auto &S : BuiltinSymbolMap) {
5394 const BuiltinSymbol &Sym = S.getValue();
5395 if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5396 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5399 for (
const auto &
B : BuiltinValues) {
5400 MCAsmMacroParameter
P;
5401 MCAsmMacroArgument
A;
5402 P.Name =
B.getKey();
5410 for (
const auto &V : Variables) {
5413 MCAsmMacroParameter
P;
5414 MCAsmMacroArgument
A;
5423 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5424 MCAsmMacro
M = MacroLikeBodies.back();
5427 SmallString<80> Buf;
5428 raw_svector_ostream OS(Buf);
5429 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5431 std::unique_ptr<MemoryBuffer>
Expansion =
5437 EndStatementAtEOFStack.push_back(
false);
5442void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5443 raw_svector_ostream &OS) {
5444 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5446void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5448 raw_svector_ostream &OS) {
5451 std::unique_ptr<MemoryBuffer> Instantiation =
5456 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5457 ExitLoc, TheCondStack.size()};
5458 ActiveMacros.push_back(
MI);
5463 EndStatementAtEOFStack.push_back(
true);
5471bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5472 const MCExpr *CountExpr;
5473 SMLoc CountLoc = getTok().getLoc();
5474 if (parseExpression(CountExpr))
5478 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5479 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5482 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5486 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5492 SmallString<256> Buf;
5493 raw_svector_ostream OS(Buf);
5495 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5498 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5507bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5508 const MCExpr *CondExpr;
5509 SMLoc CondLoc = getTok().getLoc();
5510 if (parseExpression(CondExpr))
5514 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5520 SmallString<256> Buf;
5521 raw_svector_ostream OS(Buf);
5523 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5524 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5528 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5530 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5540bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5542 MCAsmMacroArguments
A;
5543 if (check(parseIdentifier(
Parameter.Name),
5544 "expected identifier in '" + Dir +
"' directive"))
5553 ParamLoc = Lexer.getLoc();
5554 if (parseMacroArgument(
nullptr,
Parameter.Value))
5560 QualLoc = Lexer.getLoc();
5561 if (parseIdentifier(Qualifier))
5562 return Error(QualLoc,
"missing parameter qualifier for "
5567 if (
Qualifier.equals_insensitive(
"req"))
5570 return Error(QualLoc,
5571 Qualifier +
" is not a valid parameter qualifier for '" +
5572 Parameter.Name +
"' in '" + Dir +
"' directive");
5577 "expected comma in '" + Dir +
"' directive") ||
5579 "values in '" + Dir +
5580 "' directive must be enclosed in angle brackets"))
5586 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5595 "values in '" + Dir +
5596 "' directive must be enclosed in angle brackets") ||
5601 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5607 SmallString<256> Buf;
5608 raw_svector_ostream OS(Buf);
5610 for (
const MCAsmMacroArgument &Arg :
A) {
5611 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5615 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5624bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5628 if (check(parseIdentifier(
Parameter.Name),
5629 "expected identifier in '" + Directive +
"' directive") ||
5631 "expected comma in '" + Directive +
"' directive"))
5633 if (parseAngleBracketString(Argument)) {
5641 for (; End <
Argument.size(); ++End) {
5651 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5657 SmallString<256> Buf;
5658 raw_svector_ostream OS(Buf);
5660 StringRef Values(Argument);
5661 for (std::size_t
I = 0, End = Values.
size();
I != End; ++
I) {
5662 MCAsmMacroArgument Arg;
5665 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5669 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5674bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &
Info,
5676 const MCExpr *
Value;
5677 SMLoc ExprLoc = getLexer().getLoc();
5678 if (parseExpression(
Value))
5682 return Error(ExprLoc,
"unexpected expression in _emit");
5683 uint64_t IntValue = MCE->
getValue();
5685 return Error(ExprLoc,
"literal value out of range for directive");
5691bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &
Info) {
5692 const MCExpr *
Value;
5693 SMLoc ExprLoc = getLexer().getLoc();
5694 if (parseExpression(
Value))
5698 return Error(ExprLoc,
"unexpected expression in align");
5699 uint64_t IntValue = MCE->
getValue();
5701 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5707bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5708 const SMLoc Loc = getLexer().getLoc();
5710 StringRef RadixString = StringRef(RadixStringRaw).trim();
5714 "radix must be a decimal number in the range 2 to 16; was " +
5717 if (Radix < 2 || Radix > 16)
5718 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5719 std::to_string(Radix));
5720 getLexer().setMasmDefaultRadix(Radix);
5726bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5729 if (!StringRef(Message).ends_with(
"\n"))
5757bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5759 if (Var.Name.empty()) {
5761 }
else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5762 return Error(SMLoc(),
"invalid variable redefinition");
5763 }
else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5764 Warning(SMLoc(),
"redefining '" + Name +
5765 "', already defined on the command line")) {
5768 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5770 Var.TextValue =
Value.str();
5774bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &
Info)
const {
5775 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5776 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5777 return lookUpField(
Base, Member,
Info);
5780bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5781 AsmFieldInfo &
Info)
const {
5785 AsmFieldInfo BaseInfo;
5786 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5789 auto StructIt = Structs.
find(
Base.lower());
5790 auto TypeIt = KnownType.
find(
Base.lower());
5791 if (TypeIt != KnownType.
end()) {
5792 StructIt = Structs.
find(TypeIt->second.Name.lower());
5794 if (StructIt != Structs.
end())
5795 return lookUpField(StructIt->second, Member,
Info);
5800bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5801 AsmFieldInfo &
Info)
const {
5803 Info.Type.Name = Structure.Name;
5804 Info.Type.Size = Structure.Size;
5805 Info.Type.ElementSize = Structure.Size;
5806 Info.Type.Length = 1;
5810 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5811 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5813 auto StructIt = Structs.
find(FieldName.
lower());
5814 if (StructIt != Structs.
end())
5815 return lookUpField(StructIt->second, FieldMember,
Info);
5817 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5818 if (FieldIt == Structure.FieldsByName.
end())
5821 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5822 if (FieldMember.empty()) {
5827 if (
Field.Contents.FT == FT_STRUCT)
5828 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5830 Info.Type.Name =
"";
5834 if (
Field.Contents.FT != FT_STRUCT)
5836 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5838 if (lookUpField(StructInfo.Structure, FieldMember,
Info))
5845bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &
Info)
const {
5846 unsigned Size = StringSwitch<unsigned>(Name)
5847 .CasesLower(
"byte",
"db",
"sbyte", 1)
5848 .CasesLower(
"word",
"dw",
"sword", 2)
5849 .CasesLower(
"dword",
"dd",
"sdword", 4)
5850 .CasesLower(
"fword",
"df", 6)
5851 .CasesLower(
"qword",
"dq",
"sqword", 8)
5852 .CaseLower(
"real4", 4)
5853 .CaseLower(
"real8", 8)
5854 .CaseLower(
"real10", 10)
5864 auto StructIt = Structs.
find(
Name.lower());
5865 if (StructIt != Structs.
end()) {
5866 const StructInfo &Structure = StructIt->second;
5868 Info.ElementSize = Structure.Size;
5870 Info.Size = Structure.Size;
5877bool MasmParser::parseMSInlineAsm(
5878 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5879 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5880 SmallVectorImpl<std::string> &Constraints,
5881 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5882 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5883 SmallVector<void *, 4> InputDecls;
5884 SmallVector<void *, 4> OutputDecls;
5887 SmallVector<std::string, 4> InputConstraints;
5888 SmallVector<std::string, 4> OutputConstraints;
5897 unsigned InputIdx = 0;
5898 unsigned OutputIdx = 0;
5901 if (parseCurlyBlockScope(AsmStrRewrites))
5904 ParseStatementInfo
Info(&AsmStrRewrites);
5905 bool StatementErr = parseStatement(
Info, &SI);
5907 if (StatementErr ||
Info.ParseError) {
5909 printPendingErrors();
5914 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5916 if (
Info.Opcode == ~0U)
5922 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5923 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5927 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5928 unsigned NumDefs =
Desc.getNumDefs();
5937 if (SymName.
empty())
5945 if (Operand.
isImm()) {
5953 bool isOutput = (i == 1) &&
Desc.mayStore();
5959 OutputConstraints.
push_back((
"=" + Constraint).str());
5965 if (
Desc.operands()[i - 1].isBranchTarget())
5977 NumOutputs = OutputDecls.
size();
5978 NumInputs = InputDecls.
size();
5983 Clobbers.
assign(ClobberRegs.
size(), std::string());
5984 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5985 raw_string_ostream OS(Clobbers[
I]);
5990 if (NumOutputs || NumInputs) {
5991 unsigned NumExprs = NumOutputs + NumInputs;
5992 OpDecls.resize(NumExprs);
5993 Constraints.
resize(NumExprs);
5994 for (
unsigned i = 0; i < NumOutputs; ++i) {
5995 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5996 Constraints[i] = OutputConstraints[i];
5998 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
5999 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6000 Constraints[
j] = InputConstraints[i];
6005 std::string AsmStringIR;
6006 raw_string_ostream OS(AsmStringIR);
6007 StringRef ASMString =
6009 const char *AsmStart = ASMString.
begin();
6010 const char *AsmEnd = ASMString.
end();
6012 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6013 const AsmRewrite &AR = *
I;
6020 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6023 if (
unsigned Len = Loc - AsmStart)
6024 OS << StringRef(AsmStart, Len);
6028 AsmStart = Loc + AR.
Len;
6032 unsigned AdditionalSkip = 0;
6054 size_t OffsetLen = OffsetName.
size();
6055 auto rewrite_it = std::find_if(
6056 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6057 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6058 (FusingAR.Kind == AOK_Input ||
6059 FusingAR.Kind == AOK_CallInput);
6061 if (rewrite_it == AsmStrRewrites.
end()) {
6062 OS <<
"offset " << OffsetName;
6064 OS <<
"${" << InputIdx++ <<
":P}";
6065 rewrite_it->Done =
true;
6067 OS <<
'$' << InputIdx++;
6068 rewrite_it->Done =
true;
6080 OS <<
'$' << InputIdx++;
6083 OS <<
"${" << InputIdx++ <<
":P}";
6086 OS <<
'$' << OutputIdx++;
6091 case 8: OS <<
"byte ptr ";
break;
6092 case 16: OS <<
"word ptr ";
break;
6093 case 32: OS <<
"dword ptr ";
break;
6094 case 64: OS <<
"qword ptr ";
break;
6095 case 80: OS <<
"xword ptr ";
break;
6096 case 128: OS <<
"xmmword ptr ";
break;
6097 case 256: OS <<
"ymmword ptr ";
break;
6107 if (
getContext().getAsmInfo()->getAlignmentIsInBytes())
6112 unsigned Val = AR.
Val;
6114 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6115 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6127 AsmStart = Loc + AR.
Len + AdditionalSkip;
6131 if (AsmStart != AsmEnd)
6132 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6134 AsmString = OS.
str();
6138void MasmParser::initializeBuiltinSymbolMaps() {
6140 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6141 BuiltinSymbolMap[
"@line"] = BI_LINE;
6144 BuiltinSymbolMap[
"@date"] = BI_DATE;
6145 BuiltinSymbolMap[
"@time"] = BI_TIME;
6146 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6147 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6148 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6151 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6154 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6172const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6182 if (ActiveMacros.empty())
6186 ActiveMacros.front()->ExitBuffer);
6193std::optional<std::string>
6194MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6200 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6201 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6202 return std::string(TmpBuffer, Len);
6206 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6207 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6208 return std::string(TmpBuffer, Len);
6213 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6221 return getStreamer().getCurrentSectionOnly()->getName().str();
6226bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6230 "' requires arguments in parentheses")) {
6241 MCAsmMacro
M(Name,
"",
P, {},
true);
6243 MCAsmMacroArguments
A;
6252 for (
const MCAsmMacroArgument &Arg :
A) {
6253 for (
const AsmToken &Tok : Arg) {
6271 struct tm TM,
unsigned CB) {
6272 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")
Analysis containing CSE Info
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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.
StringRef getPrivateLabelPrefix() const
bool shouldUseLogicalShr() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
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 initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
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.
StringRef - 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
str - 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
empty - 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
size - Get the string size.
constexpr const char * data() const
data - 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.
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
MCAsmParserExtension * createCOFFMasmParser()
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
uint64_t Size
The required size of this field in bytes.