73typedef std::vector<AsmToken> MCAsmMacroArgument;
74typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
77struct MacroInstantiation {
79 SMLoc InstantiationLoc;
88 size_t CondStackDepth;
91struct ParseStatementInfo {
96 unsigned Opcode = ~0
U;
99 bool ParseError =
false;
102 std::optional<std::string> ExitValue;
104 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
106 ParseStatementInfo() =
delete;
107 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
108 : AsmRewrites(rewrites) {}
120 bool IsUnion =
false;
121 bool Initializable =
true;
122 unsigned Alignment = 0;
123 unsigned AlignmentSize = 0;
124 unsigned NextOffset = 0;
126 std::vector<FieldInfo> Fields;
127 StringMap<size_t> FieldsByName;
129 FieldInfo &addField(StringRef FieldName, FieldType FT,
130 unsigned FieldAlignmentSize);
132 StructInfo() =
default;
133 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
141struct StructInitializer;
145 IntFieldInfo() =
default;
149struct RealFieldInfo {
152 RealFieldInfo() =
default;
156struct StructFieldInfo {
157 std::vector<StructInitializer> Initializers;
158 StructInfo Structure;
160 StructFieldInfo() =
default;
161 StructFieldInfo(std::vector<StructInitializer>
V, StructInfo S);
164class FieldInitializer {
168 IntFieldInfo IntInfo;
169 RealFieldInfo RealInfo;
170 StructFieldInfo StructInfo;
174 FieldInitializer(FieldType FT);
178 FieldInitializer(std::vector<StructInitializer> &&Initializers,
179 struct StructInfo Structure);
181 FieldInitializer(
const FieldInitializer &Initializer);
182 FieldInitializer(FieldInitializer &&Initializer);
184 FieldInitializer &operator=(
const FieldInitializer &Initializer);
185 FieldInitializer &operator=(FieldInitializer &&Initializer);
188struct StructInitializer {
189 std::vector<FieldInitializer> FieldInitializers;
200 unsigned LengthOf = 0;
205 FieldInitializer Contents;
207 FieldInfo(FieldType FT) : Contents(FT) {}
210StructFieldInfo::StructFieldInfo(std::vector<StructInitializer>
V,
212 Initializers = std::move(
V);
213 Structure = std::move(S);
216StructInfo::StructInfo(StringRef
StructName,
bool Union,
217 unsigned AlignmentValue)
220FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
221 unsigned FieldAlignmentSize) {
222 if (!FieldName.
empty())
223 FieldsByName[FieldName.
lower()] = Fields.size();
224 Fields.emplace_back(FT);
225 FieldInfo &
Field = Fields.back();
227 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
231 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
235FieldInitializer::~FieldInitializer() {
238 IntInfo.~IntFieldInfo();
241 RealInfo.~RealFieldInfo();
244 StructInfo.~StructFieldInfo();
249FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
252 new (&IntInfo) IntFieldInfo();
255 new (&RealInfo) RealFieldInfo();
258 new (&StructInfo) StructFieldInfo();
265 new (&IntInfo) IntFieldInfo(std::move(
Values));
270 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
273FieldInitializer::FieldInitializer(
274 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
276 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
279FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
280 : FT(Initializer.FT) {
283 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
286 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
289 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
294FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
295 : FT(Initializer.FT) {
298 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
301 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
304 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
310FieldInitializer::operator=(
const FieldInitializer &Initializer) {
311 if (FT != Initializer.FT) {
314 IntInfo.~IntFieldInfo();
317 RealInfo.~RealFieldInfo();
320 StructInfo.~StructFieldInfo();
327 IntInfo = Initializer.IntInfo;
330 RealInfo = Initializer.RealInfo;
333 StructInfo = Initializer.StructInfo;
339FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
340 if (FT != Initializer.FT) {
343 IntInfo.~IntFieldInfo();
346 RealInfo.~RealFieldInfo();
349 StructInfo.~StructFieldInfo();
356 IntInfo = Initializer.IntInfo;
359 RealInfo = Initializer.RealInfo;
362 StructInfo = Initializer.StructInfo;
371class MasmParser :
public MCAsmParser {
374 void *SavedDiagContext;
375 std::unique_ptr<MCAsmParserExtension> PlatformParser;
384 BitVector EndStatementAtEOFStack;
386 AsmCond TheCondState;
387 std::vector<AsmCond> TheCondStack;
392 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
396 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
399 RedefinableKind Redefinable = REDEFINABLE;
401 std::string TextValue;
403 StringMap<Variable> Variables;
409 StringMap<StructInfo> Structs;
412 StringMap<AsmTypeInfo> KnownType;
415 std::vector<MacroInstantiation*> ActiveMacros;
418 std::deque<MCAsmMacro> MacroLikeBodies;
421 unsigned NumOfMacroInstantiations;
424 struct CppHashInfoTy {
429 CppHashInfoTy() : LineNumber(0), Buf(0) {}
431 CppHashInfoTy CppHashInfo;
434 StringRef FirstCppHashFilename;
441 unsigned AssemblerDialect = 1U;
444 bool ParsingMSInlineAsm =
false;
447 unsigned AngleBracketDepth = 0
U;
450 uint16_t LocalCounter = 0;
453 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
454 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
455 MasmParser(
const MasmParser &) =
delete;
456 MasmParser &operator=(
const MasmParser &) =
delete;
457 ~MasmParser()
override;
459 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
461 void addDirectiveHandler(StringRef Directive,
462 ExtensionDirectiveHandler Handler)
override {
463 ExtensionDirectiveMap[Directive] = std::move(Handler);
464 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
467 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
468 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
474 unsigned getAssemblerDialect()
override {
475 if (AssemblerDialect == ~0U)
476 return MAI.getAssemblerDialect();
478 return AssemblerDialect;
480 void setAssemblerDialect(
unsigned i)
override {
481 AssemblerDialect = i;
484 void Note(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
486 bool printError(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
488 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
489 const AsmToken &Lex(ExpandKind ExpandNextToken);
490 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
492 void setParsingMSInlineAsm(
bool V)
override {
493 ParsingMSInlineAsm =
V;
496 Lexer.setLexMasmIntegers(
V);
498 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
500 bool isParsingMasm()
const override {
return true; }
502 bool defineMacro(StringRef Name, StringRef
Value)
override;
504 bool lookUpField(StringRef Name, AsmFieldInfo &Info)
const override;
505 bool lookUpField(StringRef
Base, StringRef Member,
506 AsmFieldInfo &Info)
const override;
508 bool lookUpType(StringRef Name, AsmTypeInfo &Info)
const override;
510 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
512 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
513 SmallVectorImpl<std::string> &Constraints,
514 SmallVectorImpl<std::string> &Clobbers,
515 const MCInstrInfo *MII, MCInstPrinter *IP,
516 MCAsmParserSemaCallback &SI)
override;
518 bool parseExpression(
const MCExpr *&Res);
519 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
520 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
521 AsmTypeInfo *TypeInfo)
override;
522 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
523 bool parseAbsoluteExpression(int64_t &Res)
override;
527 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
531 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
532 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
533 bool parseIdentifier(StringRef &Res)
override {
534 return parseIdentifier(Res, StandardPosition);
536 void eatToEndOfStatement()
override;
538 bool checkForValidSection()
override;
544 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
546 bool parseStatement(ParseStatementInfo &Info,
547 MCAsmParserSemaCallback *SI);
548 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
549 bool parseCppHashLineFilenameComment(SMLoc L);
551 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
554 const std::vector<std::string> &Locals, SMLoc L);
557 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
563 bool handleMacroEntry(
564 const MCAsmMacro *M, SMLoc NameLoc,
571 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
574 void handleMacroExit();
578 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
583 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
586 void printMacroInstantiations();
588 bool expandStatement(SMLoc Loc);
591 SMRange
Range = {})
const {
597 bool lookUpField(
const StructInfo &Structure, StringRef Member,
598 AsmFieldInfo &Info)
const;
601 bool enterIncludeFile(
const std::string &
Filename);
609 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
610 bool EndStatementAtEOF =
true);
622 StringRef parseStringToEndOfStatement()
override;
624 bool parseTextItem(std::string &
Data);
625 bool parseTextList(std::string &Result, StringRef IDVal);
626 bool setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
627 SMLoc NameLoc, Variable::RedefinableKind Redefinable);
632 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
633 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
634 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
639 DK_HANDLER_DIRECTIVE,
730 StringMap<DirectiveKind> DirectiveKindMap;
732 bool isMacroLikeDirective();
759 StringMap<BuiltinSymbol> BuiltinSymbolMap;
761 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
763 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
767 enum BuiltinFunction {
774 StringMap<BuiltinFunction> BuiltinFunctionMap;
776 bool evaluateBuiltinMacroFunction(BuiltinFunction
Function, StringRef Name,
780 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
783 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
784 bool parseScalarInitializer(
unsigned Size,
785 SmallVectorImpl<const MCExpr *> &
Values,
786 unsigned StringPadLength = 0);
787 bool parseScalarInstList(
788 unsigned Size, SmallVectorImpl<const MCExpr *> &
Values,
790 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
791 bool addIntegralField(StringRef Name,
unsigned Size);
792 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
793 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
794 StringRef Name, SMLoc NameLoc);
797 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
798 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
799 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
801 bool parseRealInstList(
802 const fltSemantics &Semantics, SmallVectorImpl<APInt> &
Values,
804 bool parseDirectiveNamedRealValue(StringRef TypeName,
805 const fltSemantics &Semantics,
806 unsigned Size, StringRef Name,
809 bool parseOptionalAngleBracketOpen();
810 bool parseAngleBracketClose(
const Twine &
Msg =
"expected '>'");
812 bool parseFieldInitializer(
const FieldInfo &
Field,
813 FieldInitializer &Initializer);
814 bool parseFieldInitializer(
const FieldInfo &
Field,
815 const IntFieldInfo &Contents,
816 FieldInitializer &Initializer);
817 bool parseFieldInitializer(
const FieldInfo &
Field,
818 const RealFieldInfo &Contents,
819 FieldInitializer &Initializer);
820 bool parseFieldInitializer(
const FieldInfo &
Field,
821 const StructFieldInfo &Contents,
822 FieldInitializer &Initializer);
824 bool parseStructInitializer(
const StructInfo &Structure,
825 StructInitializer &Initializer);
826 bool parseStructInstList(
827 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
830 bool emitFieldValue(
const FieldInfo &
Field);
831 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
832 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
833 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
835 bool emitFieldInitializer(
const FieldInfo &
Field,
836 const FieldInitializer &Initializer);
837 bool emitFieldInitializer(
const FieldInfo &
Field,
838 const IntFieldInfo &Contents,
839 const IntFieldInfo &Initializer);
840 bool emitFieldInitializer(
const FieldInfo &
Field,
841 const RealFieldInfo &Contents,
842 const RealFieldInfo &Initializer);
843 bool emitFieldInitializer(
const FieldInfo &
Field,
844 const StructFieldInfo &Contents,
845 const StructFieldInfo &Initializer);
847 bool emitStructInitializer(
const StructInfo &Structure,
848 const StructInitializer &Initializer);
851 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
852 bool addStructField(StringRef Name,
const StructInfo &Structure);
853 bool parseDirectiveStructValue(
const StructInfo &Structure,
854 StringRef Directive, SMLoc DirLoc);
855 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
856 StringRef Directive, SMLoc DirLoc,
860 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
861 DirectiveKind DirKind, SMLoc NameLoc);
863 bool parseDirectiveOrg();
865 bool emitAlignTo(int64_t Alignment);
866 bool parseDirectiveAlign();
867 bool parseDirectiveEven();
870 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
871 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
873 bool parseDirectiveEndMacro(StringRef Directive);
874 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
876 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
877 StringRef Name, SMLoc NameLoc);
878 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
879 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
880 bool parseDirectiveNestedEnds();
882 bool parseDirectiveExtern();
888 bool parseDirectiveComm(
bool IsLocal);
890 bool parseDirectiveComment(SMLoc DirectiveLoc);
892 bool parseDirectiveInclude();
895 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
897 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
900 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
901 bool CaseInsensitive);
903 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
905 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
907 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
909 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
912 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
913 bool CaseInsensitive);
914 bool parseDirectiveElse(SMLoc DirectiveLoc);
915 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
916 bool parseEscapedString(std::string &
Data)
override;
917 bool parseAngleBracketString(std::string &
Data)
override;
920 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
921 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
922 raw_svector_ostream &OS);
923 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
924 SMLoc ExitLoc, raw_svector_ostream &OS);
925 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
926 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
928 bool parseDirectiveWhile(SMLoc DirectiveLoc);
931 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
935 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
938 bool parseDirectiveEnd(SMLoc DirectiveLoc);
941 bool parseDirectiveError(SMLoc DirectiveLoc);
943 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
945 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
948 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
949 bool CaseInsensitive);
951 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
954 bool parseDirectiveRadix(SMLoc DirectiveLoc);
957 bool parseDirectiveEcho(SMLoc DirectiveLoc);
959 void initializeDirectiveKindMap();
960 void initializeBuiltinSymbolMaps();
967MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
968 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
969 : MCAsmParser(Ctx,
Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
973 SavedDiagHandler =
SrcMgr.getDiagHandler();
974 SavedDiagContext =
SrcMgr.getDiagContext();
977 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
978 EndStatementAtEOFStack.push_back(
true);
981 switch (Ctx.getObjectFileType()) {
982 case MCContext::IsCOFF:
983 PlatformParser.reset(createCOFFMasmParser());
986 report_fatal_error(
"llvm-ml currently supports only COFF output.");
990 initializeDirectiveKindMap();
991 PlatformParser->Initialize(*
this);
992 initializeBuiltinSymbolMaps();
994 NumOfMacroInstantiations = 0;
997MasmParser::~MasmParser() {
998 assert((HadError || ActiveMacros.empty()) &&
999 "Unexpected active macro instantiation!");
1006void MasmParser::printMacroInstantiations() {
1008 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1009 it = ActiveMacros.rbegin(),
1010 ie = ActiveMacros.rend();
1013 "while in macro instantiation");
1016void MasmParser::Note(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1017 printPendingErrors();
1019 printMacroInstantiations();
1022bool MasmParser::Warning(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1028 printMacroInstantiations();
1032bool MasmParser::printError(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1035 printMacroInstantiations();
1039bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1040 std::string IncludedFile;
1048 EndStatementAtEOFStack.push_back(
true);
1052void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1053 bool EndStatementAtEOF) {
1059bool MasmParser::expandMacros() {
1060 const AsmToken &Tok = getTok();
1063 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1066 const SMLoc MacroLoc = Tok.
getLoc();
1069 if (handleMacroInvocation(M, MacroLoc)) {
1076 std::optional<std::string> ExpandedValue;
1078 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1079 BuiltinIt != BuiltinSymbolMap.end()) {
1081 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1082 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1083 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1085 if (parseIdentifier(Name)) {
1089 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1092 ExpandedValue = Res;
1093 }
else if (
auto VarIt = Variables.
find(IDLower);
1094 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1095 ExpandedValue = VarIt->getValue().TextValue;
1100 std::unique_ptr<MemoryBuffer> Instantiation =
1108 EndStatementAtEOFStack.push_back(
false);
1113const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1115 Error(Lexer.getErrLoc(), Lexer.getErr());
1116 bool StartOfStatement =
false;
1121 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1123 Out.addExplicitComment(Twine(getTok().getString()));
1124 StartOfStatement =
true;
1127 const AsmToken *tok = &Lexer.Lex();
1130 if (StartOfStatement) {
1133 size_t ReadCount = Lexer.peekTokens(Buf);
1165 if (ParentIncludeLoc != SMLoc()) {
1166 EndStatementAtEOFStack.pop_back();
1167 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1170 EndStatementAtEOFStack.pop_back();
1171 assert(EndStatementAtEOFStack.empty());
1177const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1181 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1183 if (ReadCount == 0) {
1187 if (ParentIncludeLoc != SMLoc()) {
1188 EndStatementAtEOFStack.pop_back();
1189 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1190 return peekTok(ShouldSkipSpace);
1192 EndStatementAtEOFStack.pop_back();
1193 assert(EndStatementAtEOFStack.empty());
1200bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1202 if (!NoInitialTextSection)
1203 Out.initSections(getTargetParser().getSTI());
1209 AsmCond StartingCondState = TheCondState;
1219 ParseStatementInfo
Info(&AsmStrRewrites);
1220 bool HasError = parseStatement(Info,
nullptr);
1225 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1229 printPendingErrors();
1232 if (HasError && !getLexer().justConsumedEOL())
1233 eatToEndOfStatement();
1236 printPendingErrors();
1239 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1243 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1252 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1253 if (std::get<2>(LocSym)->isUndefined()) {
1256 CppHashInfo = std::get<1>(LocSym);
1257 printError(std::get<0>(LocSym),
"directional label undefined");
1264 if (!HadError && !NoFinalize)
1265 Out.finish(Lexer.getLoc());
1270bool MasmParser::checkForValidSection() {
1271 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1272 getStreamer().getCurrentSectionOnly())) {
1273 Out.initSections(getTargetParser().getSTI());
1274 return Error(getTok().getLoc(),
1275 "expected section directive before assembly directive");
1281void MasmParser::eatToEndOfStatement() {
1285 if (ParentIncludeLoc == SMLoc()) {
1289 EndStatementAtEOFStack.pop_back();
1290 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1301SmallVector<StringRef, 1>
1303 SmallVector<StringRef, 1> Refs;
1304 const char *
Start = getTok().getLoc().getPointer();
1305 while (Lexer.isNot(EndTok)) {
1308 if (ParentIncludeLoc == SMLoc()) {
1313 EndStatementAtEOFStack.pop_back();
1314 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1316 Start = getTok().getLoc().getPointer();
1326 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1328 for (StringRef S : Refs) {
1329 Str.append(S.str());
1334StringRef MasmParser::parseStringToEndOfStatement() {
1335 const char *
Start = getTok().getLoc().getPointer();
1340 const char *
End = getTok().getLoc().getPointer();
1341 return StringRef(Start,
End - Start);
1349bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1350 if (parseExpression(Res))
1352 EndLoc = Lexer.getTok().getEndLoc();
1353 return parseRParen();
1361bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1362 if (parseExpression(Res))
1364 EndLoc = getTok().getEndLoc();
1365 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1378bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1379 AsmTypeInfo *TypeInfo) {
1380 SMLoc FirstTokenLoc = getLexer().getLoc();
1382 switch (FirstTokenKind) {
1384 return TokError(
"unknown token in expression");
1390 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1398 if (parseIdentifier(Identifier)) {
1401 if (Lexer.getMAI().getDollarIsPC()) {
1408 EndLoc = FirstTokenLoc;
1411 return Error(FirstTokenLoc,
"invalid token in expression");
1416 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1422 if (
Identifier.equals_insensitive(
"imagerel")) {
1423 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1425 if (
const MCExpr *ModifiedRes =
1430 return Error(FirstTokenLoc,
"cannot apply 'imagerel' to this expression");
1435 bool Before =
Identifier.equals_insensitive(
"@b");
1438 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1448 return Error(getLexer().getLoc(),
"expected a symbol reference");
1453 if (
Split.second.empty()) {
1456 if (lookUpField(SymbolName,
Split.second, Info)) {
1457 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1458 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1459 lookUpField(
Base, Member, Info);
1470 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1471 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1473 : BuiltinIt->getValue();
1474 if (Symbol != BI_NO_SYMBOL) {
1475 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1485 if (VarIt != Variables.
end())
1496 DoInline = TV->inlineAssignedExpr();
1504 const MCExpr *SymRef =
1514 if (
Info.Type.Name.empty()) {
1516 if (TypeIt != KnownType.
end()) {
1517 Info.Type = TypeIt->second;
1521 *TypeInfo =
Info.Type;
1526 return TokError(
"literal value out of range for directive");
1528 int64_t
IntVal = getTok().getIntVal();
1530 EndLoc = Lexer.getTok().getEndLoc();
1536 SMLoc ValueLoc = getTok().getLoc();
1538 if (parseEscapedString(
Value))
1540 if (
Value.size() > 8)
1541 return Error(ValueLoc,
"literal value out of range");
1543 for (
const unsigned char CharVal :
Value)
1544 IntValue = (IntValue << 8) | CharVal;
1549 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1552 EndLoc = Lexer.getTok().getEndLoc();
1562 EndLoc = Lexer.getTok().getEndLoc();
1568 return parseParenExpr(Res, EndLoc);
1570 if (!PlatformParser->HasBracketExpressions())
1571 return TokError(
"brackets expression not supported on this target");
1573 return parseBracketExpr(Res, EndLoc);
1576 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1582 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1588 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1595bool MasmParser::parseExpression(
const MCExpr *&Res) {
1597 return parseExpression(Res, EndLoc);
1608 "Argument to the function cannot be a NULL value");
1610 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1611 (*CharPtr !=
'\0')) {
1612 if (*CharPtr ==
'!')
1616 if (*CharPtr ==
'>') {
1626 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1627 if (BracketContents[Pos] ==
'!')
1629 Res += BracketContents[Pos];
1644bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1647 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1648 parseBinOpRHS(1, Res, EndLoc))
1654 if (Res->evaluateAsAbsolute(
Value))
1660bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1662 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1665bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1668 SMLoc StartLoc = Lexer.getLoc();
1669 if (parseExpression(Expr))
1672 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1673 return Error(StartLoc,
"expected absolute expression");
1680 bool ShouldUseLogicalShr,
1681 bool EndExpressionAtGreater) {
1709 if (EndExpressionAtGreater)
1750 if (EndExpressionAtGreater)
1761 AngleBracketDepth > 0);
1766bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1768 SMLoc StartLoc = Lexer.getLoc();
1772 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1788 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1792 if (TokPrec < Precedence)
1799 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1805 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1806 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1819bool MasmParser::parseStatement(ParseStatementInfo &Info,
1820 MCAsmParserSemaCallback *SI) {
1821 assert(!hasPendingError() &&
"parseStatement started with pending error");
1827 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1828 getTok().getString().
front() ==
'\n')
1837 SMLoc ExpansionLoc = getTok().getLoc();
1844 AsmToken
ID = getTok();
1845 SMLoc IDLoc =
ID.getLoc();
1848 return parseCppHashLineFilenameComment(IDLoc);
1855 IDVal = getTok().getString();
1858 return Error(IDLoc,
"unexpected token at start of statement");
1859 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1860 if (!TheCondState.
Ignore) {
1862 return Error(IDLoc,
"unexpected token at start of statement");
1871 DirectiveKindMap.find(IDVal.
lower());
1872 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1874 : DirKindIt->getValue();
1880 return parseDirectiveIf(IDLoc, DirKind);
1882 return parseDirectiveIfb(IDLoc,
true);
1884 return parseDirectiveIfb(IDLoc,
false);
1886 return parseDirectiveIfdef(IDLoc,
true);
1888 return parseDirectiveIfdef(IDLoc,
false);
1890 return parseDirectiveIfidn(IDLoc,
false,
1893 return parseDirectiveIfidn(IDLoc,
false,
1896 return parseDirectiveIfidn(IDLoc,
true,
1899 return parseDirectiveIfidn(IDLoc,
true,
1903 return parseDirectiveElseIf(IDLoc, DirKind);
1905 return parseDirectiveElseIfb(IDLoc,
true);
1907 return parseDirectiveElseIfb(IDLoc,
false);
1909 return parseDirectiveElseIfdef(IDLoc,
true);
1911 return parseDirectiveElseIfdef(IDLoc,
false);
1913 return parseDirectiveElseIfidn(IDLoc,
false,
1916 return parseDirectiveElseIfidn(IDLoc,
false,
1919 return parseDirectiveElseIfidn(IDLoc,
true,
1922 return parseDirectiveElseIfidn(IDLoc,
true,
1925 return parseDirectiveElse(IDLoc);
1927 return parseDirectiveEndIf(IDLoc);
1932 if (TheCondState.
Ignore) {
1933 eatToEndOfStatement();
1943 if (checkForValidSection())
1951 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1959 if (ParsingMSInlineAsm && SI) {
1960 StringRef RewrittenLabel =
1961 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1963 "We should have an internal name here.");
1966 IDVal = RewrittenLabel;
1969 if (IDVal ==
"@@") {
1992 if (!getTargetParser().isParsingMSInlineAsm())
1993 Out.emitLabel(Sym, IDLoc);
2002 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2007 if (DirKind != DK_NO_DIRECTIVE) {
2023 return parseDirectiveNestedEnds();
2028 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2031 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2037 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2039 "Should only return Failure iff there was an error");
2051 return parseDirectiveAscii(IDVal,
false);
2054 return parseDirectiveAscii(IDVal,
true);
2058 return parseDirectiveValue(IDVal, 1);
2062 return parseDirectiveValue(IDVal, 2);
2066 return parseDirectiveValue(IDVal, 4);
2069 return parseDirectiveValue(IDVal, 6);
2073 return parseDirectiveValue(IDVal, 8);
2075 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2077 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2079 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2082 return parseDirectiveNestedStruct(IDVal, DirKind);
2084 return parseDirectiveNestedEnds();
2086 return parseDirectiveAlign();
2088 return parseDirectiveEven();
2090 return parseDirectiveOrg();
2092 return parseDirectiveExtern();
2094 return parseDirectiveSymbolAttribute(
MCSA_Global);
2096 return parseDirectiveComm(
false);
2098 return parseDirectiveComment(IDLoc);
2100 return parseDirectiveInclude();
2102 return parseDirectiveRepeat(IDLoc, IDVal);
2104 return parseDirectiveWhile(IDLoc);
2106 return parseDirectiveFor(IDLoc, IDVal);
2108 return parseDirectiveForc(IDLoc, IDVal);
2110 Info.ExitValue =
"";
2111 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2113 Info.ExitValue =
"";
2114 return parseDirectiveEndMacro(IDVal);
2116 return parseDirectivePurgeMacro(IDLoc);
2118 return parseDirectiveEnd(IDLoc);
2120 return parseDirectiveError(IDLoc);
2122 return parseDirectiveErrorIfb(IDLoc,
true);
2124 return parseDirectiveErrorIfb(IDLoc,
false);
2126 return parseDirectiveErrorIfdef(IDLoc,
true);
2128 return parseDirectiveErrorIfdef(IDLoc,
false);
2130 return parseDirectiveErrorIfidn(IDLoc,
false,
2133 return parseDirectiveErrorIfidn(IDLoc,
false,
2136 return parseDirectiveErrorIfidn(IDLoc,
true,
2139 return parseDirectiveErrorIfidn(IDLoc,
true,
2142 return parseDirectiveErrorIfe(IDLoc,
true);
2144 return parseDirectiveErrorIfe(IDLoc,
false);
2146 return parseDirectiveRadix(IDLoc);
2148 return parseDirectiveEcho(IDLoc);
2151 return Error(IDLoc,
"unknown directive");
2155 auto IDIt = Structs.
find(IDVal.
lower());
2156 if (IDIt != Structs.
end())
2157 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2161 const AsmToken nextTok = getTok();
2162 const StringRef nextVal = nextTok.
getString();
2163 const SMLoc nextLoc = nextTok.
getLoc();
2165 const AsmToken afterNextTok = peekTok();
2176 getTargetParser().flushPendingInstructions(getStreamer());
2182 return parseDirectiveEnds(IDVal, IDLoc);
2187 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2189 if (Handler.first) {
2192 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2197 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2198 DirKind = (DirKindIt == DirectiveKindMap.end())
2200 : DirKindIt->getValue();
2207 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2209 Lex(DoNotExpandMacros);
2210 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2221 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2232 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2243 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2253 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2264 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2267 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2271 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2275 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2280 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2283 return parseDirectiveEnds(IDVal, IDLoc);
2286 return parseDirectiveMacro(IDVal, IDLoc);
2290 auto NextIt = Structs.
find(nextVal.
lower());
2291 if (NextIt != Structs.
end()) {
2293 return parseDirectiveNamedStructValue(NextIt->getValue(),
2294 nextVal, nextLoc, IDVal);
2298 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2299 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2300 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2303 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2304 return parseDirectiveMSAlign(IDLoc, Info);
2306 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2308 if (checkForValidSection())
2312 std::string OpcodeStr = IDVal.
lower();
2313 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2314 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2315 Info.ParsedOperands);
2316 Info.ParseError = ParseHadError;
2319 if (getShowParsedOperands()) {
2320 SmallString<256> Str;
2321 raw_svector_ostream OS(Str);
2322 OS <<
"parsed instruction: [";
2323 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2326 Info.ParsedOperands[i]->print(OS, MAI);
2334 if (hasPendingError() || ParseHadError)
2338 if (!ParseHadError) {
2340 if (getTargetParser().matchAndEmitInstruction(
2341 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2342 getTargetParser().isParsingMSInlineAsm()))
2349bool MasmParser::parseCurlyBlockScope(
2350 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2355 SMLoc StartLoc = Lexer.getLoc();
2368bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2373 "Lexing Cpp line comment: Expected Integer");
2374 int64_t LineNumber = getTok().getIntVal();
2377 "Lexing Cpp line comment: Expected String");
2378 StringRef
Filename = getTok().getString();
2386 CppHashInfo.Loc =
L;
2388 CppHashInfo.LineNumber = LineNumber;
2389 CppHashInfo.Buf = CurBuffer;
2390 if (FirstCppHashFilename.
empty())
2397void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2398 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2399 raw_ostream &OS =
errs();
2402 SMLoc DiagLoc = Diag.
getLoc();
2404 unsigned CppHashBuf =
2405 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2409 if (!Parser->SavedDiagHandler)
2415 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2416 DiagBuf != CppHashBuf) {
2417 if (Parser->SavedDiagHandler)
2418 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2420 Diag.
print(
nullptr, OS);
2427 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2430 int CppHashLocLineNo =
2431 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2433 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2439 if (Parser->SavedDiagHandler)
2440 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2442 NewDiag.print(
nullptr, OS);
2448 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2451bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2454 const std::vector<std::string> &Locals, SMLoc L) {
2456 if (NParameters !=
A.size())
2457 return Error(L,
"Wrong number of arguments");
2458 StringMap<std::string> LocalSymbols;
2461 for (StringRef
Local : Locals) {
2462 raw_string_ostream LocalName(Name);
2469 std::optional<char> CurrentQuote;
2470 while (!Body.
empty()) {
2472 std::size_t
End = Body.
size(), Pos = 0;
2473 std::size_t IdentifierPos =
End;
2474 for (; Pos !=
End; ++Pos) {
2477 if (Body[Pos] ==
'&')
2482 if (IdentifierPos ==
End)
2483 IdentifierPos = Pos;
2485 IdentifierPos =
End;
2489 if (!CurrentQuote) {
2490 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2491 CurrentQuote = Body[Pos];
2492 }
else if (Body[Pos] == CurrentQuote) {
2493 if (Pos + 1 !=
End && Body[Pos + 1] == CurrentQuote) {
2498 CurrentQuote.reset();
2502 if (IdentifierPos !=
End) {
2505 Pos = IdentifierPos;
2506 IdentifierPos =
End;
2510 OS << Body.
slice(0, Pos);
2517 bool InitialAmpersand = (Body[
I] ==
'&');
2518 if (InitialAmpersand) {
2525 const char *Begin = Body.
data() + Pos;
2527 const std::string ArgumentLower =
Argument.lower();
2531 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2534 if (Index == NParameters) {
2535 if (InitialAmpersand)
2537 auto it = LocalSymbols.
find(ArgumentLower);
2538 if (it != LocalSymbols.
end())
2544 for (
const AsmToken &Token :
A[Index]) {
2554 OS << Token.getIntVal();
2556 OS << Token.getString();
2560 if (Pos <
End && Body[Pos] ==
'&') {
2571bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2572 MCAsmMacroArgument &MA,
2575 if (Lexer.isNot(EndTok)) {
2576 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2577 for (StringRef S : Str) {
2584 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2586 const char *StrChar = StrLoc.
getPointer() + 1;
2587 const char *EndChar = EndLoc.
getPointer() - 1;
2588 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2595 unsigned ParenLevel = 0;
2599 return TokError(
"unexpected token");
2616 MA.push_back(getTok());
2620 if (ParenLevel != 0)
2621 return TokError(
"unbalanced parentheses in argument");
2623 if (MA.empty() && MP) {
2625 return TokError(
"missing value for required parameter '" + MP->
Name +
2635bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2636 MCAsmMacroArguments &
A,
2638 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2639 bool NamedParametersFound =
false;
2640 SmallVector<SMLoc, 4> FALocs;
2642 A.resize(NParameters);
2643 FALocs.
resize(NParameters);
2648 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2650 SMLoc IDLoc = Lexer.getLoc();
2651 MCAsmMacroParameter FA;
2654 if (parseIdentifier(FA.
Name))
2655 return Error(IDLoc,
"invalid argument identifier for formal argument");
2658 return TokError(
"expected '=' after formal parameter identifier");
2662 NamedParametersFound =
true;
2665 if (NamedParametersFound && FA.
Name.
empty())
2666 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2670 assert(M &&
"expected macro to be defined");
2672 for (FAI = 0; FAI < NParameters; ++FAI)
2673 if (
M->Parameters[FAI].Name == FA.
Name)
2676 if (FAI >= NParameters) {
2677 return Error(IDLoc,
"parameter named '" + FA.
Name +
2678 "' does not exist for macro '" +
M->Name +
"'");
2682 const MCAsmMacroParameter *MP =
nullptr;
2683 if (M && PI < NParameters)
2684 MP = &
M->Parameters[PI];
2686 SMLoc StrLoc = Lexer.getLoc();
2689 const MCExpr *AbsoluteExp;
2693 if (parseExpression(AbsoluteExp, EndLoc))
2695 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2696 getStreamer().getAssemblerPtr()))
2697 return Error(StrLoc,
"expected absolute expression");
2701 StringRef(StrChar, EndChar - StrChar),
Value);
2702 FA.
Value.push_back(newToken);
2703 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2705 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2710 if (!FA.
Value.empty()) {
2715 if (FALocs.
size() <= PI)
2718 FALocs[PI] = Lexer.getLoc();
2724 if (Lexer.is(EndTok)) {
2726 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2728 if (
M->Parameters[FAI].Required) {
2729 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2730 "missing value for required parameter "
2732 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2736 if (!
M->Parameters[FAI].Value.empty())
2737 A[FAI] =
M->Parameters[FAI].Value;
2747 return TokError(
"too many positional arguments");
2750bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2755 if (ActiveMacros.size() == MaxNestingDepth) {
2756 std::ostringstream MaxNestingDepthError;
2757 MaxNestingDepthError <<
"macros cannot be nested more than "
2758 << MaxNestingDepth <<
" levels deep."
2759 <<
" Use -asm-macro-max-nesting-depth to increase "
2761 return TokError(MaxNestingDepthError.str());
2764 MCAsmMacroArguments
A;
2765 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2770 SmallString<256> Buf;
2771 StringRef Body =
M->Body;
2772 raw_svector_ostream OS(Buf);
2774 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2781 std::unique_ptr<MemoryBuffer> Instantiation =
2786 MacroInstantiation *
MI =
new MacroInstantiation{
2787 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2788 ActiveMacros.push_back(
MI);
2790 ++NumOfMacroInstantiations;
2795 EndStatementAtEOFStack.push_back(
true);
2801void MasmParser::handleMacroExit() {
2803 EndStatementAtEOFStack.pop_back();
2804 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2805 EndStatementAtEOFStack.back());
2809 delete ActiveMacros.back();
2810 ActiveMacros.pop_back();
2813bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2815 return Error(NameLoc,
"cannot invoke macro procedure as function");
2818 "' requires arguments in parentheses") ||
2823 std::string ExitValue;
2826 ParseStatementInfo
Info(&AsmStrRewrites);
2827 bool HasError = parseStatement(Info,
nullptr);
2829 if (!HasError &&
Info.ExitValue) {
2830 ExitValue = std::move(*
Info.ExitValue);
2837 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2841 printPendingErrors();
2844 if (HasError && !getLexer().justConsumedEOL())
2845 eatToEndOfStatement();
2850 std::unique_ptr<MemoryBuffer> MacroValue =
2858 EndStatementAtEOFStack.push_back(
false);
2867bool MasmParser::parseIdentifier(StringRef &Res,
2868 IdentifierPositionKind Position) {
2875 SMLoc PrefixLoc = getLexer().getLoc();
2879 AsmToken nextTok = peekTok(
false);
2892 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2900 Res = getTok().getIdentifier();
2904 ExpandKind ExpandNextToken = ExpandMacros;
2905 if (Position == StartOfStatement &&
2906 StringSwitch<bool>(Res)
2907 .CaseLower(
"echo",
true)
2908 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2910 ExpandNextToken = DoNotExpandMacros;
2912 Lex(ExpandNextToken);
2922bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2923 DirectiveKind DirKind, SMLoc NameLoc) {
2924 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2925 if (BuiltinIt != BuiltinSymbolMap.end())
2926 return Error(NameLoc,
"cannot redefine a built-in symbol");
2929 if (Var.Name.empty()) {
2933 SMLoc StartLoc = Lexer.getLoc();
2939 if (!parseTextList(
Value, IDVal))
2940 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2941 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2948 if (!parseAngleBracketString(
Value))
2949 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2959 if (parseExpression(Expr, EndLoc))
2960 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2961 StringRef ExprAsString = StringRef(
2965 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2966 if (DirKind == DK_ASSIGN)
2969 "expected absolute expression; not all symbols have known values",
2970 {StartLoc, EndLoc});
2973 return setTextVariable(Var, Name, ExprAsString, NameLoc,
2974 Variable::REDEFINABLE);
2977 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
2978 const MCConstantExpr *PrevValue =
2982 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
2983 switch (Var.Redefinable) {
2984 case Variable::NOT_REDEFINABLE:
2985 return Error(getTok().getLoc(),
"invalid variable redefinition");
2986 case Variable::WARN_ON_REDEFINITION:
2987 if (
Warning(NameLoc,
"redefining '" + Name +
2988 "', already defined on the command line"))
2997 Var.TextValue.clear();
2998 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3001 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3003 Sym->setExternal(
false);
3008bool MasmParser::parseEscapedString(std::string &
Data) {
3013 char Quote = getTok().getString().front();
3014 StringRef Str = getTok().getStringContents();
3015 Data.reserve(Str.size());
3016 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3017 Data.push_back(Str[i]);
3018 if (Str[i] == Quote) {
3022 if (i + 1 == Str.size())
3023 return Error(getTok().getLoc(),
"missing quotation mark in string");
3024 if (Str[i + 1] == Quote)
3033bool MasmParser::parseAngleBracketString(std::string &
Data) {
3034 SMLoc EndLoc, StartLoc = getTok().getLoc();
3036 const char *StartChar = StartLoc.
getPointer() + 1;
3037 const char *EndChar = EndLoc.
getPointer() - 1;
3038 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3049bool MasmParser::parseTextItem(std::string &
Data) {
3050 switch (getTok().getKind()) {
3057 Data = std::to_string(Res);
3064 return parseAngleBracketString(
Data);
3068 SMLoc StartLoc = getTok().getLoc();
3069 if (parseIdentifier(ID))
3073 bool Expanded =
false;
3076 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3077 if (BuiltinIt != BuiltinSymbolMap.end()) {
3078 std::optional<std::string> BuiltinText =
3079 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3084 Data = std::move(*BuiltinText);
3091 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3092 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3094 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID,
Data)) {
3103 auto VarIt = Variables.
find(
ID.lower());
3104 if (VarIt != Variables.
end()) {
3105 const Variable &Var = VarIt->getValue();
3110 Data = Var.TextValue;
3132bool MasmParser::parseTextList(std::string &Result, StringRef IDVal) {
3133 std::string TextItem;
3134 if (parseTextItem(TextItem))
3138 Lex(DoNotExpandMacros);
3140 Lex(DoNotExpandMacros);
3141 if (parseTextItem(TextItem))
3142 return TokError(
"expected text item in '" + Twine(IDVal) +
"' directive");
3149bool MasmParser::setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
3151 Variable::RedefinableKind Redefinable) {
3152 if (!Var.IsText || Var.TextValue !=
Value) {
3153 switch (Var.Redefinable) {
3154 case Variable::NOT_REDEFINABLE:
3155 return Error(getTok().getLoc(),
"invalid variable redefinition");
3156 case Variable::WARN_ON_REDEFINITION:
3157 if (
Warning(NameLoc,
"redefining '" + Name +
3158 "', already defined on the command line"))
3166 Var.TextValue =
Value.str();
3167 Var.Redefinable = Redefinable;
3173bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3174 auto parseOp = [&]() ->
bool {
3176 if (checkForValidSection() || parseEscapedString(
Data))
3178 getStreamer().emitBytes(
Data);
3180 getStreamer().emitBytes(StringRef(
"\0", 1));
3184 if (parseMany(parseOp))
3185 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3189bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3193 int64_t IntValue = MCE->getValue();
3195 return Error(MCE->getLoc(),
"out of range literal value");
3196 getStreamer().emitIntValue(IntValue,
Size);
3201 getStreamer().emitIntValue(0,
Size);
3209bool MasmParser::parseScalarInitializer(
unsigned Size,
3210 SmallVectorImpl<const MCExpr *> &
Values,
3211 unsigned StringPadLength) {
3214 if (parseEscapedString(
Value))
3217 for (
const unsigned char CharVal :
Value)
3221 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3224 const MCExpr *
Value;
3225 if (parseExpression(
Value))
3228 getTok().getString().equals_insensitive(
"dup")) {
3233 "cannot repeat value a non-constant number of times");
3234 const int64_t Repetitions = MCE->
getValue();
3235 if (Repetitions < 0)
3237 "cannot repeat value a negative number of times");
3241 "parentheses required for 'dup' contents") ||
3242 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3245 for (
int i = 0; i < Repetitions; ++i)
3254bool MasmParser::parseScalarInstList(
unsigned Size,
3255 SmallVectorImpl<const MCExpr *> &
Values,
3257 while (getTok().
isNot(EndToken) &&
3270bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3272 if (checkForValidSection() || parseScalarInstList(
Size,
Values))
3284bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3285 StructInfo &
Struct = StructInProgress.
back();
3287 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3291 if (parseScalarInstList(
Size, IntInfo.Values))
3294 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3295 Field.LengthOf = IntInfo.Values.size();
3298 Struct.NextOffset = FieldEnd;
3306bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3307 if (StructInProgress.
empty()) {
3309 if (emitIntegralValues(
Size))
3310 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3311 }
else if (addIntegralField(
"",
Size)) {
3312 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3320bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3321 StringRef Name, SMLoc NameLoc) {
3322 if (StructInProgress.
empty()) {
3325 getStreamer().emitLabel(Sym);
3328 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3336 }
else if (addIntegralField(Name,
Size)) {
3337 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3343bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3349 SignLoc = getLexer().getLoc();
3353 SignLoc = getLexer().getLoc();
3358 return TokError(Lexer.getErr());
3361 return TokError(
"unexpected token in directive");
3365 StringRef IDVal = getTok().getString();
3374 return TokError(
"invalid floating point literal");
3378 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3379 if (SizeInBits != (IDVal.
size() << 2))
3380 return TokError(
"invalid floating point literal");
3385 Res = APInt(SizeInBits, IDVal, 16);
3387 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3390 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3392 return TokError(
"invalid floating point literal");
3400 Res =
Value.bitcastToAPInt();
3405bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3406 SmallVectorImpl<APInt> &ValuesAsInt,
3408 while (getTok().
isNot(EndToken) ||
3411 const AsmToken NextTok = peekTok();
3414 const MCExpr *
Value;
3420 "cannot repeat value a non-constant number of times");
3421 const int64_t Repetitions = MCE->
getValue();
3422 if (Repetitions < 0)
3424 "cannot repeat value a negative number of times");
3428 "parentheses required for 'dup' contents") ||
3429 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3432 for (
int i = 0; i < Repetitions; ++i)
3433 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3436 if (parseRealValue(Semantics, AsInt))
3451bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3453 if (checkForValidSection())
3457 if (parseRealInstList(Semantics, ValuesAsInt))
3460 for (
const APInt &AsInt : ValuesAsInt) {
3461 getStreamer().emitIntValue(AsInt);
3464 *
Count = ValuesAsInt.size();
3469bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3471 StructInfo &
Struct = StructInProgress.
back();
3473 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3477 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3480 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3481 Field.LengthOf = RealInfo.AsIntValues.size();
3486 Struct.NextOffset = FieldEnd;
3494bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3495 const fltSemantics &Semantics,
3497 if (StructInProgress.
empty()) {
3499 if (emitRealValues(Semantics))
3500 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3501 }
else if (addRealField(
"", Semantics,
Size)) {
3502 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3509bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3510 const fltSemantics &Semantics,
3511 unsigned Size, StringRef Name,
3513 if (StructInProgress.
empty()) {
3516 getStreamer().emitLabel(Sym);
3518 if (emitRealValues(Semantics, &
Count))
3519 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3527 }
else if (addRealField(Name, Semantics,
Size)) {
3528 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3533bool MasmParser::parseOptionalAngleBracketOpen() {
3534 const AsmToken Tok = getTok();
3536 AngleBracketDepth++;
3540 AngleBracketDepth++;
3544 AngleBracketDepth++;
3551bool MasmParser::parseAngleBracketClose(
const Twine &
Msg) {
3552 const AsmToken Tok = getTok();
3558 AngleBracketDepth--;
3562bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3563 const IntFieldInfo &Contents,
3564 FieldInitializer &Initializer) {
3565 SMLoc Loc = getTok().getLoc();
3570 return Error(Loc,
"Cannot initialize scalar field with array value");
3574 }
else if (parseOptionalAngleBracketOpen()) {
3576 return Error(Loc,
"Cannot initialize scalar field with array value");
3578 parseAngleBracketClose())
3580 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3581 return Error(Loc,
"Cannot initialize array field with scalar value");
3582 }
else if (parseScalarInitializer(
Field.Type,
Values,
3588 return Error(Loc,
"Initializer too long for field; expected at most " +
3589 std::to_string(
Field.LengthOf) +
" elements, got " +
3590 std::to_string(
Values.size()));
3593 Values.append(Contents.Values.begin() +
Values.size(), Contents.Values.end());
3595 Initializer = FieldInitializer(std::move(
Values));
3599bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3600 const RealFieldInfo &Contents,
3601 FieldInitializer &Initializer) {
3602 const fltSemantics *Semantics;
3603 switch (
Field.Type) {
3605 Semantics = &APFloat::IEEEsingle();
3608 Semantics = &APFloat::IEEEdouble();
3611 Semantics = &APFloat::x87DoubleExtended();
3617 SMLoc Loc = getTok().getLoc();
3621 if (
Field.LengthOf == 1)
3622 return Error(Loc,
"Cannot initialize scalar field with array value");
3626 }
else if (parseOptionalAngleBracketOpen()) {
3627 if (
Field.LengthOf == 1)
3628 return Error(Loc,
"Cannot initialize scalar field with array value");
3630 parseAngleBracketClose())
3632 }
else if (
Field.LengthOf > 1) {
3633 return Error(Loc,
"Cannot initialize array field with scalar value");
3636 if (parseRealValue(*Semantics, AsIntValues.
back()))
3640 if (AsIntValues.
size() >
Field.LengthOf) {
3641 return Error(Loc,
"Initializer too long for field; expected at most " +
3642 std::to_string(
Field.LengthOf) +
" elements, got " +
3643 std::to_string(AsIntValues.
size()));
3646 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3647 Contents.AsIntValues.end());
3649 Initializer = FieldInitializer(std::move(AsIntValues));
3653bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3654 const StructFieldInfo &Contents,
3655 FieldInitializer &Initializer) {
3656 SMLoc Loc = getTok().getLoc();
3658 std::vector<StructInitializer> Initializers;
3659 if (
Field.LengthOf > 1) {
3661 if (parseStructInstList(Contents.Structure, Initializers,
3665 }
else if (parseOptionalAngleBracketOpen()) {
3666 if (parseStructInstList(Contents.Structure, Initializers,
3668 parseAngleBracketClose())
3671 return Error(Loc,
"Cannot initialize array field with scalar value");
3674 Initializers.emplace_back();
3675 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3679 if (Initializers.size() >
Field.LengthOf) {
3680 return Error(Loc,
"Initializer too long for field; expected at most " +
3681 std::to_string(
Field.LengthOf) +
" elements, got " +
3682 std::to_string(Initializers.size()));
3686 Initializers.size()));
3688 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3692bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3693 FieldInitializer &Initializer) {
3694 switch (
Field.Contents.FT) {
3696 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3698 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3700 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3705bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3706 StructInitializer &Initializer) {
3707 const AsmToken FirstToken = getTok();
3709 std::optional<AsmToken::TokenKind> EndToken;
3712 }
else if (parseOptionalAngleBracketOpen()) {
3714 AngleBracketDepth++;
3721 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3724 auto &FieldInitializers = Initializer.FieldInitializers;
3725 size_t FieldIndex = 0;
3728 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3729 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3733 FieldInitializers.push_back(
Field.Contents);
3737 FieldInitializers.emplace_back(
Field.Contents.FT);
3738 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3742 SMLoc CommaLoc = getTok().getLoc();
3745 if (FieldIndex == Structure.Fields.size())
3746 return Error(CommaLoc,
"'" + Structure.Name +
3747 "' initializer initializes too many fields");
3753 FieldInitializers.push_back(
Field.Contents);
3757 return parseAngleBracketClose();
3759 return parseToken(*EndToken);
3765bool MasmParser::parseStructInstList(
3766 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3768 while (getTok().
isNot(EndToken) ||
3771 const AsmToken NextTok = peekTok();
3774 const MCExpr *
Value;
3780 "cannot repeat value a non-constant number of times");
3781 const int64_t Repetitions = MCE->
getValue();
3782 if (Repetitions < 0)
3784 "cannot repeat value a negative number of times");
3786 std::vector<StructInitializer> DuplicatedValues;
3788 "parentheses required for 'dup' contents") ||
3789 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3792 for (
int i = 0; i < Repetitions; ++i)
3795 Initializers.emplace_back();
3796 if (parseStructInitializer(Structure, Initializers.back()))
3809bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3810 const IntFieldInfo &Contents) {
3812 for (
const MCExpr *
Value : Contents.Values) {
3819bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3820 const RealFieldInfo &Contents) {
3821 for (
const APInt &AsInt : Contents.AsIntValues) {
3828bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3829 const StructFieldInfo &Contents) {
3830 for (
const auto &Initializer : Contents.Initializers) {
3832 for (
const auto &SubField : Contents.Structure.Fields) {
3833 getStreamer().emitZeros(SubField.Offset -
Offset);
3834 Offset = SubField.Offset + SubField.SizeOf;
3835 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3841bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3842 switch (
Field.Contents.FT) {
3844 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3846 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3848 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3853bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3854 const IntFieldInfo &Contents,
3855 const IntFieldInfo &Initializer) {
3856 for (
const auto &
Value : Initializer.Values) {
3861 for (
const auto &
Value :
3869bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3870 const RealFieldInfo &Contents,
3871 const RealFieldInfo &Initializer) {
3872 for (
const auto &AsInt : Initializer.AsIntValues) {
3877 for (
const auto &AsInt :
3885bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3886 const StructFieldInfo &Contents,
3887 const StructFieldInfo &Initializer) {
3888 for (
const auto &Init : Initializer.Initializers) {
3889 if (emitStructInitializer(Contents.Structure, Init))
3894 Initializer.Initializers.size())) {
3895 if (emitStructInitializer(Contents.Structure, Init))
3901bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3902 const FieldInitializer &Initializer) {
3903 switch (
Field.Contents.FT) {
3905 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3906 Initializer.IntInfo);
3908 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3909 Initializer.RealInfo);
3911 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3912 Initializer.StructInfo);
3917bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3918 const StructInitializer &Initializer) {
3919 if (!Structure.Initializable)
3920 return Error(getLexer().getLoc(),
3921 "cannot initialize a value of type '" + Structure.Name +
3922 "'; 'org' was used in the type's declaration");
3924 for (
const auto &Init : Initializer.FieldInitializers) {
3925 const auto &
Field = Structure.Fields[
Index++];
3928 if (emitFieldInitializer(
Field, Init))
3933 Structure.Fields, Initializer.FieldInitializers.size())) {
3936 if (emitFieldValue(
Field))
3940 if (
Offset != Structure.Size)
3941 getStreamer().emitZeros(Structure.Size -
Offset);
3946bool MasmParser::emitStructValues(
const StructInfo &Structure,
3948 std::vector<StructInitializer> Initializers;
3949 if (parseStructInstList(Structure, Initializers))
3952 for (
const auto &Initializer : Initializers) {
3953 if (emitStructInitializer(Structure, Initializer))
3958 *
Count = Initializers.size();
3963bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3964 StructInfo &OwningStruct = StructInProgress.
back();
3966 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3967 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3969 StructInfo.Structure = Structure;
3970 Field.Type = Structure.Size;
3972 if (parseStructInstList(Structure, StructInfo.Initializers))
3975 Field.LengthOf = StructInfo.Initializers.size();
3979 if (!OwningStruct.IsUnion) {
3980 OwningStruct.NextOffset = FieldEnd;
3982 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3990bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3991 StringRef Directive, SMLoc DirLoc) {
3992 if (StructInProgress.
empty()) {
3993 if (emitStructValues(Structure))
3995 }
else if (addStructField(
"", Structure)) {
3996 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4004bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
4005 StringRef Directive,
4006 SMLoc DirLoc, StringRef Name) {
4007 if (StructInProgress.
empty()) {
4010 getStreamer().emitLabel(Sym);
4012 if (emitStructValues(Structure, &
Count))
4015 Type.Name = Structure.Name;
4017 Type.ElementSize = Structure.Size;
4020 }
else if (addStructField(Name, Structure)) {
4021 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4033bool MasmParser::parseDirectiveStruct(StringRef Directive,
4034 DirectiveKind DirKind, StringRef Name,
4038 AsmToken NextTok = getTok();
4039 int64_t AlignmentValue = 1;
4042 parseAbsoluteExpression(AlignmentValue)) {
4043 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4047 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4048 std::to_string(AlignmentValue));
4054 QualifierLoc = getTok().getLoc();
4055 if (parseIdentifier(Qualifier))
4056 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4057 if (!
Qualifier.equals_insensitive(
"nonunique"))
4058 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4060 "' directive; expected none or NONUNIQUE");
4064 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4066 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4074bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4075 DirectiveKind DirKind) {
4076 if (StructInProgress.
empty())
4077 return TokError(
"missing name in top-level '" + Twine(Directive) +
4082 Name = getTok().getIdentifier();
4086 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4090 StructInProgress.
reserve(StructInProgress.
size() + 1);
4091 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4092 StructInProgress.
back().Alignment);
4096bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4097 if (StructInProgress.
empty())
4098 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4099 if (StructInProgress.
size() > 1)
4100 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4101 if (StructInProgress.
back().Name.compare_insensitive(Name))
4102 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4103 StructInProgress.
back().Name +
"'");
4104 StructInfo Structure = StructInProgress.
pop_back_val();
4108 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4109 Structs[
Name.lower()] = std::move(Structure);
4112 return addErrorSuffix(
" in ENDS directive");
4117bool MasmParser::parseDirectiveNestedEnds() {
4118 if (StructInProgress.
empty())
4119 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4120 if (StructInProgress.
size() == 1)
4121 return TokError(
"missing name in top-level ENDS directive");
4124 return addErrorSuffix(
" in nested ENDS directive");
4126 StructInfo Structure = StructInProgress.
pop_back_val();
4128 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4130 StructInfo &ParentStruct = StructInProgress.
back();
4131 if (Structure.Name.
empty()) {
4134 const size_t OldFields = ParentStruct.Fields.size();
4135 ParentStruct.Fields.insert(
4136 ParentStruct.Fields.end(),
4137 std::make_move_iterator(Structure.Fields.begin()),
4138 std::make_move_iterator(Structure.Fields.end()));
4139 for (
const auto &FieldByName : Structure.FieldsByName) {
4140 ParentStruct.FieldsByName[FieldByName.getKey()] =
4141 FieldByName.getValue() + OldFields;
4144 unsigned FirstFieldOffset = 0;
4145 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4147 ParentStruct.NextOffset,
4148 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4151 if (ParentStruct.IsUnion) {
4152 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4157 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4158 if (!ParentStruct.IsUnion) {
4159 ParentStruct.NextOffset = StructureEnd;
4161 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4164 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4165 Structure.AlignmentSize);
4166 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4167 Field.Type = Structure.Size;
4169 Field.SizeOf = Structure.Size;
4172 if (!ParentStruct.IsUnion) {
4173 ParentStruct.NextOffset = StructureEnd;
4175 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4177 StructInfo.Structure = Structure;
4178 StructInfo.Initializers.emplace_back();
4179 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4180 for (
const auto &SubField : Structure.Fields) {
4181 FieldInitializers.push_back(SubField.Contents);
4190bool MasmParser::parseDirectiveOrg() {
4192 SMLoc OffsetLoc = Lexer.getLoc();
4193 if (checkForValidSection() || parseExpression(
Offset))
4196 return addErrorSuffix(
" in 'org' directive");
4198 if (StructInProgress.
empty()) {
4200 if (checkForValidSection())
4201 return addErrorSuffix(
" in 'org' directive");
4203 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4206 StructInfo &Structure = StructInProgress.
back();
4208 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4209 return Error(OffsetLoc,
4210 "expected absolute expression in 'org' directive");
4214 "expected non-negative value in struct's 'org' directive; was " +
4215 std::to_string(OffsetRes));
4216 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4219 Structure.Initializable =
false;
4225bool MasmParser::emitAlignTo(int64_t Alignment) {
4226 if (StructInProgress.
empty()) {
4228 if (checkForValidSection())
4233 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4235 getStreamer().emitCodeAlignment(
Align(Alignment),
4236 getTargetParser().getSTI(),
4240 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4246 StructInfo &Structure = StructInProgress.
back();
4247 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4255bool MasmParser::parseDirectiveAlign() {
4256 SMLoc AlignmentLoc = getLexer().getLoc();
4262 "align directive with no operand is ignored") &&
4265 if (parseAbsoluteExpression(Alignment) || parseEOL())
4266 return addErrorSuffix(
" in align directive");
4269 bool ReturnVal =
false;
4276 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4277 std::to_string(Alignment));
4279 if (emitAlignTo(Alignment))
4280 ReturnVal |= addErrorSuffix(
" in align directive");
4287bool MasmParser::parseDirectiveEven() {
4288 if (parseEOL() || emitAlignTo(2))
4289 return addErrorSuffix(
" in even directive");
4300bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4304 return Error(Lexer.getLoc(),
4305 "Vararg parameter '" +
Parameters.back().Name +
4306 "' should be last in the list of parameters");
4310 return TokError(
"expected identifier in 'macro' directive");
4313 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4314 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4315 return TokError(
"macro '" + Name +
"' has multiple parameters"
4325 ParamLoc = Lexer.getLoc();
4326 if (parseMacroArgument(
nullptr,
Parameter.Value))
4332 QualLoc = Lexer.getLoc();
4333 if (parseIdentifier(Qualifier))
4334 return Error(QualLoc,
"missing parameter qualifier for "
4336 Parameter.Name +
"' in macro '" + Name +
4339 if (
Qualifier.equals_insensitive(
"req"))
4341 else if (
Qualifier.equals_insensitive(
"vararg"))
4344 return Error(QualLoc,
4345 Qualifier +
" is not a valid parameter qualifier for '" +
4346 Parameter.Name +
"' in macro '" + Name +
"'");
4359 std::vector<std::string>
Locals;
4361 getTok().getIdentifier().equals_insensitive(
"local")) {
4366 if (parseIdentifier(ID))
4378 AsmToken EndToken, StartToken = getTok();
4379 unsigned MacroDepth = 0;
4380 bool IsMacroFunction =
false;
4390 return Error(NameLoc,
"no matching 'endm' in definition");
4395 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4396 if (MacroDepth == 0) {
4397 EndToken = getTok();
4400 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4407 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4409 IsMacroFunction =
true;
4411 }
else if (isMacroLikeDirective()) {
4419 eatToEndOfStatement();
4423 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4428 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4429 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4439bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4440 StringRef Directive,
4441 std::string &
Value) {
4442 SMLoc EndLoc = getTok().getLoc();
4444 return Error(EndLoc,
4445 "unable to parse text item in '" + Directive +
"' directive");
4446 eatToEndOfStatement();
4448 if (!isInsideMacroInstantiation())
4449 return TokError(
"unexpected '" + Directive +
"' in file, "
4450 "no current macro definition");
4453 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4454 TheCondState = TheCondStack.back();
4455 TheCondStack.pop_back();
4464bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4466 return TokError(
"unexpected token in '" + Directive +
"' directive");
4470 if (isInsideMacroInstantiation()) {
4477 return TokError(
"unexpected '" + Directive +
"' in file, "
4478 "no current macro definition");
4483bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4487 if (parseTokenLoc(NameLoc) ||
4488 check(parseIdentifier(Name), NameLoc,
4489 "expected identifier in 'purge' directive"))
4493 <<
"Un-defining macro: " << Name <<
"\n");
4495 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4506bool MasmParser::parseDirectiveExtern() {
4508 auto parseOp = [&]() ->
bool {
4510 SMLoc NameLoc = getTok().getLoc();
4512 return Error(NameLoc,
"expected name");
4517 SMLoc TypeLoc = getTok().getLoc();
4518 if (parseIdentifier(TypeName))
4519 return Error(TypeLoc,
"expected type");
4520 if (!
TypeName.equals_insensitive(
"proc")) {
4522 if (lookUpType(TypeName,
Type))
4523 return Error(TypeLoc,
"unrecognized type");
4527 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4528 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4533 if (parseMany(parseOp))
4534 return addErrorSuffix(
" in directive 'extern'");
4540bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4541 auto parseOp = [&]() ->
bool {
4542 SMLoc Loc = getTok().getLoc();
4545 return Error(Loc,
"expected identifier");
4549 return Error(Loc,
"non-local symbol required");
4551 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4552 return Error(Loc,
"unable to emit symbol attribute");
4556 if (parseMany(parseOp))
4557 return addErrorSuffix(
" in directive");
4563bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4564 if (checkForValidSection())
4567 SMLoc IDLoc = getLexer().getLoc();
4570 return TokError(
"expected identifier in directive");
4573 return TokError(
"unexpected token in directive");
4577 SMLoc SizeLoc = getLexer().getLoc();
4578 if (parseAbsoluteExpression(
Size))
4581 int64_t Pow2Alignment = 0;
4582 SMLoc Pow2AlignmentLoc;
4585 Pow2AlignmentLoc = getLexer().getLoc();
4586 if (parseAbsoluteExpression(Pow2Alignment))
4591 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4594 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4597 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4598 Pow2Alignment =
Log2_64(Pow2Alignment);
4608 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4609 "be less than zero");
4614 if (Pow2Alignment < 0)
4615 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4616 "alignment, can't be less than zero");
4620 return Error(IDLoc,
"invalid symbol redefinition");
4624 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4637bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4639 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4640 assert(DelimiterEnd != std::string::npos);
4641 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4642 if (Delimiter.
empty())
4643 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4646 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4656bool MasmParser::parseDirectiveInclude() {
4659 SMLoc IncludeLoc = getTok().getLoc();
4661 if (parseAngleBracketString(
Filename))
4663 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4665 "unexpected token in 'include' directive") ||
4668 check(enterIncludeFile(
Filename), IncludeLoc,
4669 "Could not find include file '" +
Filename +
"'"))
4677bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4678 TheCondStack.push_back(TheCondState);
4680 if (TheCondState.
Ignore) {
4681 eatToEndOfStatement();
4684 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4693 ExprValue = ExprValue == 0;
4697 TheCondState.
CondMet = ExprValue;
4706bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4707 TheCondStack.push_back(TheCondState);
4710 if (TheCondState.
Ignore) {
4711 eatToEndOfStatement();
4714 if (parseTextItem(Str))
4715 return TokError(
"expected text item parameter for 'ifb' directive");
4720 TheCondState.
CondMet = ExpectBlank == Str.empty();
4729bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4730 bool CaseInsensitive) {
4731 std::string String1, String2;
4733 if (parseTextItem(String1)) {
4735 return TokError(
"expected text item parameter for 'ifidn' directive");
4736 return TokError(
"expected text item parameter for 'ifdif' directive");
4742 "expected comma after first string for 'ifidn' directive");
4743 return TokError(
"expected comma after first string for 'ifdif' directive");
4747 if (parseTextItem(String2)) {
4749 return TokError(
"expected text item parameter for 'ifidn' directive");
4750 return TokError(
"expected text item parameter for 'ifdif' directive");
4753 TheCondStack.push_back(TheCondState);
4755 if (CaseInsensitive)
4757 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4759 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4768bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4769 TheCondStack.push_back(TheCondState);
4772 if (TheCondState.
Ignore) {
4773 eatToEndOfStatement();
4775 bool is_defined =
false;
4777 SMLoc StartLoc, EndLoc;
4779 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4782 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4786 if (BuiltinSymbolMap.contains(
Name.lower())) {
4796 TheCondState.
CondMet = (is_defined == expect_defined);
4805bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4806 DirectiveKind DirKind) {
4809 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4810 " .if or an .elseif");
4813 bool LastIgnoreState =
false;
4814 if (!TheCondStack.empty())
4815 LastIgnoreState = TheCondStack.back().Ignore;
4816 if (LastIgnoreState || TheCondState.
CondMet) {
4817 TheCondState.
Ignore =
true;
4818 eatToEndOfStatement();
4821 if (parseAbsoluteExpression(ExprValue))
4833 ExprValue = ExprValue == 0;
4837 TheCondState.
CondMet = ExprValue;
4846bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4849 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4850 " if or an elseif");
4853 bool LastIgnoreState =
false;
4854 if (!TheCondStack.empty())
4855 LastIgnoreState = TheCondStack.back().Ignore;
4856 if (LastIgnoreState || TheCondState.
CondMet) {
4857 TheCondState.
Ignore =
true;
4858 eatToEndOfStatement();
4861 if (parseTextItem(Str)) {
4863 return TokError(
"expected text item parameter for 'elseifb' directive");
4864 return TokError(
"expected text item parameter for 'elseifnb' directive");
4870 TheCondState.
CondMet = ExpectBlank == Str.empty();
4880bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4881 bool expect_defined) {
4884 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4885 " if or an elseif");
4888 bool LastIgnoreState =
false;
4889 if (!TheCondStack.empty())
4890 LastIgnoreState = TheCondStack.back().Ignore;
4891 if (LastIgnoreState || TheCondState.
CondMet) {
4892 TheCondState.
Ignore =
true;
4893 eatToEndOfStatement();
4895 bool is_defined =
false;
4897 SMLoc StartLoc, EndLoc;
4899 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4902 if (check(parseIdentifier(Name),
4903 "expected identifier after 'elseifdef'") ||
4907 if (BuiltinSymbolMap.contains(
Name.lower())) {
4917 TheCondState.
CondMet = (is_defined == expect_defined);
4926bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4927 bool CaseInsensitive) {
4930 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4931 " if or an elseif");
4934 bool LastIgnoreState =
false;
4935 if (!TheCondStack.empty())
4936 LastIgnoreState = TheCondStack.back().Ignore;
4937 if (LastIgnoreState || TheCondState.
CondMet) {
4938 TheCondState.
Ignore =
true;
4939 eatToEndOfStatement();
4941 std::string String1, String2;
4943 if (parseTextItem(String1)) {
4946 "expected text item parameter for 'elseifidn' directive");
4947 return TokError(
"expected text item parameter for 'elseifdif' directive");
4953 "expected comma after first string for 'elseifidn' directive");
4955 "expected comma after first string for 'elseifdif' directive");
4959 if (parseTextItem(String2)) {
4962 "expected text item parameter for 'elseifidn' directive");
4963 return TokError(
"expected text item parameter for 'elseifdif' directive");
4966 if (CaseInsensitive)
4968 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4970 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4979bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4985 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4988 bool LastIgnoreState =
false;
4989 if (!TheCondStack.empty())
4990 LastIgnoreState = TheCondStack.back().Ignore;
4991 if (LastIgnoreState || TheCondState.
CondMet)
4992 TheCondState.
Ignore =
true;
4994 TheCondState.
Ignore =
false;
5001bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5013bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5014 if (!TheCondStack.empty()) {
5015 if (TheCondStack.back().Ignore) {
5016 eatToEndOfStatement();
5021 std::string Message =
".err directive invoked in source file";
5026 return Error(DirectiveLoc, Message);
5031bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5032 if (!TheCondStack.empty()) {
5033 if (TheCondStack.back().Ignore) {
5034 eatToEndOfStatement();
5040 if (parseTextItem(
Text))
5041 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5043 std::string Message =
".errb directive invoked in source file";
5046 return addErrorSuffix(
" in '.errb' directive");
5051 if (
Text.empty() == ExpectBlank)
5052 return Error(DirectiveLoc, Message);
5058bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5059 bool ExpectDefined) {
5060 if (!TheCondStack.empty()) {
5061 if (TheCondStack.back().Ignore) {
5062 eatToEndOfStatement();
5067 bool IsDefined =
false;
5069 SMLoc StartLoc, EndLoc;
5071 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5074 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5077 if (BuiltinSymbolMap.contains(
Name.lower())) {
5087 std::string Message =
".errdef directive invoked in source file";
5090 return addErrorSuffix(
" in '.errdef' directive");
5095 if (IsDefined == ExpectDefined)
5096 return Error(DirectiveLoc, Message);
5102bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5103 bool CaseInsensitive) {
5104 if (!TheCondStack.empty()) {
5105 if (TheCondStack.back().Ignore) {
5106 eatToEndOfStatement();
5111 std::string String1, String2;
5113 if (parseTextItem(String1)) {
5115 return TokError(
"expected string parameter for '.erridn' directive");
5116 return TokError(
"expected string parameter for '.errdif' directive");
5122 "expected comma after first string for '.erridn' directive");
5124 "expected comma after first string for '.errdif' directive");
5128 if (parseTextItem(String2)) {
5130 return TokError(
"expected string parameter for '.erridn' directive");
5131 return TokError(
"expected string parameter for '.errdif' directive");
5134 std::string Message;
5136 Message =
".erridn directive invoked in source file";
5138 Message =
".errdif directive invoked in source file";
5141 return addErrorSuffix(
" in '.erridn' directive");
5146 if (CaseInsensitive)
5148 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5150 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5153 if ((CaseInsensitive &&
5154 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5155 (ExpectEqual == (String1 == String2)))
5156 return Error(DirectiveLoc, Message);
5162bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5163 if (!TheCondStack.empty()) {
5164 if (TheCondStack.back().Ignore) {
5165 eatToEndOfStatement();
5171 if (parseAbsoluteExpression(ExprValue))
5172 return addErrorSuffix(
" in '.erre' directive");
5174 std::string Message =
".erre directive invoked in source file";
5177 return addErrorSuffix(
" in '.erre' directive");
5182 if ((ExprValue == 0) == ExpectZero)
5183 return Error(DirectiveLoc, Message);
5189bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5194 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5196 if (!TheCondStack.empty()) {
5197 TheCondState = TheCondStack.back();
5198 TheCondStack.pop_back();
5204void MasmParser::initializeDirectiveKindMap() {
5205 DirectiveKindMap[
"="] = DK_ASSIGN;
5206 DirectiveKindMap[
"equ"] = DK_EQU;
5207 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5211 DirectiveKindMap[
"byte"] = DK_BYTE;
5212 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5213 DirectiveKindMap[
"word"] = DK_WORD;
5214 DirectiveKindMap[
"sword"] = DK_SWORD;
5215 DirectiveKindMap[
"dword"] = DK_DWORD;
5216 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5217 DirectiveKindMap[
"fword"] = DK_FWORD;
5218 DirectiveKindMap[
"qword"] = DK_QWORD;
5219 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5220 DirectiveKindMap[
"real4"] = DK_REAL4;
5221 DirectiveKindMap[
"real8"] = DK_REAL8;
5222 DirectiveKindMap[
"real10"] = DK_REAL10;
5223 DirectiveKindMap[
"align"] = DK_ALIGN;
5224 DirectiveKindMap[
"even"] = DK_EVEN;
5225 DirectiveKindMap[
"org"] = DK_ORG;
5226 DirectiveKindMap[
"extern"] = DK_EXTERN;
5227 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5228 DirectiveKindMap[
"public"] = DK_PUBLIC;
5230 DirectiveKindMap[
"comment"] = DK_COMMENT;
5231 DirectiveKindMap[
"include"] = DK_INCLUDE;
5232 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5233 DirectiveKindMap[
"rept"] = DK_REPEAT;
5234 DirectiveKindMap[
"while"] = DK_WHILE;
5235 DirectiveKindMap[
"for"] = DK_FOR;
5236 DirectiveKindMap[
"irp"] = DK_FOR;
5237 DirectiveKindMap[
"forc"] = DK_FORC;
5238 DirectiveKindMap[
"irpc"] = DK_FORC;
5239 DirectiveKindMap[
"if"] = DK_IF;
5240 DirectiveKindMap[
"ife"] = DK_IFE;
5241 DirectiveKindMap[
"ifb"] = DK_IFB;
5242 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5243 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5244 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5245 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5246 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5247 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5248 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5249 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5250 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5251 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5252 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5253 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5254 DirectiveKindMap[
"else"] = DK_ELSE;
5255 DirectiveKindMap[
"end"] = DK_END;
5256 DirectiveKindMap[
"endif"] = DK_ENDIF;
5300 DirectiveKindMap[
"macro"] = DK_MACRO;
5301 DirectiveKindMap[
"exitm"] = DK_EXITM;
5302 DirectiveKindMap[
"endm"] = DK_ENDM;
5303 DirectiveKindMap[
"purge"] = DK_PURGE;
5304 DirectiveKindMap[
".err"] = DK_ERR;
5305 DirectiveKindMap[
".errb"] = DK_ERRB;
5306 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5307 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5308 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5309 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5310 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5311 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5312 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5313 DirectiveKindMap[
".erre"] = DK_ERRE;
5314 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5315 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5316 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5317 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5318 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5319 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5320 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5321 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5322 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5323 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5324 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5325 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5326 DirectiveKindMap[
".radix"] = DK_RADIX;
5327 DirectiveKindMap[
"db"] = DK_DB;
5328 DirectiveKindMap[
"dd"] = DK_DD;
5329 DirectiveKindMap[
"df"] = DK_DF;
5330 DirectiveKindMap[
"dq"] = DK_DQ;
5331 DirectiveKindMap[
"dw"] = DK_DW;
5332 DirectiveKindMap[
"echo"] = DK_ECHO;
5333 DirectiveKindMap[
"struc"] = DK_STRUCT;
5334 DirectiveKindMap[
"struct"] = DK_STRUCT;
5335 DirectiveKindMap[
"union"] = DK_UNION;
5336 DirectiveKindMap[
"ends"] = DK_ENDS;
5339bool MasmParser::isMacroLikeDirective() {
5341 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5342 .CasesLower({
"repeat",
"rept"},
true)
5343 .CaseLower(
"while",
true)
5344 .CasesLower({
"for",
"irp"},
true)
5345 .CasesLower({
"forc",
"irpc"},
true)
5351 peekTok().getIdentifier().equals_insensitive(
"macro"))
5357MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5358 AsmToken EndToken, StartToken = getTok();
5360 unsigned NestLevel = 0;
5364 printError(DirectiveLoc,
"no matching 'endm' in definition");
5368 if (isMacroLikeDirective())
5373 getTok().getIdentifier().equals_insensitive(
"endm")) {
5374 if (NestLevel == 0) {
5375 EndToken = getTok();
5378 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5387 eatToEndOfStatement();
5392 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5396 return &MacroLikeBodies.back();
5399bool MasmParser::expandStatement(SMLoc Loc) {
5401 SMLoc EndLoc = getTok().getLoc();
5406 StringMap<std::string> BuiltinValues;
5407 for (
const auto &S : BuiltinSymbolMap) {
5408 const BuiltinSymbol &Sym = S.getValue();
5409 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5410 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5413 for (
const auto &
B : BuiltinValues) {
5414 MCAsmMacroParameter
P;
5415 MCAsmMacroArgument
A;
5416 P.Name =
B.getKey();
5424 for (
const auto &
V : Variables) {
5427 MCAsmMacroParameter
P;
5428 MCAsmMacroArgument
A;
5437 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5438 MCAsmMacro
M = MacroLikeBodies.back();
5441 SmallString<80> Buf;
5442 raw_svector_ostream OS(Buf);
5443 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5445 std::unique_ptr<MemoryBuffer>
Expansion =
5451 EndStatementAtEOFStack.push_back(
false);
5456void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5457 raw_svector_ostream &OS) {
5458 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5460void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5462 raw_svector_ostream &OS) {
5465 std::unique_ptr<MemoryBuffer> Instantiation =
5470 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5471 ExitLoc, TheCondStack.size()};
5472 ActiveMacros.push_back(
MI);
5477 EndStatementAtEOFStack.push_back(
true);
5485bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5486 const MCExpr *CountExpr;
5487 SMLoc CountLoc = getTok().getLoc();
5488 if (parseExpression(CountExpr))
5492 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5493 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5496 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5500 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5506 SmallString<256> Buf;
5507 raw_svector_ostream OS(Buf);
5509 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5512 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5521bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5522 const MCExpr *CondExpr;
5523 SMLoc CondLoc = getTok().getLoc();
5524 if (parseExpression(CondExpr))
5528 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5534 SmallString<256> Buf;
5535 raw_svector_ostream OS(Buf);
5537 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5538 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5542 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5544 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5554bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5556 MCAsmMacroArguments
A;
5557 if (check(parseIdentifier(
Parameter.Name),
5558 "expected identifier in '" + Dir +
"' directive"))
5567 ParamLoc = Lexer.getLoc();
5568 if (parseMacroArgument(
nullptr,
Parameter.Value))
5574 QualLoc = Lexer.getLoc();
5575 if (parseIdentifier(Qualifier))
5576 return Error(QualLoc,
"missing parameter qualifier for "
5581 if (
Qualifier.equals_insensitive(
"req"))
5584 return Error(QualLoc,
5585 Qualifier +
" is not a valid parameter qualifier for '" +
5586 Parameter.Name +
"' in '" + Dir +
"' directive");
5591 "expected comma in '" + Dir +
"' directive") ||
5593 "values in '" + Dir +
5594 "' directive must be enclosed in angle brackets"))
5600 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5609 "values in '" + Dir +
5610 "' directive must be enclosed in angle brackets") ||
5615 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5621 SmallString<256> Buf;
5622 raw_svector_ostream OS(Buf);
5624 for (
const MCAsmMacroArgument &Arg :
A) {
5625 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5629 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5638bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5642 if (check(parseIdentifier(
Parameter.Name),
5643 "expected identifier in '" + Directive +
"' directive") ||
5645 "expected comma in '" + Directive +
"' directive"))
5647 if (parseAngleBracketString(Argument)) {
5665 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5671 SmallString<256> Buf;
5672 raw_svector_ostream OS(Buf);
5674 StringRef
Values(Argument);
5676 MCAsmMacroArgument Arg;
5679 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5683 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5688bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5690 const MCExpr *
Value;
5691 SMLoc ExprLoc = getLexer().getLoc();
5692 if (parseExpression(
Value))
5696 return Error(ExprLoc,
"unexpected expression in _emit");
5699 return Error(ExprLoc,
"literal value out of range for directive");
5705bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5706 const MCExpr *
Value;
5707 SMLoc ExprLoc = getLexer().getLoc();
5708 if (parseExpression(
Value))
5712 return Error(ExprLoc,
"unexpected expression in align");
5715 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5721bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5722 const SMLoc Loc = getLexer().getLoc();
5724 StringRef RadixString = StringRef(RadixStringRaw).trim();
5728 "radix must be a decimal number in the range 2 to 16; was " +
5731 if (Radix < 2 || Radix > 16)
5732 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5733 std::to_string(Radix));
5734 getLexer().setMasmDefaultRadix(Radix);
5740bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5743 if (!StringRef(Message).ends_with(
"\n"))
5771bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5773 if (Var.Name.empty())
5775 return setTextVariable(Var, Name,
Value, SMLoc(),
5776 Variable::WARN_ON_REDEFINITION);
5779bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5780 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5781 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5782 return lookUpField(
Base, Member, Info);
5785bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5786 AsmFieldInfo &Info)
const {
5790 AsmFieldInfo BaseInfo;
5791 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5794 auto StructIt = Structs.
find(
Base.lower());
5795 auto TypeIt = KnownType.
find(
Base.lower());
5796 if (TypeIt != KnownType.
end()) {
5797 StructIt = Structs.
find(TypeIt->second.Name.lower());
5799 if (StructIt != Structs.
end())
5800 return lookUpField(StructIt->second, Member, Info);
5805bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5806 AsmFieldInfo &Info)
const {
5808 Info.Type.Name = Structure.Name;
5809 Info.Type.Size = Structure.Size;
5810 Info.Type.ElementSize = Structure.Size;
5811 Info.Type.Length = 1;
5815 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5816 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5818 auto StructIt = Structs.
find(FieldName.
lower());
5819 if (StructIt != Structs.
end())
5820 return lookUpField(StructIt->second, FieldMember, Info);
5822 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5823 if (FieldIt == Structure.FieldsByName.
end())
5826 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5827 if (FieldMember.empty()) {
5832 if (
Field.Contents.FT == FT_STRUCT)
5833 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5835 Info.Type.Name =
"";
5839 if (
Field.Contents.FT != FT_STRUCT)
5841 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5843 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5850bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5851 unsigned Size = StringSwitch<unsigned>(Name)
5852 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5853 .CasesLower({
"word",
"dw",
"sword"}, 2)
5854 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5855 .CasesLower({
"fword",
"df"}, 6)
5856 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5857 .CaseLower(
"real4", 4)
5858 .CaseLower(
"real8", 8)
5859 .CaseLower(
"real10", 10)
5869 auto StructIt = Structs.
find(
Name.lower());
5870 if (StructIt != Structs.
end()) {
5871 const StructInfo &Structure = StructIt->second;
5873 Info.ElementSize = Structure.Size;
5875 Info.Size = Structure.Size;
5882bool MasmParser::parseMSInlineAsm(
5883 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5884 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5885 SmallVectorImpl<std::string> &Constraints,
5886 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5887 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5888 SmallVector<void *, 4> InputDecls;
5889 SmallVector<void *, 4> OutputDecls;
5890 SmallVector<bool, 4> InputDeclsAddressOf;
5891 SmallVector<bool, 4> OutputDeclsAddressOf;
5892 SmallVector<std::string, 4> InputConstraints;
5893 SmallVector<std::string, 4> OutputConstraints;
5902 unsigned InputIdx = 0;
5903 unsigned OutputIdx = 0;
5906 if (parseCurlyBlockScope(AsmStrRewrites))
5909 ParseStatementInfo
Info(&AsmStrRewrites);
5910 bool StatementErr = parseStatement(Info, &SI);
5912 if (StatementErr ||
Info.ParseError) {
5914 printPendingErrors();
5919 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5921 if (
Info.Opcode == ~0U)
5927 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5928 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5932 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5933 unsigned NumDefs =
Desc.getNumDefs();
5942 if (SymName.
empty())
5950 if (Operand.
isImm()) {
5958 bool isOutput = (i == 1) &&
Desc.mayStore();
5964 OutputConstraints.
push_back((
"=" + Constraint).str());
5970 if (
Desc.operands()[i - 1].isBranchTarget())
5982 NumOutputs = OutputDecls.
size();
5983 NumInputs = InputDecls.
size();
5988 Clobbers.
assign(ClobberRegs.
size(), std::string());
5989 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5990 raw_string_ostream OS(Clobbers[
I]);
5995 if (NumOutputs || NumInputs) {
5996 unsigned NumExprs = NumOutputs + NumInputs;
5997 OpDecls.resize(NumExprs);
5998 Constraints.
resize(NumExprs);
5999 for (
unsigned i = 0; i < NumOutputs; ++i) {
6000 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6001 Constraints[i] = OutputConstraints[i];
6003 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6004 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6005 Constraints[
j] = InputConstraints[i];
6010 std::string AsmStringIR;
6011 raw_string_ostream OS(AsmStringIR);
6012 StringRef ASMString =
6014 const char *AsmStart = ASMString.
begin();
6015 const char *AsmEnd = ASMString.
end();
6017 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6018 const AsmRewrite &AR = *
I;
6025 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6028 if (
unsigned Len = Loc - AsmStart)
6029 OS << StringRef(AsmStart, Len);
6033 AsmStart = Loc + AR.
Len;
6037 unsigned AdditionalSkip = 0;
6059 size_t OffsetLen = OffsetName.
size();
6060 auto rewrite_it = std::find_if(
6061 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6062 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6063 (FusingAR.Kind == AOK_Input ||
6064 FusingAR.Kind == AOK_CallInput);
6066 if (rewrite_it == AsmStrRewrites.
end()) {
6067 OS <<
"offset " << OffsetName;
6069 OS <<
"${" << InputIdx++ <<
":P}";
6070 rewrite_it->Done =
true;
6072 OS <<
'$' << InputIdx++;
6073 rewrite_it->Done =
true;
6085 OS <<
'$' << InputIdx++;
6088 OS <<
"${" << InputIdx++ <<
":P}";
6091 OS <<
'$' << OutputIdx++;
6096 case 8: OS <<
"byte ptr ";
break;
6097 case 16: OS <<
"word ptr ";
break;
6098 case 32: OS <<
"dword ptr ";
break;
6099 case 64: OS <<
"qword ptr ";
break;
6100 case 80: OS <<
"xword ptr ";
break;
6101 case 128: OS <<
"xmmword ptr ";
break;
6102 case 256: OS <<
"ymmword ptr ";
break;
6112 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6117 unsigned Val = AR.
Val;
6119 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6120 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6132 AsmStart = Loc + AR.
Len + AdditionalSkip;
6136 if (AsmStart != AsmEnd)
6137 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6139 AsmString = OS.
str();
6143void MasmParser::initializeBuiltinSymbolMaps() {
6145 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6146 BuiltinSymbolMap[
"@line"] = BI_LINE;
6147 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6150 BuiltinSymbolMap[
"@date"] = BI_DATE;
6151 BuiltinSymbolMap[
"@time"] = BI_TIME;
6152 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6153 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6154 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6157 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6160 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6178const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6188 if (ActiveMacros.empty())
6192 ActiveMacros.front()->ExitBuffer);
6195 case BI_UNWINDVERSION:
6202std::optional<std::string>
6203MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6209 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6210 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6211 return std::string(TmpBuffer, Len);
6215 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6216 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6217 return std::string(TmpBuffer, Len);
6222 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6230 return getStreamer().getCurrentSectionOnly()->getName().str();
6235bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction
Function,
6239 "' requires arguments in parentheses")) {
6250 MCAsmMacro
M(Name,
"",
P, {},
true);
6252 MCAsmMacroArguments
A;
6261 for (
const MCAsmMacroArgument &Arg :
A) {
6262 for (
const AsmToken &Tok : Arg) {
6280 struct tm TM,
unsigned CB) {
6281 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
bool shouldUseLogicalShr() const
StringRef getInternalSymbolPrefix() const
unsigned getAsmMacroMaxNestingDepth() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo & getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
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.
LLVM_ABI void printIncludeStackForDiagnostic(SMLoc Loc, raw_ostream &OS) const
Prints the include stack of a buffer unless it is a macro instantiation buffer.
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 unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
LLVM_ABI TargetOptions getTargetOptions(const cl::LibraryOptionsContext &LibraryOptions, const llvm::Triple &TheTriple)
Common utility function tightly tied to the options listed here.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
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.
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.
RelativeUniformCounterPtr Values
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI SourceMgr SrcMgr
auto dyn_cast_or_null(const Y &Val)
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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.
@ End
Run the machine verifier once, at the end of the pipeline.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.