75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
79struct MacroInstantiation {
81 SMLoc InstantiationLoc;
90 size_t CondStackDepth;
93struct ParseStatementInfo {
98 unsigned Opcode = ~0
U;
101 bool ParseError =
false;
104 std::optional<std::string> ExitValue;
106 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
108 ParseStatementInfo() =
delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
122 bool IsUnion =
false;
123 bool Initializable =
true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
128 std::vector<FieldInfo> Fields;
129 StringMap<size_t> FieldsByName;
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
134 StructInfo() =
default;
135 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
143struct StructInitializer;
147 IntFieldInfo() =
default;
151struct RealFieldInfo {
154 RealFieldInfo() =
default;
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
162 StructFieldInfo() =
default;
163 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
166class FieldInitializer {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
176 FieldInitializer(FieldType FT);
180 FieldInitializer(std::vector<StructInitializer> &&Initializers,
181 struct StructInfo Structure);
183 FieldInitializer(
const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
186 FieldInitializer &operator=(
const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
190struct StructInitializer {
191 std::vector<FieldInitializer> FieldInitializers;
202 unsigned LengthOf = 0;
207 FieldInitializer Contents;
209 FieldInfo(FieldType FT) : Contents(FT) {}
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
214 Initializers = std::move(V);
218StructInfo::StructInfo(StringRef
StructName,
bool Union,
219 unsigned AlignmentValue)
222FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.
empty())
225 FieldsByName[FieldName.
lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &
Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
237FieldInitializer::~FieldInitializer() {
240 IntInfo.~IntFieldInfo();
243 RealInfo.~RealFieldInfo();
246 StructInfo.~StructFieldInfo();
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
254 new (&IntInfo) IntFieldInfo();
257 new (&RealInfo) RealFieldInfo();
260 new (&StructInfo) StructFieldInfo();
267 new (&IntInfo) IntFieldInfo(std::move(Values));
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
281FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312FieldInitializer::operator=(
const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
316 IntInfo.~IntFieldInfo();
319 RealInfo.~RealFieldInfo();
322 StructInfo.~StructFieldInfo();
329 IntInfo = Initializer.IntInfo;
332 RealInfo = Initializer.RealInfo;
335 StructInfo = Initializer.StructInfo;
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
345 IntInfo.~IntFieldInfo();
348 RealInfo.~RealFieldInfo();
351 StructInfo.~StructFieldInfo();
358 IntInfo = Initializer.IntInfo;
361 RealInfo = Initializer.RealInfo;
364 StructInfo = Initializer.StructInfo;
373class MasmParser :
public MCAsmParser {
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
386 BitVector EndStatementAtEOFStack;
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
401 RedefinableKind Redefinable = REDEFINABLE;
403 std::string TextValue;
405 StringMap<Variable> Variables;
411 StringMap<StructInfo> Structs;
414 StringMap<AsmTypeInfo> KnownType;
417 std::vector<MacroInstantiation*> ActiveMacros;
420 std::deque<MCAsmMacro> MacroLikeBodies;
423 unsigned NumOfMacroInstantiations;
426 struct CppHashInfoTy {
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
433 CppHashInfoTy CppHashInfo;
436 StringRef FirstCppHashFilename;
443 unsigned AssemblerDialect = 1U;
446 bool ParsingMSInlineAsm =
false;
449 unsigned AngleBracketDepth = 0
U;
452 uint16_t LocalCounter = 0;
455 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
457 MasmParser(
const MasmParser &) =
delete;
458 MasmParser &operator=(
const MasmParser &) =
delete;
459 ~MasmParser()
override;
461 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler)
override {
465 ExtensionDirectiveMap[Directive] = Handler;
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
469 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
476 unsigned getAssemblerDialect()
override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
480 return AssemblerDialect;
482 void setAssemblerDialect(
unsigned i)
override {
483 AssemblerDialect = i;
486 void Note(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
487 bool Warning(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
488 bool printError(SMLoc L,
const Twine &Msg, SMRange
Range = {})
override;
490 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
491 const AsmToken &Lex(ExpandKind ExpandNextToken);
492 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
494 void setParsingMSInlineAsm(
bool V)
override {
495 ParsingMSInlineAsm =
V;
498 Lexer.setLexMasmIntegers(V);
500 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
502 bool isParsingMasm()
const override {
return true; }
504 bool defineMacro(StringRef Name, StringRef
Value)
override;
506 bool lookUpField(StringRef Name, AsmFieldInfo &
Info)
const override;
507 bool lookUpField(StringRef
Base, StringRef Member,
508 AsmFieldInfo &
Info)
const override;
510 bool lookUpType(StringRef Name, AsmTypeInfo &
Info)
const override;
512 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
514 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
515 SmallVectorImpl<std::string> &Constraints,
516 SmallVectorImpl<std::string> &Clobbers,
517 const MCInstrInfo *MII, MCInstPrinter *IP,
518 MCAsmParserSemaCallback &SI)
override;
520 bool parseExpression(
const MCExpr *&Res);
521 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
522 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
523 AsmTypeInfo *TypeInfo)
override;
524 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
525 bool parseAbsoluteExpression(int64_t &Res)
override;
529 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
533 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
534 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
535 bool parseIdentifier(StringRef &Res)
override {
536 return parseIdentifier(Res, StandardPosition);
538 void eatToEndOfStatement()
override;
540 bool checkForValidSection()
override;
546 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
548 bool parseStatement(ParseStatementInfo &
Info,
549 MCAsmParserSemaCallback *SI);
550 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
551 bool parseCppHashLineFilenameComment(SMLoc L);
553 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
556 const std::vector<std::string> &Locals, SMLoc L);
559 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
565 bool handleMacroEntry(
566 const MCAsmMacro *M, SMLoc NameLoc,
573 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
576 void handleMacroExit();
580 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
585 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
588 void printMacroInstantiations();
590 bool expandStatement(SMLoc Loc);
593 SMRange
Range = {})
const {
599 bool lookUpField(
const StructInfo &Structure, StringRef Member,
600 AsmFieldInfo &
Info)
const;
603 bool enterIncludeFile(
const std::string &Filename);
611 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
612 bool EndStatementAtEOF =
true);
624 StringRef parseStringToEndOfStatement()
override;
626 bool parseTextItem(std::string &
Data);
631 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
632 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
633 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
638 DK_HANDLER_DIRECTIVE,
728 StringMap<DirectiveKind> DirectiveKindMap;
730 bool isMacroLikeDirective();
756 StringMap<BuiltinSymbol> BuiltinSymbolMap;
758 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
760 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
764 enum BuiltinFunction {
771 StringMap<BuiltinFunction> BuiltinFunctionMap;
773 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
777 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
780 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
781 bool parseScalarInitializer(
unsigned Size,
782 SmallVectorImpl<const MCExpr *> &Values,
783 unsigned StringPadLength = 0);
784 bool parseScalarInstList(
785 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
787 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
788 bool addIntegralField(StringRef Name,
unsigned Size);
789 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
790 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
791 StringRef Name, SMLoc NameLoc);
794 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
795 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
796 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
798 bool parseRealInstList(
799 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
801 bool parseDirectiveNamedRealValue(StringRef TypeName,
802 const fltSemantics &Semantics,
803 unsigned Size, StringRef Name,
806 bool parseOptionalAngleBracketOpen();
807 bool parseAngleBracketClose(
const Twine &Msg =
"expected '>'");
809 bool parseFieldInitializer(
const FieldInfo &
Field,
810 FieldInitializer &Initializer);
811 bool parseFieldInitializer(
const FieldInfo &
Field,
812 const IntFieldInfo &Contents,
813 FieldInitializer &Initializer);
814 bool parseFieldInitializer(
const FieldInfo &
Field,
815 const RealFieldInfo &Contents,
816 FieldInitializer &Initializer);
817 bool parseFieldInitializer(
const FieldInfo &
Field,
818 const StructFieldInfo &Contents,
819 FieldInitializer &Initializer);
821 bool parseStructInitializer(
const StructInfo &Structure,
822 StructInitializer &Initializer);
823 bool parseStructInstList(
824 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
827 bool emitFieldValue(
const FieldInfo &
Field);
828 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
829 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
830 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
832 bool emitFieldInitializer(
const FieldInfo &
Field,
833 const FieldInitializer &Initializer);
834 bool emitFieldInitializer(
const FieldInfo &
Field,
835 const IntFieldInfo &Contents,
836 const IntFieldInfo &Initializer);
837 bool emitFieldInitializer(
const FieldInfo &
Field,
838 const RealFieldInfo &Contents,
839 const RealFieldInfo &Initializer);
840 bool emitFieldInitializer(
const FieldInfo &
Field,
841 const StructFieldInfo &Contents,
842 const StructFieldInfo &Initializer);
844 bool emitStructInitializer(
const StructInfo &Structure,
845 const StructInitializer &Initializer);
848 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
849 bool addStructField(StringRef Name,
const StructInfo &Structure);
850 bool parseDirectiveStructValue(
const StructInfo &Structure,
851 StringRef Directive, SMLoc DirLoc);
852 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc,
857 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
858 DirectiveKind DirKind, SMLoc NameLoc);
860 bool parseDirectiveOrg();
862 bool emitAlignTo(int64_t Alignment);
863 bool parseDirectiveAlign();
864 bool parseDirectiveEven();
867 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
868 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
870 bool parseDirectiveEndMacro(StringRef Directive);
871 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
873 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
874 StringRef Name, SMLoc NameLoc);
875 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
876 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedEnds();
879 bool parseDirectiveExtern();
885 bool parseDirectiveComm(
bool IsLocal);
887 bool parseDirectiveComment(SMLoc DirectiveLoc);
889 bool parseDirectiveInclude();
892 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
894 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
897 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
898 bool CaseInsensitive);
900 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
902 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
904 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
906 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
909 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
910 bool CaseInsensitive);
911 bool parseDirectiveElse(SMLoc DirectiveLoc);
912 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
913 bool parseEscapedString(std::string &
Data)
override;
914 bool parseAngleBracketString(std::string &
Data)
override;
917 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
918 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
919 raw_svector_ostream &OS);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 SMLoc ExitLoc, raw_svector_ostream &OS);
922 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
923 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
924 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveWhile(SMLoc DirectiveLoc);
928 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &
Info,
932 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &
Info);
935 bool parseDirectiveEnd(SMLoc DirectiveLoc);
938 bool parseDirectiveError(SMLoc DirectiveLoc);
940 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
942 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
945 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
946 bool CaseInsensitive);
948 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
951 bool parseDirectiveRadix(SMLoc DirectiveLoc);
954 bool parseDirectiveEcho(SMLoc DirectiveLoc);
956 void initializeDirectiveKindMap();
957 void initializeBuiltinSymbolMaps();
970MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
971 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
972 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
976 SavedDiagHandler =
SrcMgr.getDiagHandler();
977 SavedDiagContext =
SrcMgr.getDiagContext();
980 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
981 EndStatementAtEOFStack.push_back(
true);
984 switch (Ctx.getObjectFileType()) {
985 case MCContext::IsCOFF:
986 PlatformParser.reset(createCOFFMasmParser());
989 report_fatal_error(
"llvm-ml currently supports only COFF output.");
993 initializeDirectiveKindMap();
994 PlatformParser->Initialize(*
this);
995 initializeBuiltinSymbolMaps();
997 NumOfMacroInstantiations = 0;
1000MasmParser::~MasmParser() {
1001 assert((HadError || ActiveMacros.empty()) &&
1002 "Unexpected active macro instantiation!");
1009void MasmParser::printMacroInstantiations() {
1011 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1012 it = ActiveMacros.rbegin(),
1013 ie = ActiveMacros.rend();
1016 "while in macro instantiation");
1019void MasmParser::Note(SMLoc L,
const Twine &Msg, SMRange
Range) {
1020 printPendingErrors();
1022 printMacroInstantiations();
1025bool MasmParser::Warning(SMLoc L,
const Twine &Msg, SMRange
Range) {
1026 if (getTargetParser().getTargetOptions().MCNoWarn)
1028 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1031 printMacroInstantiations();
1035bool MasmParser::printError(SMLoc L,
const Twine &Msg, SMRange
Range) {
1038 printMacroInstantiations();
1042bool MasmParser::enterIncludeFile(
const std::string &Filename) {
1043 std::string IncludedFile;
1051 EndStatementAtEOFStack.push_back(
true);
1055void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1056 bool EndStatementAtEOF) {
1062bool MasmParser::expandMacros() {
1063 const AsmToken &Tok = getTok();
1066 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1069 const SMLoc MacroLoc = Tok.
getLoc();
1072 if (handleMacroInvocation(M, MacroLoc)) {
1079 std::optional<std::string> ExpandedValue;
1081 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1082 BuiltinIt != BuiltinSymbolMap.end()) {
1084 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1085 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1086 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1088 if (parseIdentifier(Name)) {
1092 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1095 ExpandedValue = Res;
1096 }
else if (
auto VarIt = Variables.
find(IDLower);
1097 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1098 ExpandedValue = VarIt->getValue().TextValue;
1103 std::unique_ptr<MemoryBuffer> Instantiation =
1111 EndStatementAtEOFStack.push_back(
false);
1116const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1118 Error(Lexer.getErrLoc(), Lexer.getErr());
1119 bool StartOfStatement =
false;
1124 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1127 StartOfStatement =
true;
1130 const AsmToken *tok = &Lexer.Lex();
1133 if (StartOfStatement) {
1136 size_t ReadCount = Lexer.peekTokens(Buf);
1168 if (ParentIncludeLoc != SMLoc()) {
1169 EndStatementAtEOFStack.pop_back();
1170 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1173 EndStatementAtEOFStack.pop_back();
1174 assert(EndStatementAtEOFStack.empty());
1180const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1184 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1186 if (ReadCount == 0) {
1190 if (ParentIncludeLoc != SMLoc()) {
1191 EndStatementAtEOFStack.pop_back();
1192 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1193 return peekTok(ShouldSkipSpace);
1195 EndStatementAtEOFStack.pop_back();
1196 assert(EndStatementAtEOFStack.empty());
1203bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1205 if (!NoInitialTextSection)
1212 AsmCond StartingCondState = TheCondState;
1222 ParseStatementInfo
Info(&AsmStrRewrites);
1223 bool HasError = parseStatement(
Info,
nullptr);
1228 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1232 printPendingErrors();
1235 if (HasError && !getLexer().justConsumedEOL())
1236 eatToEndOfStatement();
1239 printPendingErrors();
1242 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1246 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1255 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1256 if (std::get<2>(LocSym)->isUndefined()) {
1259 CppHashInfo = std::get<1>(LocSym);
1260 printError(std::get<0>(LocSym),
"directional label undefined");
1267 if (!HadError && !NoFinalize)
1268 Out.
finish(Lexer.getLoc());
1273bool MasmParser::checkForValidSection() {
1274 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1275 getStreamer().getCurrentSectionOnly())) {
1277 return Error(getTok().getLoc(),
1278 "expected section directive before assembly directive");
1284void MasmParser::eatToEndOfStatement() {
1288 if (ParentIncludeLoc == SMLoc()) {
1292 EndStatementAtEOFStack.pop_back();
1293 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1304SmallVector<StringRef, 1>
1306 SmallVector<StringRef, 1> Refs;
1307 const char *
Start = getTok().getLoc().getPointer();
1308 while (Lexer.isNot(EndTok)) {
1311 if (ParentIncludeLoc == SMLoc()) {
1316 EndStatementAtEOFStack.pop_back();
1317 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1319 Start = getTok().getLoc().getPointer();
1329 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1331 for (StringRef S : Refs) {
1332 Str.append(S.str());
1337StringRef MasmParser::parseStringToEndOfStatement() {
1338 const char *
Start = getTok().getLoc().getPointer();
1343 const char *End = getTok().getLoc().getPointer();
1344 return StringRef(Start, End - Start);
1352bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1353 if (parseExpression(Res))
1355 EndLoc = Lexer.getTok().getEndLoc();
1356 return parseRParen();
1364bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1365 if (parseExpression(Res))
1367 EndLoc = getTok().getEndLoc();
1368 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1381bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1382 AsmTypeInfo *TypeInfo) {
1383 SMLoc FirstTokenLoc = getLexer().getLoc();
1385 switch (FirstTokenKind) {
1387 return TokError(
"unknown token in expression");
1393 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1401 if (parseIdentifier(Identifier)) {
1404 if (Lexer.getMAI().getDollarIsPC()) {
1411 EndLoc = FirstTokenLoc;
1414 return Error(FirstTokenLoc,
"invalid token in expression");
1419 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1427 bool Before =
Identifier.equals_insensitive(
"@b");
1430 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1440 return Error(getLexer().getLoc(),
"expected a symbol reference");
1445 if (
Split.second.empty()) {
1448 if (lookUpField(SymbolName,
Split.second,
Info)) {
1449 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1450 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1462 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1463 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1465 : BuiltinIt->getValue();
1466 if (Symbol != BI_NO_SYMBOL) {
1467 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1477 if (VarIt != Variables.
end())
1488 DoInline = TV->inlineAssignedExpr();
1496 const MCExpr *SymRef =
1506 if (
Info.Type.Name.empty()) {
1508 if (TypeIt != KnownType.
end()) {
1509 Info.Type = TypeIt->second;
1513 *TypeInfo =
Info.Type;
1518 return TokError(
"literal value out of range for directive");
1520 int64_t
IntVal = getTok().getIntVal();
1522 EndLoc = Lexer.getTok().getEndLoc();
1528 SMLoc ValueLoc = getTok().getLoc();
1530 if (parseEscapedString(
Value))
1532 if (
Value.size() > 8)
1533 return Error(ValueLoc,
"literal value out of range");
1534 uint64_t IntValue = 0;
1535 for (
const unsigned char CharVal :
Value)
1536 IntValue = (IntValue << 8) | CharVal;
1541 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1542 uint64_t
IntVal = RealVal.bitcastToAPInt().getZExtValue();
1544 EndLoc = Lexer.getTok().getEndLoc();
1554 EndLoc = Lexer.getTok().getEndLoc();
1560 return parseParenExpr(Res, EndLoc);
1562 if (!PlatformParser->HasBracketExpressions())
1563 return TokError(
"brackets expression not supported on this target");
1565 return parseBracketExpr(Res, EndLoc);
1568 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1574 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1580 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1587bool MasmParser::parseExpression(
const MCExpr *&Res) {
1589 return parseExpression(Res, EndLoc);
1600 "Argument to the function cannot be a NULL value");
1602 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1603 (*CharPtr !=
'\0')) {
1604 if (*CharPtr ==
'!')
1608 if (*CharPtr ==
'>') {
1618 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1619 if (BracketContents[Pos] ==
'!')
1621 Res += BracketContents[Pos];
1636bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1639 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1640 parseBinOpRHS(1, Res, EndLoc))
1646 if (Res->evaluateAsAbsolute(
Value))
1652bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1654 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1657bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1660 SMLoc StartLoc = Lexer.getLoc();
1661 if (parseExpression(Expr))
1664 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1665 return Error(StartLoc,
"expected absolute expression");
1672 bool ShouldUseLogicalShr,
1673 bool EndExpressionAtGreater) {
1701 if (EndExpressionAtGreater)
1742 if (EndExpressionAtGreater)
1753 AngleBracketDepth > 0);
1758bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1760 SMLoc StartLoc = Lexer.getLoc();
1764 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1780 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1784 if (TokPrec < Precedence)
1791 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1797 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1798 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1811bool MasmParser::parseStatement(ParseStatementInfo &
Info,
1812 MCAsmParserSemaCallback *SI) {
1813 assert(!hasPendingError() &&
"parseStatement started with pending error");
1819 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1820 getTok().getString().
front() ==
'\n')
1829 SMLoc ExpansionLoc = getTok().getLoc();
1836 AsmToken
ID = getTok();
1837 SMLoc IDLoc =
ID.getLoc();
1840 return parseCppHashLineFilenameComment(IDLoc);
1847 IDVal = getTok().getString();
1850 return Error(IDLoc,
"unexpected token at start of statement");
1851 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1852 if (!TheCondState.
Ignore) {
1854 return Error(IDLoc,
"unexpected token at start of statement");
1863 DirectiveKindMap.find(IDVal.
lower());
1864 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1866 : DirKindIt->getValue();
1872 return parseDirectiveIf(IDLoc, DirKind);
1874 return parseDirectiveIfb(IDLoc,
true);
1876 return parseDirectiveIfb(IDLoc,
false);
1878 return parseDirectiveIfdef(IDLoc,
true);
1880 return parseDirectiveIfdef(IDLoc,
false);
1882 return parseDirectiveIfidn(IDLoc,
false,
1885 return parseDirectiveIfidn(IDLoc,
false,
1888 return parseDirectiveIfidn(IDLoc,
true,
1891 return parseDirectiveIfidn(IDLoc,
true,
1895 return parseDirectiveElseIf(IDLoc, DirKind);
1897 return parseDirectiveElseIfb(IDLoc,
true);
1899 return parseDirectiveElseIfb(IDLoc,
false);
1901 return parseDirectiveElseIfdef(IDLoc,
true);
1903 return parseDirectiveElseIfdef(IDLoc,
false);
1905 return parseDirectiveElseIfidn(IDLoc,
false,
1908 return parseDirectiveElseIfidn(IDLoc,
false,
1911 return parseDirectiveElseIfidn(IDLoc,
true,
1914 return parseDirectiveElseIfidn(IDLoc,
true,
1917 return parseDirectiveElse(IDLoc);
1919 return parseDirectiveEndIf(IDLoc);
1924 if (TheCondState.
Ignore) {
1925 eatToEndOfStatement();
1935 if (checkForValidSection())
1943 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1951 if (ParsingMSInlineAsm && SI) {
1952 StringRef RewrittenLabel =
1953 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1955 "We should have an internal name here.");
1958 IDVal = RewrittenLabel;
1961 if (IDVal ==
"@@") {
1984 if (!getTargetParser().isParsingMSInlineAsm())
1994 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
1999 if (DirKind != DK_NO_DIRECTIVE) {
2015 return parseDirectiveNestedEnds();
2020 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2023 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2029 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(
ID);
2031 "Should only return Failure iff there was an error");
2043 return parseDirectiveAscii(IDVal,
false);
2046 return parseDirectiveAscii(IDVal,
true);
2050 return parseDirectiveValue(IDVal, 1);
2054 return parseDirectiveValue(IDVal, 2);
2058 return parseDirectiveValue(IDVal, 4);
2061 return parseDirectiveValue(IDVal, 6);
2065 return parseDirectiveValue(IDVal, 8);
2067 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2069 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2071 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2074 return parseDirectiveNestedStruct(IDVal, DirKind);
2076 return parseDirectiveNestedEnds();
2078 return parseDirectiveAlign();
2080 return parseDirectiveEven();
2082 return parseDirectiveOrg();
2084 return parseDirectiveExtern();
2086 return parseDirectiveSymbolAttribute(
MCSA_Global);
2088 return parseDirectiveComm(
false);
2090 return parseDirectiveComment(IDLoc);
2092 return parseDirectiveInclude();
2094 return parseDirectiveRepeat(IDLoc, IDVal);
2096 return parseDirectiveWhile(IDLoc);
2098 return parseDirectiveFor(IDLoc, IDVal);
2100 return parseDirectiveForc(IDLoc, IDVal);
2102 Info.ExitValue =
"";
2103 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2105 Info.ExitValue =
"";
2106 return parseDirectiveEndMacro(IDVal);
2108 return parseDirectivePurgeMacro(IDLoc);
2110 return parseDirectiveEnd(IDLoc);
2112 return parseDirectiveError(IDLoc);
2114 return parseDirectiveErrorIfb(IDLoc,
true);
2116 return parseDirectiveErrorIfb(IDLoc,
false);
2118 return parseDirectiveErrorIfdef(IDLoc,
true);
2120 return parseDirectiveErrorIfdef(IDLoc,
false);
2122 return parseDirectiveErrorIfidn(IDLoc,
false,
2125 return parseDirectiveErrorIfidn(IDLoc,
false,
2128 return parseDirectiveErrorIfidn(IDLoc,
true,
2131 return parseDirectiveErrorIfidn(IDLoc,
true,
2134 return parseDirectiveErrorIfe(IDLoc,
true);
2136 return parseDirectiveErrorIfe(IDLoc,
false);
2138 return parseDirectiveRadix(IDLoc);
2140 return parseDirectiveEcho(IDLoc);
2143 return Error(IDLoc,
"unknown directive");
2147 auto IDIt = Structs.
find(IDVal.
lower());
2148 if (IDIt != Structs.
end())
2149 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2153 const AsmToken nextTok = getTok();
2154 const StringRef nextVal = nextTok.
getString();
2155 const SMLoc nextLoc = nextTok.
getLoc();
2157 const AsmToken afterNextTok = peekTok();
2168 getTargetParser().flushPendingInstructions(getStreamer());
2174 return parseDirectiveEnds(IDVal, IDLoc);
2179 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2181 if (Handler.first) {
2184 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2189 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2190 DirKind = (DirKindIt == DirectiveKindMap.end())
2192 : DirKindIt->getValue();
2200 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2211 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2222 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2233 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2243 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2254 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2257 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2261 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2265 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2270 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2273 return parseDirectiveEnds(IDVal, IDLoc);
2276 return parseDirectiveMacro(IDVal, IDLoc);
2280 auto NextIt = Structs.
find(nextVal.
lower());
2281 if (NextIt != Structs.
end()) {
2283 return parseDirectiveNamedStructValue(NextIt->getValue(),
2284 nextVal, nextLoc, IDVal);
2288 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2289 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2290 return parseDirectiveMSEmit(IDLoc,
Info, IDVal.
size());
2293 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2294 return parseDirectiveMSAlign(IDLoc,
Info);
2296 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2298 if (checkForValidSection())
2302 std::string OpcodeStr = IDVal.
lower();
2303 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2304 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr,
ID,
2305 Info.ParsedOperands);
2306 Info.ParseError = ParseHadError;
2309 if (getShowParsedOperands()) {
2310 SmallString<256> Str;
2311 raw_svector_ostream OS(Str);
2312 OS <<
"parsed instruction: [";
2313 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2316 Info.ParsedOperands[i]->print(OS, MAI);
2324 if (hasPendingError() || ParseHadError)
2328 if (!ParseHadError) {
2330 if (getTargetParser().matchAndEmitInstruction(
2331 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2332 getTargetParser().isParsingMSInlineAsm()))
2339bool MasmParser::parseCurlyBlockScope(
2340 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2345 SMLoc StartLoc = Lexer.getLoc();
2358bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2363 "Lexing Cpp line comment: Expected Integer");
2364 int64_t LineNumber = getTok().getIntVal();
2367 "Lexing Cpp line comment: Expected String");
2368 StringRef
Filename = getTok().getString();
2376 CppHashInfo.Loc =
L;
2378 CppHashInfo.LineNumber = LineNumber;
2379 CppHashInfo.Buf = CurBuffer;
2380 if (FirstCppHashFilename.
empty())
2387void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2388 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2389 raw_ostream &OS =
errs();
2392 SMLoc DiagLoc = Diag.
getLoc();
2394 unsigned CppHashBuf =
2395 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2400 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2409 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2410 DiagBuf != CppHashBuf) {
2411 if (Parser->SavedDiagHandler)
2412 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2414 Diag.
print(
nullptr, OS);
2421 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2424 int CppHashLocLineNo =
2425 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2427 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2433 if (Parser->SavedDiagHandler)
2434 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2436 NewDiag.print(
nullptr, OS);
2442 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2445bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2448 const std::vector<std::string> &Locals, SMLoc L) {
2450 if (NParameters !=
A.size())
2451 return Error(L,
"Wrong number of arguments");
2452 StringMap<std::string> LocalSymbols;
2455 for (StringRef
Local : Locals) {
2456 raw_string_ostream LocalName(Name);
2463 std::optional<char> CurrentQuote;
2464 while (!Body.
empty()) {
2466 std::size_t End = Body.
size(), Pos = 0;
2467 std::size_t IdentifierPos = End;
2468 for (; Pos != End; ++Pos) {
2471 if (Body[Pos] ==
'&')
2476 if (IdentifierPos == End)
2477 IdentifierPos = Pos;
2479 IdentifierPos = End;
2483 if (!CurrentQuote) {
2484 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2485 CurrentQuote = Body[Pos];
2486 }
else if (Body[Pos] == CurrentQuote) {
2487 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2492 CurrentQuote.reset();
2496 if (IdentifierPos != End) {
2499 Pos = IdentifierPos;
2500 IdentifierPos = End;
2504 OS << Body.
slice(0, Pos);
2511 bool InitialAmpersand = (Body[
I] ==
'&');
2512 if (InitialAmpersand) {
2519 const char *Begin = Body.
data() + Pos;
2521 const std::string ArgumentLower =
Argument.lower();
2525 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2528 if (Index == NParameters) {
2529 if (InitialAmpersand)
2531 auto it = LocalSymbols.
find(ArgumentLower);
2532 if (it != LocalSymbols.
end())
2538 for (
const AsmToken &Token :
A[Index]) {
2548 OS << Token.getIntVal();
2550 OS << Token.getString();
2554 if (Pos < End && Body[Pos] ==
'&') {
2565bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2566 MCAsmMacroArgument &MA,
2569 if (Lexer.isNot(EndTok)) {
2570 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2571 for (StringRef S : Str) {
2578 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2580 const char *StrChar = StrLoc.
getPointer() + 1;
2581 const char *EndChar = EndLoc.
getPointer() - 1;
2582 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2589 unsigned ParenLevel = 0;
2593 return TokError(
"unexpected token");
2610 MA.push_back(getTok());
2614 if (ParenLevel != 0)
2615 return TokError(
"unbalanced parentheses in argument");
2617 if (MA.empty() && MP) {
2619 return TokError(
"missing value for required parameter '" + MP->
Name +
2629bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2630 MCAsmMacroArguments &
A,
2632 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2633 bool NamedParametersFound =
false;
2634 SmallVector<SMLoc, 4> FALocs;
2636 A.resize(NParameters);
2637 FALocs.
resize(NParameters);
2642 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2644 SMLoc IDLoc = Lexer.getLoc();
2645 MCAsmMacroParameter FA;
2648 if (parseIdentifier(FA.
Name))
2649 return Error(IDLoc,
"invalid argument identifier for formal argument");
2652 return TokError(
"expected '=' after formal parameter identifier");
2656 NamedParametersFound =
true;
2659 if (NamedParametersFound && FA.
Name.
empty())
2660 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2664 assert(M &&
"expected macro to be defined");
2666 for (FAI = 0; FAI < NParameters; ++FAI)
2667 if (
M->Parameters[FAI].Name == FA.
Name)
2670 if (FAI >= NParameters) {
2671 return Error(IDLoc,
"parameter named '" + FA.
Name +
2672 "' does not exist for macro '" +
M->Name +
"'");
2676 const MCAsmMacroParameter *MP =
nullptr;
2677 if (M && PI < NParameters)
2678 MP = &
M->Parameters[PI];
2680 SMLoc StrLoc = Lexer.getLoc();
2683 const MCExpr *AbsoluteExp;
2687 if (parseExpression(AbsoluteExp, EndLoc))
2689 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2690 getStreamer().getAssemblerPtr()))
2691 return Error(StrLoc,
"expected absolute expression");
2695 StringRef(StrChar, EndChar - StrChar),
Value);
2696 FA.
Value.push_back(newToken);
2697 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2699 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2704 if (!FA.
Value.empty()) {
2709 if (FALocs.
size() <= PI)
2712 FALocs[PI] = Lexer.getLoc();
2718 if (Lexer.is(EndTok)) {
2720 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2722 if (
M->Parameters[FAI].Required) {
2723 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2724 "missing value for required parameter "
2726 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2730 if (!
M->Parameters[FAI].Value.empty())
2731 A[FAI] =
M->Parameters[FAI].Value;
2741 return TokError(
"too many positional arguments");
2744bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2749 if (ActiveMacros.size() == MaxNestingDepth) {
2750 std::ostringstream MaxNestingDepthError;
2751 MaxNestingDepthError <<
"macros cannot be nested more than "
2752 << MaxNestingDepth <<
" levels deep."
2753 <<
" Use -asm-macro-max-nesting-depth to increase "
2755 return TokError(MaxNestingDepthError.str());
2758 MCAsmMacroArguments
A;
2759 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2764 SmallString<256> Buf;
2765 StringRef Body =
M->Body;
2766 raw_svector_ostream OS(Buf);
2768 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2775 std::unique_ptr<MemoryBuffer> Instantiation =
2780 MacroInstantiation *
MI =
new MacroInstantiation{
2781 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2782 ActiveMacros.push_back(
MI);
2784 ++NumOfMacroInstantiations;
2789 EndStatementAtEOFStack.push_back(
true);
2795void MasmParser::handleMacroExit() {
2797 EndStatementAtEOFStack.pop_back();
2798 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2799 EndStatementAtEOFStack.back());
2803 delete ActiveMacros.back();
2804 ActiveMacros.pop_back();
2807bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2809 return Error(NameLoc,
"cannot invoke macro procedure as function");
2812 "' requires arguments in parentheses") ||
2817 std::string ExitValue;
2820 ParseStatementInfo
Info(&AsmStrRewrites);
2821 bool HasError = parseStatement(
Info,
nullptr);
2823 if (!HasError &&
Info.ExitValue) {
2824 ExitValue = std::move(*
Info.ExitValue);
2831 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2835 printPendingErrors();
2838 if (HasError && !getLexer().justConsumedEOL())
2839 eatToEndOfStatement();
2844 std::unique_ptr<MemoryBuffer> MacroValue =
2852 EndStatementAtEOFStack.push_back(
false);
2861bool MasmParser::parseIdentifier(StringRef &Res,
2862 IdentifierPositionKind Position) {
2869 SMLoc PrefixLoc = getLexer().getLoc();
2873 AsmToken nextTok = peekTok(
false);
2886 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2894 Res = getTok().getIdentifier();
2898 ExpandKind ExpandNextToken = ExpandMacros;
2899 if (Position == StartOfStatement &&
2900 StringSwitch<bool>(Res)
2901 .CaseLower(
"echo",
true)
2902 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2904 ExpandNextToken = DoNotExpandMacros;
2906 Lex(ExpandNextToken);
2916bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2917 DirectiveKind DirKind, SMLoc NameLoc) {
2918 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2919 if (BuiltinIt != BuiltinSymbolMap.end())
2920 return Error(NameLoc,
"cannot redefine a built-in symbol");
2923 if (Var.Name.empty()) {
2927 SMLoc StartLoc = Lexer.getLoc();
2928 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2931 std::string TextItem;
2932 if (!parseTextItem(TextItem)) {
2936 auto parseItem = [&]() ->
bool {
2937 if (parseTextItem(TextItem))
2938 return TokError(
"expected text item");
2943 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2945 if (!Var.IsText || Var.TextValue !=
Value) {
2946 switch (Var.Redefinable) {
2947 case Variable::NOT_REDEFINABLE:
2948 return Error(getTok().getLoc(),
"invalid variable redefinition");
2949 case Variable::WARN_ON_REDEFINITION:
2950 if (
Warning(NameLoc,
"redefining '" + Name +
2951 "', already defined on the command line")) {
2960 Var.TextValue =
Value;
2961 Var.Redefinable = Variable::REDEFINABLE;
2966 if (DirKind == DK_TEXTEQU)
2967 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2972 if (parseExpression(Expr, EndLoc))
2973 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2974 StringRef ExprAsString = StringRef(
2978 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2979 if (DirKind == DK_ASSIGN)
2982 "expected absolute expression; not all symbols have known values",
2983 {StartLoc, EndLoc});
2986 if (!Var.IsText || Var.TextValue != ExprAsString) {
2987 switch (Var.Redefinable) {
2988 case Variable::NOT_REDEFINABLE:
2989 return Error(getTok().getLoc(),
"invalid variable redefinition");
2990 case Variable::WARN_ON_REDEFINITION:
2991 if (
Warning(NameLoc,
"redefining '" + Name +
2992 "', already defined on the command line")) {
3002 Var.TextValue = ExprAsString.
str();
3003 Var.Redefinable = Variable::REDEFINABLE;
3008 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
3009 const MCConstantExpr *PrevValue =
3013 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
3014 switch (Var.Redefinable) {
3015 case Variable::NOT_REDEFINABLE:
3016 return Error(getTok().getLoc(),
"invalid variable redefinition");
3017 case Variable::WARN_ON_REDEFINITION:
3018 if (
Warning(NameLoc,
"redefining '" + Name +
3019 "', already defined on the command line")) {
3029 Var.TextValue.clear();
3030 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3033 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3035 Sym->setExternal(
false);
3040bool MasmParser::parseEscapedString(std::string &
Data) {
3045 char Quote = getTok().getString().front();
3046 StringRef Str = getTok().getStringContents();
3047 Data.reserve(Str.size());
3048 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3049 Data.push_back(Str[i]);
3050 if (Str[i] == Quote) {
3054 if (i + 1 == Str.size())
3055 return Error(getTok().getLoc(),
"missing quotation mark in string");
3056 if (Str[i + 1] == Quote)
3065bool MasmParser::parseAngleBracketString(std::string &
Data) {
3066 SMLoc EndLoc, StartLoc = getTok().getLoc();
3068 const char *StartChar = StartLoc.
getPointer() + 1;
3069 const char *EndChar = EndLoc.
getPointer() - 1;
3070 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3081bool MasmParser::parseTextItem(std::string &
Data) {
3082 switch (getTok().getKind()) {
3089 Data = std::to_string(Res);
3096 return parseAngleBracketString(
Data);
3100 SMLoc StartLoc = getTok().getLoc();
3101 if (parseIdentifier(
ID))
3105 bool Expanded =
false;
3108 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3109 if (BuiltinIt != BuiltinSymbolMap.end()) {
3110 std::optional<std::string> BuiltinText =
3111 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3116 Data = std::move(*BuiltinText);
3123 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3124 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3126 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(),
ID,
Data)) {
3135 auto VarIt = Variables.
find(
ID.lower());
3136 if (VarIt != Variables.
end()) {
3137 const Variable &Var = VarIt->getValue();
3142 Data = Var.TextValue;
3165bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3166 auto parseOp = [&]() ->
bool {
3168 if (checkForValidSection() || parseEscapedString(
Data))
3170 getStreamer().emitBytes(
Data);
3172 getStreamer().emitBytes(StringRef(
"\0", 1));
3176 if (parseMany(parseOp))
3177 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3181bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3185 int64_t IntValue = MCE->getValue();
3187 return Error(MCE->getLoc(),
"out of range literal value");
3188 getStreamer().emitIntValue(IntValue,
Size);
3193 getStreamer().emitIntValue(0,
Size);
3201bool MasmParser::parseScalarInitializer(
unsigned Size,
3202 SmallVectorImpl<const MCExpr *> &Values,
3203 unsigned StringPadLength) {
3206 if (parseEscapedString(
Value))
3209 for (
const unsigned char CharVal :
Value)
3213 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3216 const MCExpr *
Value;
3217 if (parseExpression(
Value))
3220 getTok().getString().equals_insensitive(
"dup")) {
3225 "cannot repeat value a non-constant number of times");
3226 const int64_t Repetitions = MCE->
getValue();
3227 if (Repetitions < 0)
3229 "cannot repeat value a negative number of times");
3233 "parentheses required for 'dup' contents") ||
3234 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3237 for (
int i = 0; i < Repetitions; ++i)
3246bool MasmParser::parseScalarInstList(
unsigned Size,
3247 SmallVectorImpl<const MCExpr *> &Values,
3249 while (getTok().
isNot(EndToken) &&
3252 parseScalarInitializer(
Size, Values);
3262bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3264 if (checkForValidSection() || parseScalarInstList(
Size, Values))
3267 for (
const auto *
Value : Values) {
3271 *
Count = Values.size();
3276bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3277 StructInfo &
Struct = StructInProgress.
back();
3279 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3283 if (parseScalarInstList(
Size, IntInfo.Values))
3286 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3287 Field.LengthOf = IntInfo.Values.size();
3290 Struct.NextOffset = FieldEnd;
3298bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3299 if (StructInProgress.
empty()) {
3301 if (emitIntegralValues(
Size))
3302 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3303 }
else if (addIntegralField(
"",
Size)) {
3304 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3312bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3313 StringRef Name, SMLoc NameLoc) {
3314 if (StructInProgress.
empty()) {
3317 getStreamer().emitLabel(Sym);
3320 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3328 }
else if (addIntegralField(Name,
Size)) {
3329 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3335bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3341 SignLoc = getLexer().getLoc();
3345 SignLoc = getLexer().getLoc();
3350 return TokError(Lexer.getErr());
3353 return TokError(
"unexpected token in directive");
3357 StringRef IDVal = getTok().getString();
3366 return TokError(
"invalid floating point literal");
3370 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3371 if (SizeInBits != (IDVal.
size() << 2))
3372 return TokError(
"invalid floating point literal");
3377 Res = APInt(SizeInBits, IDVal, 16);
3379 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3382 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3384 return TokError(
"invalid floating point literal");
3392 Res =
Value.bitcastToAPInt();
3397bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3398 SmallVectorImpl<APInt> &ValuesAsInt,
3400 while (getTok().
isNot(EndToken) ||
3403 const AsmToken NextTok = peekTok();
3406 const MCExpr *
Value;
3412 "cannot repeat value a non-constant number of times");
3413 const int64_t Repetitions = MCE->
getValue();
3414 if (Repetitions < 0)
3416 "cannot repeat value a negative number of times");
3420 "parentheses required for 'dup' contents") ||
3421 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3424 for (
int i = 0; i < Repetitions; ++i)
3425 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3428 if (parseRealValue(Semantics, AsInt))
3443bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3445 if (checkForValidSection())
3449 if (parseRealInstList(Semantics, ValuesAsInt))
3452 for (
const APInt &AsInt : ValuesAsInt) {
3453 getStreamer().emitIntValue(AsInt);
3456 *
Count = ValuesAsInt.size();
3461bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3463 StructInfo &
Struct = StructInProgress.
back();
3465 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3469 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3472 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3473 Field.LengthOf = RealInfo.AsIntValues.size();
3478 Struct.NextOffset = FieldEnd;
3486bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3487 const fltSemantics &Semantics,
3489 if (StructInProgress.
empty()) {
3491 if (emitRealValues(Semantics))
3492 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3493 }
else if (addRealField(
"", Semantics,
Size)) {
3494 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3501bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3502 const fltSemantics &Semantics,
3503 unsigned Size, StringRef Name,
3505 if (StructInProgress.
empty()) {
3508 getStreamer().emitLabel(Sym);
3510 if (emitRealValues(Semantics, &
Count))
3511 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3519 }
else if (addRealField(Name, Semantics,
Size)) {
3520 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3525bool MasmParser::parseOptionalAngleBracketOpen() {
3526 const AsmToken Tok = getTok();
3528 AngleBracketDepth++;
3532 AngleBracketDepth++;
3536 AngleBracketDepth++;
3543bool MasmParser::parseAngleBracketClose(
const Twine &Msg) {
3544 const AsmToken Tok = getTok();
3550 AngleBracketDepth--;
3554bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3555 const IntFieldInfo &Contents,
3556 FieldInitializer &Initializer) {
3557 SMLoc Loc = getTok().getLoc();
3562 return Error(Loc,
"Cannot initialize scalar field with array value");
3566 }
else if (parseOptionalAngleBracketOpen()) {
3568 return Error(Loc,
"Cannot initialize scalar field with array value");
3570 parseAngleBracketClose())
3572 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3573 return Error(Loc,
"Cannot initialize array field with scalar value");
3574 }
else if (parseScalarInitializer(
Field.Type, Values,
3580 return Error(Loc,
"Initializer too long for field; expected at most " +
3581 std::to_string(
Field.LengthOf) +
" elements, got " +
3582 std::to_string(Values.
size()));
3585 Values.
append(Contents.Values.begin() + Values.
size(), Contents.Values.end());
3587 Initializer = FieldInitializer(std::move(Values));
3591bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3592 const RealFieldInfo &Contents,
3593 FieldInitializer &Initializer) {
3594 const fltSemantics *Semantics;
3595 switch (
Field.Type) {
3597 Semantics = &APFloat::IEEEsingle();
3600 Semantics = &APFloat::IEEEdouble();
3603 Semantics = &APFloat::x87DoubleExtended();
3609 SMLoc Loc = getTok().getLoc();
3613 if (
Field.LengthOf == 1)
3614 return Error(Loc,
"Cannot initialize scalar field with array value");
3618 }
else if (parseOptionalAngleBracketOpen()) {
3619 if (
Field.LengthOf == 1)
3620 return Error(Loc,
"Cannot initialize scalar field with array value");
3622 parseAngleBracketClose())
3624 }
else if (
Field.LengthOf > 1) {
3625 return Error(Loc,
"Cannot initialize array field with scalar value");
3628 if (parseRealValue(*Semantics, AsIntValues.
back()))
3632 if (AsIntValues.
size() >
Field.LengthOf) {
3633 return Error(Loc,
"Initializer too long for field; expected at most " +
3634 std::to_string(
Field.LengthOf) +
" elements, got " +
3635 std::to_string(AsIntValues.
size()));
3638 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3639 Contents.AsIntValues.end());
3641 Initializer = FieldInitializer(std::move(AsIntValues));
3645bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3646 const StructFieldInfo &Contents,
3647 FieldInitializer &Initializer) {
3648 SMLoc Loc = getTok().getLoc();
3650 std::vector<StructInitializer> Initializers;
3651 if (
Field.LengthOf > 1) {
3653 if (parseStructInstList(Contents.Structure, Initializers,
3657 }
else if (parseOptionalAngleBracketOpen()) {
3658 if (parseStructInstList(Contents.Structure, Initializers,
3660 parseAngleBracketClose())
3663 return Error(Loc,
"Cannot initialize array field with scalar value");
3666 Initializers.emplace_back();
3667 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3671 if (Initializers.size() >
Field.LengthOf) {
3672 return Error(Loc,
"Initializer too long for field; expected at most " +
3673 std::to_string(
Field.LengthOf) +
" elements, got " +
3674 std::to_string(Initializers.size()));
3678 Initializers.size()));
3680 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3684bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3685 FieldInitializer &Initializer) {
3686 switch (
Field.Contents.FT) {
3688 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3690 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3692 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3697bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3698 StructInitializer &Initializer) {
3699 const AsmToken FirstToken = getTok();
3701 std::optional<AsmToken::TokenKind> EndToken;
3704 }
else if (parseOptionalAngleBracketOpen()) {
3706 AngleBracketDepth++;
3713 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3716 auto &FieldInitializers = Initializer.FieldInitializers;
3717 size_t FieldIndex = 0;
3720 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3721 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3725 FieldInitializers.push_back(
Field.Contents);
3729 FieldInitializers.emplace_back(
Field.Contents.FT);
3730 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3734 SMLoc CommaLoc = getTok().getLoc();
3737 if (FieldIndex == Structure.Fields.size())
3738 return Error(CommaLoc,
"'" + Structure.Name +
3739 "' initializer initializes too many fields");
3745 FieldInitializers.push_back(
Field.Contents);
3749 return parseAngleBracketClose();
3751 return parseToken(*EndToken);
3757bool MasmParser::parseStructInstList(
3758 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3760 while (getTok().
isNot(EndToken) ||
3763 const AsmToken NextTok = peekTok();
3766 const MCExpr *
Value;
3772 "cannot repeat value a non-constant number of times");
3773 const int64_t Repetitions = MCE->
getValue();
3774 if (Repetitions < 0)
3776 "cannot repeat value a negative number of times");
3778 std::vector<StructInitializer> DuplicatedValues;
3780 "parentheses required for 'dup' contents") ||
3781 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3784 for (
int i = 0; i < Repetitions; ++i)
3787 Initializers.emplace_back();
3788 if (parseStructInitializer(Structure, Initializers.back()))
3801bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3802 const IntFieldInfo &Contents) {
3804 for (
const MCExpr *
Value : Contents.Values) {
3811bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3812 const RealFieldInfo &Contents) {
3813 for (
const APInt &AsInt : Contents.AsIntValues) {
3820bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3821 const StructFieldInfo &Contents) {
3822 for (
const auto &Initializer : Contents.Initializers) {
3824 for (
const auto &SubField : Contents.Structure.Fields) {
3825 getStreamer().emitZeros(SubField.Offset -
Offset);
3826 Offset = SubField.Offset + SubField.SizeOf;
3827 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3833bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3834 switch (
Field.Contents.FT) {
3836 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3838 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3840 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3845bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3846 const IntFieldInfo &Contents,
3847 const IntFieldInfo &Initializer) {
3848 for (
const auto &
Value : Initializer.Values) {
3853 for (
const auto &
Value :
3861bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3862 const RealFieldInfo &Contents,
3863 const RealFieldInfo &Initializer) {
3864 for (
const auto &AsInt : Initializer.AsIntValues) {
3869 for (
const auto &AsInt :
3877bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3878 const StructFieldInfo &Contents,
3879 const StructFieldInfo &Initializer) {
3880 for (
const auto &Init : Initializer.Initializers) {
3881 if (emitStructInitializer(Contents.Structure, Init))
3886 Initializer.Initializers.size())) {
3887 if (emitStructInitializer(Contents.Structure, Init))
3893bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3894 const FieldInitializer &Initializer) {
3895 switch (
Field.Contents.FT) {
3897 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3898 Initializer.IntInfo);
3900 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3901 Initializer.RealInfo);
3903 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3904 Initializer.StructInfo);
3909bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3910 const StructInitializer &Initializer) {
3911 if (!Structure.Initializable)
3912 return Error(getLexer().getLoc(),
3913 "cannot initialize a value of type '" + Structure.Name +
3914 "'; 'org' was used in the type's declaration");
3916 for (
const auto &Init : Initializer.FieldInitializers) {
3917 const auto &
Field = Structure.Fields[
Index++];
3920 if (emitFieldInitializer(
Field, Init))
3925 Structure.Fields, Initializer.FieldInitializers.size())) {
3928 if (emitFieldValue(
Field))
3932 if (
Offset != Structure.Size)
3933 getStreamer().emitZeros(Structure.Size -
Offset);
3938bool MasmParser::emitStructValues(
const StructInfo &Structure,
3940 std::vector<StructInitializer> Initializers;
3941 if (parseStructInstList(Structure, Initializers))
3944 for (
const auto &Initializer : Initializers) {
3945 if (emitStructInitializer(Structure, Initializer))
3950 *
Count = Initializers.size();
3955bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3956 StructInfo &OwningStruct = StructInProgress.
back();
3958 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3959 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3961 StructInfo.Structure = Structure;
3962 Field.Type = Structure.Size;
3964 if (parseStructInstList(Structure, StructInfo.Initializers))
3967 Field.LengthOf = StructInfo.Initializers.size();
3971 if (!OwningStruct.IsUnion) {
3972 OwningStruct.NextOffset = FieldEnd;
3974 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3982bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3983 StringRef Directive, SMLoc DirLoc) {
3984 if (StructInProgress.
empty()) {
3985 if (emitStructValues(Structure))
3987 }
else if (addStructField(
"", Structure)) {
3988 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
3996bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
3997 StringRef Directive,
3998 SMLoc DirLoc, StringRef Name) {
3999 if (StructInProgress.
empty()) {
4002 getStreamer().emitLabel(Sym);
4004 if (emitStructValues(Structure, &
Count))
4007 Type.Name = Structure.Name;
4009 Type.ElementSize = Structure.Size;
4012 }
else if (addStructField(Name, Structure)) {
4013 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4025bool MasmParser::parseDirectiveStruct(StringRef Directive,
4026 DirectiveKind DirKind, StringRef Name,
4030 AsmToken NextTok = getTok();
4031 int64_t AlignmentValue = 1;
4034 parseAbsoluteExpression(AlignmentValue)) {
4035 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4039 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4040 std::to_string(AlignmentValue));
4046 QualifierLoc = getTok().getLoc();
4047 if (parseIdentifier(Qualifier))
4048 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4049 if (!
Qualifier.equals_insensitive(
"nonunique"))
4050 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4052 "' directive; expected none or NONUNIQUE");
4056 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4058 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4066bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4067 DirectiveKind DirKind) {
4068 if (StructInProgress.
empty())
4069 return TokError(
"missing name in top-level '" + Twine(Directive) +
4074 Name = getTok().getIdentifier();
4078 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4082 StructInProgress.
reserve(StructInProgress.
size() + 1);
4083 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4084 StructInProgress.
back().Alignment);
4088bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4089 if (StructInProgress.
empty())
4090 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4091 if (StructInProgress.
size() > 1)
4092 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4093 if (StructInProgress.
back().Name.compare_insensitive(Name))
4094 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4095 StructInProgress.
back().Name +
"'");
4096 StructInfo Structure = StructInProgress.
pop_back_val();
4100 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4101 Structs[
Name.lower()] = Structure;
4104 return addErrorSuffix(
" in ENDS directive");
4109bool MasmParser::parseDirectiveNestedEnds() {
4110 if (StructInProgress.
empty())
4111 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4112 if (StructInProgress.
size() == 1)
4113 return TokError(
"missing name in top-level ENDS directive");
4116 return addErrorSuffix(
" in nested ENDS directive");
4118 StructInfo Structure = StructInProgress.
pop_back_val();
4120 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4122 StructInfo &ParentStruct = StructInProgress.
back();
4123 if (Structure.Name.
empty()) {
4126 const size_t OldFields = ParentStruct.Fields.size();
4127 ParentStruct.Fields.insert(
4128 ParentStruct.Fields.end(),
4129 std::make_move_iterator(Structure.Fields.begin()),
4130 std::make_move_iterator(Structure.Fields.end()));
4131 for (
const auto &FieldByName : Structure.FieldsByName) {
4132 ParentStruct.FieldsByName[FieldByName.getKey()] =
4133 FieldByName.getValue() + OldFields;
4136 unsigned FirstFieldOffset = 0;
4137 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4139 ParentStruct.NextOffset,
4140 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4143 if (ParentStruct.IsUnion) {
4144 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4149 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4150 if (!ParentStruct.IsUnion) {
4151 ParentStruct.NextOffset = StructureEnd;
4153 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4156 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4157 Structure.AlignmentSize);
4158 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4159 Field.Type = Structure.Size;
4161 Field.SizeOf = Structure.Size;
4164 if (!ParentStruct.IsUnion) {
4165 ParentStruct.NextOffset = StructureEnd;
4167 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4169 StructInfo.Structure = Structure;
4170 StructInfo.Initializers.emplace_back();
4171 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4172 for (
const auto &SubField : Structure.Fields) {
4173 FieldInitializers.push_back(SubField.Contents);
4182bool MasmParser::parseDirectiveOrg() {
4184 SMLoc OffsetLoc = Lexer.getLoc();
4185 if (checkForValidSection() || parseExpression(
Offset))
4188 return addErrorSuffix(
" in 'org' directive");
4190 if (StructInProgress.
empty()) {
4192 if (checkForValidSection())
4193 return addErrorSuffix(
" in 'org' directive");
4195 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4198 StructInfo &Structure = StructInProgress.
back();
4200 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4201 return Error(OffsetLoc,
4202 "expected absolute expression in 'org' directive");
4206 "expected non-negative value in struct's 'org' directive; was " +
4207 std::to_string(OffsetRes));
4208 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4211 Structure.Initializable =
false;
4217bool MasmParser::emitAlignTo(int64_t Alignment) {
4218 if (StructInProgress.
empty()) {
4220 if (checkForValidSection())
4225 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4227 getStreamer().emitCodeAlignment(
Align(Alignment),
4228 &getTargetParser().getSTI(),
4232 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4238 StructInfo &Structure = StructInProgress.
back();
4239 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4247bool MasmParser::parseDirectiveAlign() {
4248 SMLoc AlignmentLoc = getLexer().getLoc();
4254 "align directive with no operand is ignored") &&
4257 if (parseAbsoluteExpression(Alignment) || parseEOL())
4258 return addErrorSuffix(
" in align directive");
4261 bool ReturnVal =
false;
4268 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4269 std::to_string(Alignment));
4271 if (emitAlignTo(Alignment))
4272 ReturnVal |= addErrorSuffix(
" in align directive");
4279bool MasmParser::parseDirectiveEven() {
4280 if (parseEOL() || emitAlignTo(2))
4281 return addErrorSuffix(
" in even directive");
4292bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4296 return Error(Lexer.getLoc(),
4297 "Vararg parameter '" +
Parameters.back().Name +
4298 "' should be last in the list of parameters");
4302 return TokError(
"expected identifier in 'macro' directive");
4305 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4306 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4307 return TokError(
"macro '" + Name +
"' has multiple parameters"
4317 ParamLoc = Lexer.getLoc();
4318 if (parseMacroArgument(
nullptr,
Parameter.Value))
4324 QualLoc = Lexer.getLoc();
4325 if (parseIdentifier(Qualifier))
4326 return Error(QualLoc,
"missing parameter qualifier for "
4328 Parameter.Name +
"' in macro '" + Name +
4331 if (
Qualifier.equals_insensitive(
"req"))
4333 else if (
Qualifier.equals_insensitive(
"vararg"))
4336 return Error(QualLoc,
4337 Qualifier +
" is not a valid parameter qualifier for '" +
4338 Parameter.Name +
"' in macro '" + Name +
"'");
4351 std::vector<std::string>
Locals;
4353 getTok().getIdentifier().equals_insensitive(
"local")) {
4358 if (parseIdentifier(
ID))
4370 AsmToken EndToken, StartToken = getTok();
4371 unsigned MacroDepth = 0;
4372 bool IsMacroFunction =
false;
4382 return Error(NameLoc,
"no matching 'endm' in definition");
4387 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4388 if (MacroDepth == 0) {
4389 EndToken = getTok();
4392 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4399 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4401 IsMacroFunction =
true;
4403 }
else if (isMacroLikeDirective()) {
4411 eatToEndOfStatement();
4415 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4420 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4421 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4431bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4432 StringRef Directive,
4433 std::string &
Value) {
4434 SMLoc EndLoc = getTok().getLoc();
4436 return Error(EndLoc,
4437 "unable to parse text item in '" + Directive +
"' directive");
4438 eatToEndOfStatement();
4440 if (!isInsideMacroInstantiation())
4441 return TokError(
"unexpected '" + Directive +
"' in file, "
4442 "no current macro definition");
4445 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4446 TheCondState = TheCondStack.back();
4447 TheCondStack.pop_back();
4456bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4458 return TokError(
"unexpected token in '" + Directive +
"' directive");
4462 if (isInsideMacroInstantiation()) {
4469 return TokError(
"unexpected '" + Directive +
"' in file, "
4470 "no current macro definition");
4475bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4479 if (parseTokenLoc(NameLoc) ||
4480 check(parseIdentifier(Name), NameLoc,
4481 "expected identifier in 'purge' directive"))
4485 <<
"Un-defining macro: " << Name <<
"\n");
4487 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4498bool MasmParser::parseDirectiveExtern() {
4500 auto parseOp = [&]() ->
bool {
4502 SMLoc NameLoc = getTok().getLoc();
4504 return Error(NameLoc,
"expected name");
4509 SMLoc TypeLoc = getTok().getLoc();
4510 if (parseIdentifier(TypeName))
4511 return Error(TypeLoc,
"expected type");
4512 if (!
TypeName.equals_insensitive(
"proc")) {
4514 if (lookUpType(TypeName,
Type))
4515 return Error(TypeLoc,
"unrecognized type");
4519 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4520 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4525 if (parseMany(parseOp))
4526 return addErrorSuffix(
" in directive 'extern'");
4532bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4533 auto parseOp = [&]() ->
bool {
4534 SMLoc Loc = getTok().getLoc();
4537 return Error(Loc,
"expected identifier");
4541 return Error(Loc,
"non-local symbol required");
4543 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4544 return Error(Loc,
"unable to emit symbol attribute");
4548 if (parseMany(parseOp))
4549 return addErrorSuffix(
" in directive");
4555bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4556 if (checkForValidSection())
4559 SMLoc IDLoc = getLexer().getLoc();
4562 return TokError(
"expected identifier in directive");
4565 return TokError(
"unexpected token in directive");
4569 SMLoc SizeLoc = getLexer().getLoc();
4570 if (parseAbsoluteExpression(
Size))
4573 int64_t Pow2Alignment = 0;
4574 SMLoc Pow2AlignmentLoc;
4577 Pow2AlignmentLoc = getLexer().getLoc();
4578 if (parseAbsoluteExpression(Pow2Alignment))
4583 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4586 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4589 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4590 Pow2Alignment =
Log2_64(Pow2Alignment);
4600 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4601 "be less than zero");
4606 if (Pow2Alignment < 0)
4607 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4608 "alignment, can't be less than zero");
4612 return Error(IDLoc,
"invalid symbol redefinition");
4616 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4617 Align(1ULL << Pow2Alignment));
4621 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4629bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4631 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4632 assert(DelimiterEnd != std::string::npos);
4633 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4634 if (Delimiter.
empty())
4635 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4638 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4648bool MasmParser::parseDirectiveInclude() {
4651 SMLoc IncludeLoc = getTok().getLoc();
4653 if (parseAngleBracketString(Filename))
4655 if (check(
Filename.empty(),
"missing filename in 'include' directive") ||
4657 "unexpected token in 'include' directive") ||
4660 check(enterIncludeFile(Filename), IncludeLoc,
4661 "Could not find include file '" + Filename +
"'"))
4669bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4670 TheCondStack.push_back(TheCondState);
4672 if (TheCondState.
Ignore) {
4673 eatToEndOfStatement();
4676 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4685 ExprValue = ExprValue == 0;
4689 TheCondState.
CondMet = ExprValue;
4698bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4699 TheCondStack.push_back(TheCondState);
4702 if (TheCondState.
Ignore) {
4703 eatToEndOfStatement();
4706 if (parseTextItem(Str))
4707 return TokError(
"expected text item parameter for 'ifb' directive");
4712 TheCondState.
CondMet = ExpectBlank == Str.empty();
4721bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4722 bool CaseInsensitive) {
4723 std::string String1, String2;
4725 if (parseTextItem(String1)) {
4727 return TokError(
"expected text item parameter for 'ifidn' directive");
4728 return TokError(
"expected text item parameter for 'ifdif' directive");
4734 "expected comma after first string for 'ifidn' directive");
4735 return TokError(
"expected comma after first string for 'ifdif' directive");
4739 if (parseTextItem(String2)) {
4741 return TokError(
"expected text item parameter for 'ifidn' directive");
4742 return TokError(
"expected text item parameter for 'ifdif' directive");
4745 TheCondStack.push_back(TheCondState);
4747 if (CaseInsensitive)
4749 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4751 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4760bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4761 TheCondStack.push_back(TheCondState);
4764 if (TheCondState.
Ignore) {
4765 eatToEndOfStatement();
4767 bool is_defined =
false;
4769 SMLoc StartLoc, EndLoc;
4771 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4774 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4778 if (BuiltinSymbolMap.contains(
Name.lower())) {
4788 TheCondState.
CondMet = (is_defined == expect_defined);
4797bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4798 DirectiveKind DirKind) {
4801 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4802 " .if or an .elseif");
4805 bool LastIgnoreState =
false;
4806 if (!TheCondStack.empty())
4807 LastIgnoreState = TheCondStack.back().Ignore;
4808 if (LastIgnoreState || TheCondState.
CondMet) {
4809 TheCondState.
Ignore =
true;
4810 eatToEndOfStatement();
4813 if (parseAbsoluteExpression(ExprValue))
4825 ExprValue = ExprValue == 0;
4829 TheCondState.
CondMet = ExprValue;
4838bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4841 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4842 " if or an elseif");
4845 bool LastIgnoreState =
false;
4846 if (!TheCondStack.empty())
4847 LastIgnoreState = TheCondStack.back().Ignore;
4848 if (LastIgnoreState || TheCondState.
CondMet) {
4849 TheCondState.
Ignore =
true;
4850 eatToEndOfStatement();
4853 if (parseTextItem(Str)) {
4855 return TokError(
"expected text item parameter for 'elseifb' directive");
4856 return TokError(
"expected text item parameter for 'elseifnb' directive");
4862 TheCondState.
CondMet = ExpectBlank == Str.empty();
4872bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4873 bool expect_defined) {
4876 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4877 " if or an elseif");
4880 bool LastIgnoreState =
false;
4881 if (!TheCondStack.empty())
4882 LastIgnoreState = TheCondStack.back().Ignore;
4883 if (LastIgnoreState || TheCondState.
CondMet) {
4884 TheCondState.
Ignore =
true;
4885 eatToEndOfStatement();
4887 bool is_defined =
false;
4889 SMLoc StartLoc, EndLoc;
4891 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4894 if (check(parseIdentifier(Name),
4895 "expected identifier after 'elseifdef'") ||
4899 if (BuiltinSymbolMap.contains(
Name.lower())) {
4909 TheCondState.
CondMet = (is_defined == expect_defined);
4918bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4919 bool CaseInsensitive) {
4922 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4923 " if or an elseif");
4926 bool LastIgnoreState =
false;
4927 if (!TheCondStack.empty())
4928 LastIgnoreState = TheCondStack.back().Ignore;
4929 if (LastIgnoreState || TheCondState.
CondMet) {
4930 TheCondState.
Ignore =
true;
4931 eatToEndOfStatement();
4933 std::string String1, String2;
4935 if (parseTextItem(String1)) {
4938 "expected text item parameter for 'elseifidn' directive");
4939 return TokError(
"expected text item parameter for 'elseifdif' directive");
4945 "expected comma after first string for 'elseifidn' directive");
4947 "expected comma after first string for 'elseifdif' directive");
4951 if (parseTextItem(String2)) {
4954 "expected text item parameter for 'elseifidn' directive");
4955 return TokError(
"expected text item parameter for 'elseifdif' directive");
4958 if (CaseInsensitive)
4960 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4962 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4971bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4977 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4980 bool LastIgnoreState =
false;
4981 if (!TheCondStack.empty())
4982 LastIgnoreState = TheCondStack.back().Ignore;
4983 if (LastIgnoreState || TheCondState.
CondMet)
4984 TheCondState.
Ignore =
true;
4986 TheCondState.
Ignore =
false;
4993bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5005bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5006 if (!TheCondStack.empty()) {
5007 if (TheCondStack.back().Ignore) {
5008 eatToEndOfStatement();
5013 std::string Message =
".err directive invoked in source file";
5018 return Error(DirectiveLoc, Message);
5023bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5024 if (!TheCondStack.empty()) {
5025 if (TheCondStack.back().Ignore) {
5026 eatToEndOfStatement();
5032 if (parseTextItem(Text))
5033 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5035 std::string Message =
".errb directive invoked in source file";
5038 return addErrorSuffix(
" in '.errb' directive");
5043 if (
Text.empty() == ExpectBlank)
5044 return Error(DirectiveLoc, Message);
5050bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5051 bool ExpectDefined) {
5052 if (!TheCondStack.empty()) {
5053 if (TheCondStack.back().Ignore) {
5054 eatToEndOfStatement();
5059 bool IsDefined =
false;
5061 SMLoc StartLoc, EndLoc;
5063 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5066 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5069 if (BuiltinSymbolMap.contains(
Name.lower())) {
5079 std::string Message =
".errdef directive invoked in source file";
5082 return addErrorSuffix(
" in '.errdef' directive");
5087 if (IsDefined == ExpectDefined)
5088 return Error(DirectiveLoc, Message);
5094bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5095 bool CaseInsensitive) {
5096 if (!TheCondStack.empty()) {
5097 if (TheCondStack.back().Ignore) {
5098 eatToEndOfStatement();
5103 std::string String1, String2;
5105 if (parseTextItem(String1)) {
5107 return TokError(
"expected string parameter for '.erridn' directive");
5108 return TokError(
"expected string parameter for '.errdif' directive");
5114 "expected comma after first string for '.erridn' directive");
5116 "expected comma after first string for '.errdif' directive");
5120 if (parseTextItem(String2)) {
5122 return TokError(
"expected string parameter for '.erridn' directive");
5123 return TokError(
"expected string parameter for '.errdif' directive");
5126 std::string Message;
5128 Message =
".erridn directive invoked in source file";
5130 Message =
".errdif directive invoked in source file";
5133 return addErrorSuffix(
" in '.erridn' directive");
5138 if (CaseInsensitive)
5140 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5142 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5145 if ((CaseInsensitive &&
5146 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5147 (ExpectEqual == (String1 == String2)))
5148 return Error(DirectiveLoc, Message);
5154bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5155 if (!TheCondStack.empty()) {
5156 if (TheCondStack.back().Ignore) {
5157 eatToEndOfStatement();
5163 if (parseAbsoluteExpression(ExprValue))
5164 return addErrorSuffix(
" in '.erre' directive");
5166 std::string Message =
".erre directive invoked in source file";
5169 return addErrorSuffix(
" in '.erre' directive");
5174 if ((ExprValue == 0) == ExpectZero)
5175 return Error(DirectiveLoc, Message);
5181bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5186 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5188 if (!TheCondStack.empty()) {
5189 TheCondState = TheCondStack.back();
5190 TheCondStack.pop_back();
5196void MasmParser::initializeDirectiveKindMap() {
5197 DirectiveKindMap[
"="] = DK_ASSIGN;
5198 DirectiveKindMap[
"equ"] = DK_EQU;
5199 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5203 DirectiveKindMap[
"byte"] = DK_BYTE;
5204 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5205 DirectiveKindMap[
"word"] = DK_WORD;
5206 DirectiveKindMap[
"sword"] = DK_SWORD;
5207 DirectiveKindMap[
"dword"] = DK_DWORD;
5208 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5209 DirectiveKindMap[
"fword"] = DK_FWORD;
5210 DirectiveKindMap[
"qword"] = DK_QWORD;
5211 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5212 DirectiveKindMap[
"real4"] = DK_REAL4;
5213 DirectiveKindMap[
"real8"] = DK_REAL8;
5214 DirectiveKindMap[
"real10"] = DK_REAL10;
5215 DirectiveKindMap[
"align"] = DK_ALIGN;
5216 DirectiveKindMap[
"even"] = DK_EVEN;
5217 DirectiveKindMap[
"org"] = DK_ORG;
5218 DirectiveKindMap[
"extern"] = DK_EXTERN;
5219 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5220 DirectiveKindMap[
"public"] = DK_PUBLIC;
5222 DirectiveKindMap[
"comment"] = DK_COMMENT;
5223 DirectiveKindMap[
"include"] = DK_INCLUDE;
5224 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5225 DirectiveKindMap[
"rept"] = DK_REPEAT;
5226 DirectiveKindMap[
"while"] = DK_WHILE;
5227 DirectiveKindMap[
"for"] = DK_FOR;
5228 DirectiveKindMap[
"irp"] = DK_FOR;
5229 DirectiveKindMap[
"forc"] = DK_FORC;
5230 DirectiveKindMap[
"irpc"] = DK_FORC;
5231 DirectiveKindMap[
"if"] = DK_IF;
5232 DirectiveKindMap[
"ife"] = DK_IFE;
5233 DirectiveKindMap[
"ifb"] = DK_IFB;
5234 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5235 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5236 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5237 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5238 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5239 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5240 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5241 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5242 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5243 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5244 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5245 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5246 DirectiveKindMap[
"else"] = DK_ELSE;
5247 DirectiveKindMap[
"end"] = DK_END;
5248 DirectiveKindMap[
"endif"] = DK_ENDIF;
5288 DirectiveKindMap[
"macro"] = DK_MACRO;
5289 DirectiveKindMap[
"exitm"] = DK_EXITM;
5290 DirectiveKindMap[
"endm"] = DK_ENDM;
5291 DirectiveKindMap[
"purge"] = DK_PURGE;
5292 DirectiveKindMap[
".err"] = DK_ERR;
5293 DirectiveKindMap[
".errb"] = DK_ERRB;
5294 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5295 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5296 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5297 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5298 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5299 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5300 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5301 DirectiveKindMap[
".erre"] = DK_ERRE;
5302 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5303 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5304 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5305 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5306 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5307 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5308 DirectiveKindMap[
".radix"] = DK_RADIX;
5309 DirectiveKindMap[
"db"] = DK_DB;
5310 DirectiveKindMap[
"dd"] = DK_DD;
5311 DirectiveKindMap[
"df"] = DK_DF;
5312 DirectiveKindMap[
"dq"] = DK_DQ;
5313 DirectiveKindMap[
"dw"] = DK_DW;
5314 DirectiveKindMap[
"echo"] = DK_ECHO;
5315 DirectiveKindMap[
"struc"] = DK_STRUCT;
5316 DirectiveKindMap[
"struct"] = DK_STRUCT;
5317 DirectiveKindMap[
"union"] = DK_UNION;
5318 DirectiveKindMap[
"ends"] = DK_ENDS;
5321bool MasmParser::isMacroLikeDirective() {
5323 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5324 .CasesLower({
"repeat",
"rept"},
true)
5325 .CaseLower(
"while",
true)
5326 .CasesLower({
"for",
"irp"},
true)
5327 .CasesLower({
"forc",
"irpc"},
true)
5333 peekTok().getIdentifier().equals_insensitive(
"macro"))
5339MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5340 AsmToken EndToken, StartToken = getTok();
5342 unsigned NestLevel = 0;
5346 printError(DirectiveLoc,
"no matching 'endm' in definition");
5350 if (isMacroLikeDirective())
5355 getTok().getIdentifier().equals_insensitive(
"endm")) {
5356 if (NestLevel == 0) {
5357 EndToken = getTok();
5360 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5369 eatToEndOfStatement();
5374 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5378 return &MacroLikeBodies.back();
5381bool MasmParser::expandStatement(SMLoc Loc) {
5383 SMLoc EndLoc = getTok().getLoc();
5388 StringMap<std::string> BuiltinValues;
5389 for (
const auto &S : BuiltinSymbolMap) {
5390 const BuiltinSymbol &Sym = S.getValue();
5391 if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5392 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5395 for (
const auto &
B : BuiltinValues) {
5396 MCAsmMacroParameter
P;
5397 MCAsmMacroArgument
A;
5398 P.Name =
B.getKey();
5406 for (
const auto &V : Variables) {
5409 MCAsmMacroParameter
P;
5410 MCAsmMacroArgument
A;
5419 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5420 MCAsmMacro
M = MacroLikeBodies.back();
5423 SmallString<80> Buf;
5424 raw_svector_ostream OS(Buf);
5425 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5427 std::unique_ptr<MemoryBuffer>
Expansion =
5433 EndStatementAtEOFStack.push_back(
false);
5438void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5439 raw_svector_ostream &OS) {
5440 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5442void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5444 raw_svector_ostream &OS) {
5447 std::unique_ptr<MemoryBuffer> Instantiation =
5452 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5453 ExitLoc, TheCondStack.size()};
5454 ActiveMacros.push_back(
MI);
5459 EndStatementAtEOFStack.push_back(
true);
5467bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5468 const MCExpr *CountExpr;
5469 SMLoc CountLoc = getTok().getLoc();
5470 if (parseExpression(CountExpr))
5474 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5475 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5478 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5482 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5488 SmallString<256> Buf;
5489 raw_svector_ostream OS(Buf);
5491 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5494 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5503bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5504 const MCExpr *CondExpr;
5505 SMLoc CondLoc = getTok().getLoc();
5506 if (parseExpression(CondExpr))
5510 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5516 SmallString<256> Buf;
5517 raw_svector_ostream OS(Buf);
5519 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5520 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5524 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5526 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5536bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5538 MCAsmMacroArguments
A;
5539 if (check(parseIdentifier(
Parameter.Name),
5540 "expected identifier in '" + Dir +
"' directive"))
5549 ParamLoc = Lexer.getLoc();
5550 if (parseMacroArgument(
nullptr,
Parameter.Value))
5556 QualLoc = Lexer.getLoc();
5557 if (parseIdentifier(Qualifier))
5558 return Error(QualLoc,
"missing parameter qualifier for "
5563 if (
Qualifier.equals_insensitive(
"req"))
5566 return Error(QualLoc,
5567 Qualifier +
" is not a valid parameter qualifier for '" +
5568 Parameter.Name +
"' in '" + Dir +
"' directive");
5573 "expected comma in '" + Dir +
"' directive") ||
5575 "values in '" + Dir +
5576 "' directive must be enclosed in angle brackets"))
5582 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5591 "values in '" + Dir +
5592 "' directive must be enclosed in angle brackets") ||
5597 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5603 SmallString<256> Buf;
5604 raw_svector_ostream OS(Buf);
5606 for (
const MCAsmMacroArgument &Arg :
A) {
5607 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5611 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5620bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5624 if (check(parseIdentifier(
Parameter.Name),
5625 "expected identifier in '" + Directive +
"' directive") ||
5627 "expected comma in '" + Directive +
"' directive"))
5629 if (parseAngleBracketString(Argument)) {
5637 for (; End <
Argument.size(); ++End) {
5647 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5653 SmallString<256> Buf;
5654 raw_svector_ostream OS(Buf);
5656 StringRef Values(Argument);
5657 for (std::size_t
I = 0, End = Values.
size();
I != End; ++
I) {
5658 MCAsmMacroArgument Arg;
5661 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5665 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5670bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &
Info,
5672 const MCExpr *
Value;
5673 SMLoc ExprLoc = getLexer().getLoc();
5674 if (parseExpression(
Value))
5678 return Error(ExprLoc,
"unexpected expression in _emit");
5679 uint64_t IntValue = MCE->
getValue();
5681 return Error(ExprLoc,
"literal value out of range for directive");
5687bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &
Info) {
5688 const MCExpr *
Value;
5689 SMLoc ExprLoc = getLexer().getLoc();
5690 if (parseExpression(
Value))
5694 return Error(ExprLoc,
"unexpected expression in align");
5695 uint64_t IntValue = MCE->
getValue();
5697 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5703bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5704 const SMLoc Loc = getLexer().getLoc();
5706 StringRef RadixString = StringRef(RadixStringRaw).trim();
5710 "radix must be a decimal number in the range 2 to 16; was " +
5713 if (Radix < 2 || Radix > 16)
5714 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5715 std::to_string(Radix));
5716 getLexer().setMasmDefaultRadix(Radix);
5722bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5725 if (!StringRef(Message).ends_with(
"\n"))
5753bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5755 if (Var.Name.empty()) {
5757 }
else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5758 return Error(SMLoc(),
"invalid variable redefinition");
5759 }
else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5760 Warning(SMLoc(),
"redefining '" + Name +
5761 "', already defined on the command line")) {
5764 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5766 Var.TextValue =
Value.str();
5770bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &
Info)
const {
5771 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5772 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5773 return lookUpField(
Base, Member,
Info);
5776bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5777 AsmFieldInfo &
Info)
const {
5781 AsmFieldInfo BaseInfo;
5782 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5785 auto StructIt = Structs.
find(
Base.lower());
5786 auto TypeIt = KnownType.
find(
Base.lower());
5787 if (TypeIt != KnownType.
end()) {
5788 StructIt = Structs.
find(TypeIt->second.Name.lower());
5790 if (StructIt != Structs.
end())
5791 return lookUpField(StructIt->second, Member,
Info);
5796bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5797 AsmFieldInfo &
Info)
const {
5799 Info.Type.Name = Structure.Name;
5800 Info.Type.Size = Structure.Size;
5801 Info.Type.ElementSize = Structure.Size;
5802 Info.Type.Length = 1;
5806 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5807 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5809 auto StructIt = Structs.
find(FieldName.
lower());
5810 if (StructIt != Structs.
end())
5811 return lookUpField(StructIt->second, FieldMember,
Info);
5813 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5814 if (FieldIt == Structure.FieldsByName.
end())
5817 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5818 if (FieldMember.empty()) {
5823 if (
Field.Contents.FT == FT_STRUCT)
5824 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5826 Info.Type.Name =
"";
5830 if (
Field.Contents.FT != FT_STRUCT)
5832 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5834 if (lookUpField(StructInfo.Structure, FieldMember,
Info))
5841bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &
Info)
const {
5842 unsigned Size = StringSwitch<unsigned>(Name)
5843 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5844 .CasesLower({
"word",
"dw",
"sword"}, 2)
5845 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5846 .CasesLower({
"fword",
"df"}, 6)
5847 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5848 .CaseLower(
"real4", 4)
5849 .CaseLower(
"real8", 8)
5850 .CaseLower(
"real10", 10)
5860 auto StructIt = Structs.
find(
Name.lower());
5861 if (StructIt != Structs.
end()) {
5862 const StructInfo &Structure = StructIt->second;
5864 Info.ElementSize = Structure.Size;
5866 Info.Size = Structure.Size;
5873bool MasmParser::parseMSInlineAsm(
5874 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5875 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5876 SmallVectorImpl<std::string> &Constraints,
5877 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5878 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5879 SmallVector<void *, 4> InputDecls;
5880 SmallVector<void *, 4> OutputDecls;
5883 SmallVector<std::string, 4> InputConstraints;
5884 SmallVector<std::string, 4> OutputConstraints;
5893 unsigned InputIdx = 0;
5894 unsigned OutputIdx = 0;
5897 if (parseCurlyBlockScope(AsmStrRewrites))
5900 ParseStatementInfo
Info(&AsmStrRewrites);
5901 bool StatementErr = parseStatement(
Info, &SI);
5903 if (StatementErr ||
Info.ParseError) {
5905 printPendingErrors();
5910 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5912 if (
Info.Opcode == ~0U)
5918 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5919 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5923 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5924 unsigned NumDefs =
Desc.getNumDefs();
5933 if (SymName.
empty())
5941 if (Operand.
isImm()) {
5949 bool isOutput = (i == 1) &&
Desc.mayStore();
5955 OutputConstraints.
push_back((
"=" + Constraint).str());
5961 if (
Desc.operands()[i - 1].isBranchTarget())
5973 NumOutputs = OutputDecls.
size();
5974 NumInputs = InputDecls.
size();
5979 Clobbers.
assign(ClobberRegs.
size(), std::string());
5980 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5981 raw_string_ostream OS(Clobbers[
I]);
5986 if (NumOutputs || NumInputs) {
5987 unsigned NumExprs = NumOutputs + NumInputs;
5988 OpDecls.resize(NumExprs);
5989 Constraints.
resize(NumExprs);
5990 for (
unsigned i = 0; i < NumOutputs; ++i) {
5991 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5992 Constraints[i] = OutputConstraints[i];
5994 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
5995 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
5996 Constraints[
j] = InputConstraints[i];
6001 std::string AsmStringIR;
6002 raw_string_ostream OS(AsmStringIR);
6003 StringRef ASMString =
6005 const char *AsmStart = ASMString.
begin();
6006 const char *AsmEnd = ASMString.
end();
6008 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6009 const AsmRewrite &AR = *
I;
6016 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6019 if (
unsigned Len = Loc - AsmStart)
6020 OS << StringRef(AsmStart, Len);
6024 AsmStart = Loc + AR.
Len;
6028 unsigned AdditionalSkip = 0;
6050 size_t OffsetLen = OffsetName.
size();
6051 auto rewrite_it = std::find_if(
6052 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6053 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6054 (FusingAR.Kind == AOK_Input ||
6055 FusingAR.Kind == AOK_CallInput);
6057 if (rewrite_it == AsmStrRewrites.
end()) {
6058 OS <<
"offset " << OffsetName;
6060 OS <<
"${" << InputIdx++ <<
":P}";
6061 rewrite_it->Done =
true;
6063 OS <<
'$' << InputIdx++;
6064 rewrite_it->Done =
true;
6076 OS <<
'$' << InputIdx++;
6079 OS <<
"${" << InputIdx++ <<
":P}";
6082 OS <<
'$' << OutputIdx++;
6087 case 8: OS <<
"byte ptr ";
break;
6088 case 16: OS <<
"word ptr ";
break;
6089 case 32: OS <<
"dword ptr ";
break;
6090 case 64: OS <<
"qword ptr ";
break;
6091 case 80: OS <<
"xword ptr ";
break;
6092 case 128: OS <<
"xmmword ptr ";
break;
6093 case 256: OS <<
"ymmword ptr ";
break;
6103 if (
getContext().getAsmInfo()->getAlignmentIsInBytes())
6108 unsigned Val = AR.
Val;
6110 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6111 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6123 AsmStart = Loc + AR.
Len + AdditionalSkip;
6127 if (AsmStart != AsmEnd)
6128 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6130 AsmString = OS.
str();
6134void MasmParser::initializeBuiltinSymbolMaps() {
6136 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6137 BuiltinSymbolMap[
"@line"] = BI_LINE;
6140 BuiltinSymbolMap[
"@date"] = BI_DATE;
6141 BuiltinSymbolMap[
"@time"] = BI_TIME;
6142 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6143 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6144 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6147 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6150 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6168const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6178 if (ActiveMacros.empty())
6182 ActiveMacros.front()->ExitBuffer);
6189std::optional<std::string>
6190MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6196 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6197 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6198 return std::string(TmpBuffer, Len);
6202 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6203 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6204 return std::string(TmpBuffer, Len);
6209 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6217 return getStreamer().getCurrentSectionOnly()->getName().str();
6222bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6226 "' requires arguments in parentheses")) {
6237 MCAsmMacro
M(Name,
"",
P, {},
true);
6239 MCAsmMacroArguments
A;
6248 for (
const MCAsmMacroArgument &Arg :
A) {
6249 for (
const AsmToken &Tok : Arg) {
6267 struct tm TM,
unsigned CB) {
6268 return new MasmParser(SM,
C, Out, MAI, TM, CB);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
AMDGPU Lower Kernel Arguments
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
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))
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
StringRef getPrivateLabelPrefix() const
bool shouldUseLogicalShr() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo * getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
Context & getContext() const
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.