75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
79struct MacroInstantiation {
81 SMLoc InstantiationLoc;
90 size_t CondStackDepth;
93struct ParseStatementInfo {
98 unsigned Opcode = ~0
U;
101 bool ParseError =
false;
104 std::optional<std::string> ExitValue;
106 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
108 ParseStatementInfo() =
delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
122 bool IsUnion =
false;
123 bool Initializable =
true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
128 std::vector<FieldInfo> Fields;
129 StringMap<size_t> FieldsByName;
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
134 StructInfo() =
default;
135 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
143struct StructInitializer;
147 IntFieldInfo() =
default;
151struct RealFieldInfo {
154 RealFieldInfo() =
default;
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
162 StructFieldInfo() =
default;
163 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
166class FieldInitializer {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
176 FieldInitializer(FieldType FT);
180 FieldInitializer(std::vector<StructInitializer> &&Initializers,
181 struct StructInfo Structure);
183 FieldInitializer(
const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
186 FieldInitializer &operator=(
const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
190struct StructInitializer {
191 std::vector<FieldInitializer> FieldInitializers;
202 unsigned LengthOf = 0;
207 FieldInitializer Contents;
209 FieldInfo(FieldType FT) : Contents(FT) {}
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
214 Initializers = std::move(V);
215 Structure = std::move(S);
218StructInfo::StructInfo(StringRef
StructName,
bool Union,
219 unsigned AlignmentValue)
222FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.
empty())
225 FieldsByName[FieldName.
lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &
Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
237FieldInitializer::~FieldInitializer() {
240 IntInfo.~IntFieldInfo();
243 RealInfo.~RealFieldInfo();
246 StructInfo.~StructFieldInfo();
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
254 new (&IntInfo) IntFieldInfo();
257 new (&RealInfo) RealFieldInfo();
260 new (&StructInfo) StructFieldInfo();
267 new (&IntInfo) IntFieldInfo(std::move(
Values));
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
281FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312FieldInitializer::operator=(
const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
316 IntInfo.~IntFieldInfo();
319 RealInfo.~RealFieldInfo();
322 StructInfo.~StructFieldInfo();
329 IntInfo = Initializer.IntInfo;
332 RealInfo = Initializer.RealInfo;
335 StructInfo = Initializer.StructInfo;
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
345 IntInfo.~IntFieldInfo();
348 RealInfo.~RealFieldInfo();
351 StructInfo.~StructFieldInfo();
358 IntInfo = Initializer.IntInfo;
361 RealInfo = Initializer.RealInfo;
364 StructInfo = Initializer.StructInfo;
373class MasmParser :
public MCAsmParser {
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
386 BitVector EndStatementAtEOFStack;
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
401 RedefinableKind Redefinable = REDEFINABLE;
403 std::string TextValue;
405 StringMap<Variable> Variables;
411 StringMap<StructInfo> Structs;
414 StringMap<AsmTypeInfo> KnownType;
417 std::vector<MacroInstantiation*> ActiveMacros;
420 std::deque<MCAsmMacro> MacroLikeBodies;
423 unsigned NumOfMacroInstantiations;
426 struct CppHashInfoTy {
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
433 CppHashInfoTy CppHashInfo;
436 StringRef FirstCppHashFilename;
443 unsigned AssemblerDialect = 1U;
446 bool ParsingMSInlineAsm =
false;
449 unsigned AngleBracketDepth = 0
U;
452 uint16_t LocalCounter = 0;
455 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
457 MasmParser(
const MasmParser &) =
delete;
458 MasmParser &operator=(
const MasmParser &) =
delete;
459 ~MasmParser()
override;
461 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler)
override {
465 ExtensionDirectiveMap[Directive] = std::move(Handler);
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
469 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
476 unsigned getAssemblerDialect()
override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
480 return AssemblerDialect;
482 void setAssemblerDialect(
unsigned i)
override {
483 AssemblerDialect = i;
486 void Note(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
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);
627 bool parseTextList(std::string &Result, StringRef IDVal);
628 bool setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
629 SMLoc NameLoc, Variable::RedefinableKind Redefinable);
634 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
635 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
636 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
641 DK_HANDLER_DIRECTIVE,
732 StringMap<DirectiveKind> DirectiveKindMap;
734 bool isMacroLikeDirective();
761 StringMap<BuiltinSymbol> BuiltinSymbolMap;
763 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
765 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
769 enum BuiltinFunction {
776 StringMap<BuiltinFunction> BuiltinFunctionMap;
778 bool evaluateBuiltinMacroFunction(BuiltinFunction
Function, StringRef Name,
782 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
785 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
786 bool parseScalarInitializer(
unsigned Size,
787 SmallVectorImpl<const MCExpr *> &
Values,
788 unsigned StringPadLength = 0);
789 bool parseScalarInstList(
790 unsigned Size, SmallVectorImpl<const MCExpr *> &
Values,
792 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
793 bool addIntegralField(StringRef Name,
unsigned Size);
794 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
795 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
796 StringRef Name, SMLoc NameLoc);
799 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
800 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
801 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
803 bool parseRealInstList(
804 const fltSemantics &Semantics, SmallVectorImpl<APInt> &
Values,
806 bool parseDirectiveNamedRealValue(StringRef TypeName,
807 const fltSemantics &Semantics,
808 unsigned Size, StringRef Name,
811 bool parseOptionalAngleBracketOpen();
812 bool parseAngleBracketClose(
const Twine &
Msg =
"expected '>'");
814 bool parseFieldInitializer(
const FieldInfo &
Field,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(
const FieldInfo &
Field,
817 const IntFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(
const FieldInfo &
Field,
820 const RealFieldInfo &Contents,
821 FieldInitializer &Initializer);
822 bool parseFieldInitializer(
const FieldInfo &
Field,
823 const StructFieldInfo &Contents,
824 FieldInitializer &Initializer);
826 bool parseStructInitializer(
const StructInfo &Structure,
827 StructInitializer &Initializer);
828 bool parseStructInstList(
829 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
832 bool emitFieldValue(
const FieldInfo &
Field);
833 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
834 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
835 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
837 bool emitFieldInitializer(
const FieldInfo &
Field,
838 const FieldInitializer &Initializer);
839 bool emitFieldInitializer(
const FieldInfo &
Field,
840 const IntFieldInfo &Contents,
841 const IntFieldInfo &Initializer);
842 bool emitFieldInitializer(
const FieldInfo &
Field,
843 const RealFieldInfo &Contents,
844 const RealFieldInfo &Initializer);
845 bool emitFieldInitializer(
const FieldInfo &
Field,
846 const StructFieldInfo &Contents,
847 const StructFieldInfo &Initializer);
849 bool emitStructInitializer(
const StructInfo &Structure,
850 const StructInitializer &Initializer);
853 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
854 bool addStructField(StringRef Name,
const StructInfo &Structure);
855 bool parseDirectiveStructValue(
const StructInfo &Structure,
856 StringRef Directive, SMLoc DirLoc);
857 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
858 StringRef Directive, SMLoc DirLoc,
862 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
863 DirectiveKind DirKind, SMLoc NameLoc);
865 bool parseDirectiveOrg();
867 bool emitAlignTo(int64_t Alignment);
868 bool parseDirectiveAlign();
869 bool parseDirectiveEven();
872 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
873 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
875 bool parseDirectiveEndMacro(StringRef Directive);
876 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
878 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
879 StringRef Name, SMLoc NameLoc);
880 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
881 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
882 bool parseDirectiveNestedEnds();
884 bool parseDirectiveExtern();
890 bool parseDirectiveComm(
bool IsLocal);
892 bool parseDirectiveComment(SMLoc DirectiveLoc);
894 bool parseDirectiveInclude();
897 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
899 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
902 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
903 bool CaseInsensitive);
905 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
907 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
909 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
911 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
914 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
915 bool CaseInsensitive);
916 bool parseDirectiveElse(SMLoc DirectiveLoc);
917 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
918 bool parseEscapedString(std::string &
Data)
override;
919 bool parseAngleBracketString(std::string &
Data)
override;
922 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
923 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
924 raw_svector_ostream &OS);
925 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
926 SMLoc ExitLoc, raw_svector_ostream &OS);
927 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
928 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
929 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
930 bool parseDirectiveWhile(SMLoc DirectiveLoc);
933 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
937 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
940 bool parseDirectiveEnd(SMLoc DirectiveLoc);
943 bool parseDirectiveError(SMLoc DirectiveLoc);
945 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
947 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
950 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
951 bool CaseInsensitive);
953 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
956 bool parseDirectiveRadix(SMLoc DirectiveLoc);
959 bool parseDirectiveEcho(SMLoc DirectiveLoc);
961 void initializeDirectiveKindMap();
962 void initializeBuiltinSymbolMaps();
975MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
976 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
977 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
981 SavedDiagHandler =
SrcMgr.getDiagHandler();
982 SavedDiagContext =
SrcMgr.getDiagContext();
985 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
986 EndStatementAtEOFStack.push_back(
true);
989 switch (Ctx.getObjectFileType()) {
990 case MCContext::IsCOFF:
991 PlatformParser.reset(createCOFFMasmParser());
994 report_fatal_error(
"llvm-ml currently supports only COFF output.");
998 initializeDirectiveKindMap();
999 PlatformParser->Initialize(*
this);
1000 initializeBuiltinSymbolMaps();
1002 NumOfMacroInstantiations = 0;
1005MasmParser::~MasmParser() {
1006 assert((HadError || ActiveMacros.empty()) &&
1007 "Unexpected active macro instantiation!");
1014void MasmParser::printMacroInstantiations() {
1016 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1017 it = ActiveMacros.rbegin(),
1018 ie = ActiveMacros.rend();
1021 "while in macro instantiation");
1024void MasmParser::Note(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1025 printPendingErrors();
1027 printMacroInstantiations();
1030bool MasmParser::Warning(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1031 if (getTargetParser().getTargetOptions().MCNoWarn)
1033 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1036 printMacroInstantiations();
1040bool MasmParser::printError(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1043 printMacroInstantiations();
1047bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1048 std::string IncludedFile;
1056 EndStatementAtEOFStack.push_back(
true);
1060void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1061 bool EndStatementAtEOF) {
1067bool MasmParser::expandMacros() {
1068 const AsmToken &Tok = getTok();
1071 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1074 const SMLoc MacroLoc = Tok.
getLoc();
1077 if (handleMacroInvocation(M, MacroLoc)) {
1084 std::optional<std::string> ExpandedValue;
1086 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1087 BuiltinIt != BuiltinSymbolMap.end()) {
1089 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1090 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1091 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1093 if (parseIdentifier(Name)) {
1097 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1100 ExpandedValue = Res;
1101 }
else if (
auto VarIt = Variables.
find(IDLower);
1102 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1103 ExpandedValue = VarIt->getValue().TextValue;
1108 std::unique_ptr<MemoryBuffer> Instantiation =
1116 EndStatementAtEOFStack.push_back(
false);
1121const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1123 Error(Lexer.getErrLoc(), Lexer.getErr());
1124 bool StartOfStatement =
false;
1129 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1132 StartOfStatement =
true;
1135 const AsmToken *tok = &Lexer.Lex();
1138 if (StartOfStatement) {
1141 size_t ReadCount = Lexer.peekTokens(Buf);
1173 if (ParentIncludeLoc != SMLoc()) {
1174 EndStatementAtEOFStack.pop_back();
1175 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1178 EndStatementAtEOFStack.pop_back();
1179 assert(EndStatementAtEOFStack.empty());
1185const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1189 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1191 if (ReadCount == 0) {
1195 if (ParentIncludeLoc != SMLoc()) {
1196 EndStatementAtEOFStack.pop_back();
1197 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1198 return peekTok(ShouldSkipSpace);
1200 EndStatementAtEOFStack.pop_back();
1201 assert(EndStatementAtEOFStack.empty());
1208bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1210 if (!NoInitialTextSection)
1217 AsmCond StartingCondState = TheCondState;
1227 ParseStatementInfo
Info(&AsmStrRewrites);
1228 bool HasError = parseStatement(Info,
nullptr);
1233 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1237 printPendingErrors();
1240 if (HasError && !getLexer().justConsumedEOL())
1241 eatToEndOfStatement();
1244 printPendingErrors();
1247 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1251 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1260 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1261 if (std::get<2>(LocSym)->isUndefined()) {
1264 CppHashInfo = std::get<1>(LocSym);
1265 printError(std::get<0>(LocSym),
"directional label undefined");
1272 if (!HadError && !NoFinalize)
1273 Out.
finish(Lexer.getLoc());
1278bool MasmParser::checkForValidSection() {
1279 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1280 getStreamer().getCurrentSectionOnly())) {
1282 return Error(getTok().getLoc(),
1283 "expected section directive before assembly directive");
1289void MasmParser::eatToEndOfStatement() {
1293 if (ParentIncludeLoc == SMLoc()) {
1297 EndStatementAtEOFStack.pop_back();
1298 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1309SmallVector<StringRef, 1>
1311 SmallVector<StringRef, 1> Refs;
1312 const char *
Start = getTok().getLoc().getPointer();
1313 while (Lexer.isNot(EndTok)) {
1316 if (ParentIncludeLoc == SMLoc()) {
1321 EndStatementAtEOFStack.pop_back();
1322 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1324 Start = getTok().getLoc().getPointer();
1334 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1336 for (StringRef S : Refs) {
1337 Str.append(S.str());
1342StringRef MasmParser::parseStringToEndOfStatement() {
1343 const char *
Start = getTok().getLoc().getPointer();
1348 const char *End = getTok().getLoc().getPointer();
1349 return StringRef(Start, End - Start);
1357bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1358 if (parseExpression(Res))
1360 EndLoc = Lexer.getTok().getEndLoc();
1361 return parseRParen();
1369bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1370 if (parseExpression(Res))
1372 EndLoc = getTok().getEndLoc();
1373 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1386bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1387 AsmTypeInfo *TypeInfo) {
1388 SMLoc FirstTokenLoc = getLexer().getLoc();
1390 switch (FirstTokenKind) {
1392 return TokError(
"unknown token in expression");
1398 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1406 if (parseIdentifier(Identifier)) {
1409 if (Lexer.getMAI().getDollarIsPC()) {
1416 EndLoc = FirstTokenLoc;
1419 return Error(FirstTokenLoc,
"invalid token in expression");
1424 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1430 if (
Identifier.equals_insensitive(
"imagerel")) {
1431 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1433 if (
const MCExpr *ModifiedRes =
1438 return Error(FirstTokenLoc,
"cannot apply 'imagerel' to this expression");
1443 bool Before =
Identifier.equals_insensitive(
"@b");
1446 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1456 return Error(getLexer().getLoc(),
"expected a symbol reference");
1461 if (
Split.second.empty()) {
1464 if (lookUpField(SymbolName,
Split.second, Info)) {
1465 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1466 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1467 lookUpField(
Base, Member, Info);
1478 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1479 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1481 : BuiltinIt->getValue();
1482 if (Symbol != BI_NO_SYMBOL) {
1483 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1493 if (VarIt != Variables.
end())
1504 DoInline = TV->inlineAssignedExpr();
1512 const MCExpr *SymRef =
1522 if (
Info.Type.Name.empty()) {
1524 if (TypeIt != KnownType.
end()) {
1525 Info.Type = TypeIt->second;
1529 *TypeInfo =
Info.Type;
1534 return TokError(
"literal value out of range for directive");
1536 int64_t
IntVal = getTok().getIntVal();
1538 EndLoc = Lexer.getTok().getEndLoc();
1544 SMLoc ValueLoc = getTok().getLoc();
1546 if (parseEscapedString(
Value))
1548 if (
Value.size() > 8)
1549 return Error(ValueLoc,
"literal value out of range");
1551 for (
const unsigned char CharVal :
Value)
1552 IntValue = (IntValue << 8) | CharVal;
1557 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1560 EndLoc = Lexer.getTok().getEndLoc();
1570 EndLoc = Lexer.getTok().getEndLoc();
1576 return parseParenExpr(Res, EndLoc);
1578 if (!PlatformParser->HasBracketExpressions())
1579 return TokError(
"brackets expression not supported on this target");
1581 return parseBracketExpr(Res, EndLoc);
1584 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1590 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1596 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1603bool MasmParser::parseExpression(
const MCExpr *&Res) {
1605 return parseExpression(Res, EndLoc);
1616 "Argument to the function cannot be a NULL value");
1618 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1619 (*CharPtr !=
'\0')) {
1620 if (*CharPtr ==
'!')
1624 if (*CharPtr ==
'>') {
1634 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1635 if (BracketContents[Pos] ==
'!')
1637 Res += BracketContents[Pos];
1652bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1655 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1656 parseBinOpRHS(1, Res, EndLoc))
1662 if (Res->evaluateAsAbsolute(
Value))
1668bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1670 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1673bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1676 SMLoc StartLoc = Lexer.getLoc();
1677 if (parseExpression(Expr))
1680 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1681 return Error(StartLoc,
"expected absolute expression");
1688 bool ShouldUseLogicalShr,
1689 bool EndExpressionAtGreater) {
1717 if (EndExpressionAtGreater)
1758 if (EndExpressionAtGreater)
1769 AngleBracketDepth > 0);
1774bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1776 SMLoc StartLoc = Lexer.getLoc();
1780 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1796 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1800 if (TokPrec < Precedence)
1807 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1813 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1814 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1827bool MasmParser::parseStatement(ParseStatementInfo &Info,
1828 MCAsmParserSemaCallback *SI) {
1829 assert(!hasPendingError() &&
"parseStatement started with pending error");
1835 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1836 getTok().getString().
front() ==
'\n')
1845 SMLoc ExpansionLoc = getTok().getLoc();
1852 AsmToken
ID = getTok();
1853 SMLoc IDLoc =
ID.getLoc();
1856 return parseCppHashLineFilenameComment(IDLoc);
1863 IDVal = getTok().getString();
1866 return Error(IDLoc,
"unexpected token at start of statement");
1867 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1868 if (!TheCondState.
Ignore) {
1870 return Error(IDLoc,
"unexpected token at start of statement");
1879 DirectiveKindMap.find(IDVal.
lower());
1880 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1882 : DirKindIt->getValue();
1888 return parseDirectiveIf(IDLoc, DirKind);
1890 return parseDirectiveIfb(IDLoc,
true);
1892 return parseDirectiveIfb(IDLoc,
false);
1894 return parseDirectiveIfdef(IDLoc,
true);
1896 return parseDirectiveIfdef(IDLoc,
false);
1898 return parseDirectiveIfidn(IDLoc,
false,
1901 return parseDirectiveIfidn(IDLoc,
false,
1904 return parseDirectiveIfidn(IDLoc,
true,
1907 return parseDirectiveIfidn(IDLoc,
true,
1911 return parseDirectiveElseIf(IDLoc, DirKind);
1913 return parseDirectiveElseIfb(IDLoc,
true);
1915 return parseDirectiveElseIfb(IDLoc,
false);
1917 return parseDirectiveElseIfdef(IDLoc,
true);
1919 return parseDirectiveElseIfdef(IDLoc,
false);
1921 return parseDirectiveElseIfidn(IDLoc,
false,
1924 return parseDirectiveElseIfidn(IDLoc,
false,
1927 return parseDirectiveElseIfidn(IDLoc,
true,
1930 return parseDirectiveElseIfidn(IDLoc,
true,
1933 return parseDirectiveElse(IDLoc);
1935 return parseDirectiveEndIf(IDLoc);
1940 if (TheCondState.
Ignore) {
1941 eatToEndOfStatement();
1951 if (checkForValidSection())
1959 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1967 if (ParsingMSInlineAsm && SI) {
1968 StringRef RewrittenLabel =
1969 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1971 "We should have an internal name here.");
1974 IDVal = RewrittenLabel;
1977 if (IDVal ==
"@@") {
2000 if (!getTargetParser().isParsingMSInlineAsm())
2010 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2015 if (DirKind != DK_NO_DIRECTIVE) {
2031 return parseDirectiveNestedEnds();
2036 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2039 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2045 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2047 "Should only return Failure iff there was an error");
2059 return parseDirectiveAscii(IDVal,
false);
2062 return parseDirectiveAscii(IDVal,
true);
2066 return parseDirectiveValue(IDVal, 1);
2070 return parseDirectiveValue(IDVal, 2);
2074 return parseDirectiveValue(IDVal, 4);
2077 return parseDirectiveValue(IDVal, 6);
2081 return parseDirectiveValue(IDVal, 8);
2083 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2085 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2087 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2090 return parseDirectiveNestedStruct(IDVal, DirKind);
2092 return parseDirectiveNestedEnds();
2094 return parseDirectiveAlign();
2096 return parseDirectiveEven();
2098 return parseDirectiveOrg();
2100 return parseDirectiveExtern();
2102 return parseDirectiveSymbolAttribute(
MCSA_Global);
2104 return parseDirectiveComm(
false);
2106 return parseDirectiveComment(IDLoc);
2108 return parseDirectiveInclude();
2110 return parseDirectiveRepeat(IDLoc, IDVal);
2112 return parseDirectiveWhile(IDLoc);
2114 return parseDirectiveFor(IDLoc, IDVal);
2116 return parseDirectiveForc(IDLoc, IDVal);
2118 Info.ExitValue =
"";
2119 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2121 Info.ExitValue =
"";
2122 return parseDirectiveEndMacro(IDVal);
2124 return parseDirectivePurgeMacro(IDLoc);
2126 return parseDirectiveEnd(IDLoc);
2128 return parseDirectiveError(IDLoc);
2130 return parseDirectiveErrorIfb(IDLoc,
true);
2132 return parseDirectiveErrorIfb(IDLoc,
false);
2134 return parseDirectiveErrorIfdef(IDLoc,
true);
2136 return parseDirectiveErrorIfdef(IDLoc,
false);
2138 return parseDirectiveErrorIfidn(IDLoc,
false,
2141 return parseDirectiveErrorIfidn(IDLoc,
false,
2144 return parseDirectiveErrorIfidn(IDLoc,
true,
2147 return parseDirectiveErrorIfidn(IDLoc,
true,
2150 return parseDirectiveErrorIfe(IDLoc,
true);
2152 return parseDirectiveErrorIfe(IDLoc,
false);
2154 return parseDirectiveRadix(IDLoc);
2156 return parseDirectiveEcho(IDLoc);
2159 return Error(IDLoc,
"unknown directive");
2163 auto IDIt = Structs.
find(IDVal.
lower());
2164 if (IDIt != Structs.
end())
2165 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2169 const AsmToken nextTok = getTok();
2170 const StringRef nextVal = nextTok.
getString();
2171 const SMLoc nextLoc = nextTok.
getLoc();
2173 const AsmToken afterNextTok = peekTok();
2184 getTargetParser().flushPendingInstructions(getStreamer());
2190 return parseDirectiveEnds(IDVal, IDLoc);
2195 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2197 if (Handler.first) {
2200 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2205 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2206 DirKind = (DirKindIt == DirectiveKindMap.end())
2208 : DirKindIt->getValue();
2215 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2217 Lex(DoNotExpandMacros);
2218 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2229 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2240 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2251 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2261 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2272 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2275 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2279 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2283 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2288 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2291 return parseDirectiveEnds(IDVal, IDLoc);
2294 return parseDirectiveMacro(IDVal, IDLoc);
2298 auto NextIt = Structs.
find(nextVal.
lower());
2299 if (NextIt != Structs.
end()) {
2301 return parseDirectiveNamedStructValue(NextIt->getValue(),
2302 nextVal, nextLoc, IDVal);
2306 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2307 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2308 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2311 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2312 return parseDirectiveMSAlign(IDLoc, Info);
2314 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2316 if (checkForValidSection())
2320 std::string OpcodeStr = IDVal.
lower();
2321 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2322 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2323 Info.ParsedOperands);
2324 Info.ParseError = ParseHadError;
2327 if (getShowParsedOperands()) {
2328 SmallString<256> Str;
2329 raw_svector_ostream OS(Str);
2330 OS <<
"parsed instruction: [";
2331 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2334 Info.ParsedOperands[i]->print(OS, MAI);
2342 if (hasPendingError() || ParseHadError)
2346 if (!ParseHadError) {
2348 if (getTargetParser().matchAndEmitInstruction(
2349 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2350 getTargetParser().isParsingMSInlineAsm()))
2357bool MasmParser::parseCurlyBlockScope(
2358 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2363 SMLoc StartLoc = Lexer.getLoc();
2376bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2381 "Lexing Cpp line comment: Expected Integer");
2382 int64_t LineNumber = getTok().getIntVal();
2385 "Lexing Cpp line comment: Expected String");
2386 StringRef
Filename = getTok().getString();
2394 CppHashInfo.Loc =
L;
2396 CppHashInfo.LineNumber = LineNumber;
2397 CppHashInfo.Buf = CurBuffer;
2398 if (FirstCppHashFilename.
empty())
2405void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2406 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2407 raw_ostream &OS =
errs();
2410 SMLoc DiagLoc = Diag.
getLoc();
2412 unsigned CppHashBuf =
2413 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2417 if (!Parser->SavedDiagHandler)
2423 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2424 DiagBuf != CppHashBuf) {
2425 if (Parser->SavedDiagHandler)
2426 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2428 Diag.
print(
nullptr, OS);
2435 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2438 int CppHashLocLineNo =
2439 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2441 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2447 if (Parser->SavedDiagHandler)
2448 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2450 NewDiag.print(
nullptr, OS);
2456 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2459bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2462 const std::vector<std::string> &Locals, SMLoc L) {
2464 if (NParameters !=
A.size())
2465 return Error(L,
"Wrong number of arguments");
2466 StringMap<std::string> LocalSymbols;
2469 for (StringRef
Local : Locals) {
2470 raw_string_ostream LocalName(Name);
2477 std::optional<char> CurrentQuote;
2478 while (!Body.
empty()) {
2480 std::size_t End = Body.
size(), Pos = 0;
2481 std::size_t IdentifierPos = End;
2482 for (; Pos != End; ++Pos) {
2485 if (Body[Pos] ==
'&')
2490 if (IdentifierPos == End)
2491 IdentifierPos = Pos;
2493 IdentifierPos = End;
2497 if (!CurrentQuote) {
2498 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2499 CurrentQuote = Body[Pos];
2500 }
else if (Body[Pos] == CurrentQuote) {
2501 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2506 CurrentQuote.reset();
2510 if (IdentifierPos != End) {
2513 Pos = IdentifierPos;
2514 IdentifierPos = End;
2518 OS << Body.
slice(0, Pos);
2525 bool InitialAmpersand = (Body[
I] ==
'&');
2526 if (InitialAmpersand) {
2533 const char *Begin = Body.
data() + Pos;
2535 const std::string ArgumentLower =
Argument.lower();
2539 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2542 if (Index == NParameters) {
2543 if (InitialAmpersand)
2545 auto it = LocalSymbols.
find(ArgumentLower);
2546 if (it != LocalSymbols.
end())
2552 for (
const AsmToken &Token :
A[Index]) {
2562 OS << Token.getIntVal();
2564 OS << Token.getString();
2568 if (Pos < End && Body[Pos] ==
'&') {
2579bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2580 MCAsmMacroArgument &MA,
2583 if (Lexer.isNot(EndTok)) {
2584 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2585 for (StringRef S : Str) {
2592 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2594 const char *StrChar = StrLoc.
getPointer() + 1;
2595 const char *EndChar = EndLoc.
getPointer() - 1;
2596 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2603 unsigned ParenLevel = 0;
2607 return TokError(
"unexpected token");
2624 MA.push_back(getTok());
2628 if (ParenLevel != 0)
2629 return TokError(
"unbalanced parentheses in argument");
2631 if (MA.empty() && MP) {
2633 return TokError(
"missing value for required parameter '" + MP->
Name +
2643bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2644 MCAsmMacroArguments &
A,
2646 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2647 bool NamedParametersFound =
false;
2648 SmallVector<SMLoc, 4> FALocs;
2650 A.resize(NParameters);
2651 FALocs.
resize(NParameters);
2656 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2658 SMLoc IDLoc = Lexer.getLoc();
2659 MCAsmMacroParameter FA;
2662 if (parseIdentifier(FA.
Name))
2663 return Error(IDLoc,
"invalid argument identifier for formal argument");
2666 return TokError(
"expected '=' after formal parameter identifier");
2670 NamedParametersFound =
true;
2673 if (NamedParametersFound && FA.
Name.
empty())
2674 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2678 assert(M &&
"expected macro to be defined");
2680 for (FAI = 0; FAI < NParameters; ++FAI)
2681 if (
M->Parameters[FAI].Name == FA.
Name)
2684 if (FAI >= NParameters) {
2685 return Error(IDLoc,
"parameter named '" + FA.
Name +
2686 "' does not exist for macro '" +
M->Name +
"'");
2690 const MCAsmMacroParameter *MP =
nullptr;
2691 if (M && PI < NParameters)
2692 MP = &
M->Parameters[PI];
2694 SMLoc StrLoc = Lexer.getLoc();
2697 const MCExpr *AbsoluteExp;
2701 if (parseExpression(AbsoluteExp, EndLoc))
2703 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2704 getStreamer().getAssemblerPtr()))
2705 return Error(StrLoc,
"expected absolute expression");
2709 StringRef(StrChar, EndChar - StrChar),
Value);
2710 FA.
Value.push_back(newToken);
2711 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2713 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2718 if (!FA.
Value.empty()) {
2723 if (FALocs.
size() <= PI)
2726 FALocs[PI] = Lexer.getLoc();
2732 if (Lexer.is(EndTok)) {
2734 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2736 if (
M->Parameters[FAI].Required) {
2737 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2738 "missing value for required parameter "
2740 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2744 if (!
M->Parameters[FAI].Value.empty())
2745 A[FAI] =
M->Parameters[FAI].Value;
2755 return TokError(
"too many positional arguments");
2758bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2763 if (ActiveMacros.size() == MaxNestingDepth) {
2764 std::ostringstream MaxNestingDepthError;
2765 MaxNestingDepthError <<
"macros cannot be nested more than "
2766 << MaxNestingDepth <<
" levels deep."
2767 <<
" Use -asm-macro-max-nesting-depth to increase "
2769 return TokError(MaxNestingDepthError.str());
2772 MCAsmMacroArguments
A;
2773 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2778 SmallString<256> Buf;
2779 StringRef Body =
M->Body;
2780 raw_svector_ostream OS(Buf);
2782 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2789 std::unique_ptr<MemoryBuffer> Instantiation =
2794 MacroInstantiation *
MI =
new MacroInstantiation{
2795 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2796 ActiveMacros.push_back(
MI);
2798 ++NumOfMacroInstantiations;
2803 EndStatementAtEOFStack.push_back(
true);
2809void MasmParser::handleMacroExit() {
2811 EndStatementAtEOFStack.pop_back();
2812 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2813 EndStatementAtEOFStack.back());
2817 delete ActiveMacros.back();
2818 ActiveMacros.pop_back();
2821bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2823 return Error(NameLoc,
"cannot invoke macro procedure as function");
2826 "' requires arguments in parentheses") ||
2831 std::string ExitValue;
2834 ParseStatementInfo
Info(&AsmStrRewrites);
2835 bool HasError = parseStatement(Info,
nullptr);
2837 if (!HasError &&
Info.ExitValue) {
2838 ExitValue = std::move(*
Info.ExitValue);
2845 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2849 printPendingErrors();
2852 if (HasError && !getLexer().justConsumedEOL())
2853 eatToEndOfStatement();
2858 std::unique_ptr<MemoryBuffer> MacroValue =
2866 EndStatementAtEOFStack.push_back(
false);
2875bool MasmParser::parseIdentifier(StringRef &Res,
2876 IdentifierPositionKind Position) {
2883 SMLoc PrefixLoc = getLexer().getLoc();
2887 AsmToken nextTok = peekTok(
false);
2900 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2908 Res = getTok().getIdentifier();
2912 ExpandKind ExpandNextToken = ExpandMacros;
2913 if (Position == StartOfStatement &&
2914 StringSwitch<bool>(Res)
2915 .CaseLower(
"echo",
true)
2916 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2918 ExpandNextToken = DoNotExpandMacros;
2920 Lex(ExpandNextToken);
2930bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2931 DirectiveKind DirKind, SMLoc NameLoc) {
2932 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2933 if (BuiltinIt != BuiltinSymbolMap.end())
2934 return Error(NameLoc,
"cannot redefine a built-in symbol");
2937 if (Var.Name.empty()) {
2941 SMLoc StartLoc = Lexer.getLoc();
2947 if (!parseTextList(
Value, IDVal))
2948 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2949 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2956 if (!parseAngleBracketString(
Value))
2957 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2967 if (parseExpression(Expr, EndLoc))
2968 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2969 StringRef ExprAsString = StringRef(
2973 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2974 if (DirKind == DK_ASSIGN)
2977 "expected absolute expression; not all symbols have known values",
2978 {StartLoc, EndLoc});
2981 return setTextVariable(Var, Name, ExprAsString, NameLoc,
2982 Variable::REDEFINABLE);
2985 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
2986 const MCConstantExpr *PrevValue =
2990 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
2991 switch (Var.Redefinable) {
2992 case Variable::NOT_REDEFINABLE:
2993 return Error(getTok().getLoc(),
"invalid variable redefinition");
2994 case Variable::WARN_ON_REDEFINITION:
2995 if (
Warning(NameLoc,
"redefining '" + Name +
2996 "', already defined on the command line"))
3005 Var.TextValue.clear();
3006 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3009 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3011 Sym->setExternal(
false);
3016bool MasmParser::parseEscapedString(std::string &
Data) {
3021 char Quote = getTok().getString().front();
3022 StringRef Str = getTok().getStringContents();
3023 Data.reserve(Str.size());
3024 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3025 Data.push_back(Str[i]);
3026 if (Str[i] == Quote) {
3030 if (i + 1 == Str.size())
3031 return Error(getTok().getLoc(),
"missing quotation mark in string");
3032 if (Str[i + 1] == Quote)
3041bool MasmParser::parseAngleBracketString(std::string &
Data) {
3042 SMLoc EndLoc, StartLoc = getTok().getLoc();
3044 const char *StartChar = StartLoc.
getPointer() + 1;
3045 const char *EndChar = EndLoc.
getPointer() - 1;
3046 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3057bool MasmParser::parseTextItem(std::string &
Data) {
3058 switch (getTok().getKind()) {
3065 Data = std::to_string(Res);
3072 return parseAngleBracketString(
Data);
3076 SMLoc StartLoc = getTok().getLoc();
3077 if (parseIdentifier(ID))
3081 bool Expanded =
false;
3084 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3085 if (BuiltinIt != BuiltinSymbolMap.end()) {
3086 std::optional<std::string> BuiltinText =
3087 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3092 Data = std::move(*BuiltinText);
3099 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3100 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3102 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID,
Data)) {
3111 auto VarIt = Variables.
find(
ID.lower());
3112 if (VarIt != Variables.
end()) {
3113 const Variable &Var = VarIt->getValue();
3118 Data = Var.TextValue;
3140bool MasmParser::parseTextList(std::string &Result, StringRef IDVal) {
3141 std::string TextItem;
3142 if (parseTextItem(TextItem))
3146 Lex(DoNotExpandMacros);
3148 Lex(DoNotExpandMacros);
3149 if (parseTextItem(TextItem))
3150 return TokError(
"expected text item in '" + Twine(IDVal) +
"' directive");
3157bool MasmParser::setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
3159 Variable::RedefinableKind Redefinable) {
3160 if (!Var.IsText || Var.TextValue !=
Value) {
3161 switch (Var.Redefinable) {
3162 case Variable::NOT_REDEFINABLE:
3163 return Error(getTok().getLoc(),
"invalid variable redefinition");
3164 case Variable::WARN_ON_REDEFINITION:
3165 if (
Warning(NameLoc,
"redefining '" + Name +
3166 "', already defined on the command line"))
3174 Var.TextValue =
Value.str();
3175 Var.Redefinable = Redefinable;
3181bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3182 auto parseOp = [&]() ->
bool {
3184 if (checkForValidSection() || parseEscapedString(
Data))
3186 getStreamer().emitBytes(
Data);
3188 getStreamer().emitBytes(StringRef(
"\0", 1));
3192 if (parseMany(parseOp))
3193 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3197bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3201 int64_t IntValue = MCE->getValue();
3203 return Error(MCE->getLoc(),
"out of range literal value");
3204 getStreamer().emitIntValue(IntValue,
Size);
3209 getStreamer().emitIntValue(0,
Size);
3217bool MasmParser::parseScalarInitializer(
unsigned Size,
3218 SmallVectorImpl<const MCExpr *> &
Values,
3219 unsigned StringPadLength) {
3222 if (parseEscapedString(
Value))
3225 for (
const unsigned char CharVal :
Value)
3229 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3232 const MCExpr *
Value;
3233 if (parseExpression(
Value))
3236 getTok().getString().equals_insensitive(
"dup")) {
3241 "cannot repeat value a non-constant number of times");
3242 const int64_t Repetitions = MCE->
getValue();
3243 if (Repetitions < 0)
3245 "cannot repeat value a negative number of times");
3249 "parentheses required for 'dup' contents") ||
3250 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3253 for (
int i = 0; i < Repetitions; ++i)
3262bool MasmParser::parseScalarInstList(
unsigned Size,
3263 SmallVectorImpl<const MCExpr *> &
Values,
3265 while (getTok().
isNot(EndToken) &&
3278bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3280 if (checkForValidSection() || parseScalarInstList(
Size,
Values))
3292bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3293 StructInfo &
Struct = StructInProgress.
back();
3295 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3299 if (parseScalarInstList(
Size, IntInfo.Values))
3302 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3303 Field.LengthOf = IntInfo.Values.size();
3306 Struct.NextOffset = FieldEnd;
3314bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3315 if (StructInProgress.
empty()) {
3317 if (emitIntegralValues(
Size))
3318 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3319 }
else if (addIntegralField(
"",
Size)) {
3320 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3328bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3329 StringRef Name, SMLoc NameLoc) {
3330 if (StructInProgress.
empty()) {
3333 getStreamer().emitLabel(Sym);
3336 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3344 }
else if (addIntegralField(Name,
Size)) {
3345 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3351bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3357 SignLoc = getLexer().getLoc();
3361 SignLoc = getLexer().getLoc();
3366 return TokError(Lexer.getErr());
3369 return TokError(
"unexpected token in directive");
3373 StringRef IDVal = getTok().getString();
3382 return TokError(
"invalid floating point literal");
3386 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3387 if (SizeInBits != (IDVal.
size() << 2))
3388 return TokError(
"invalid floating point literal");
3393 Res = APInt(SizeInBits, IDVal, 16);
3395 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3398 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3400 return TokError(
"invalid floating point literal");
3408 Res =
Value.bitcastToAPInt();
3413bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3414 SmallVectorImpl<APInt> &ValuesAsInt,
3416 while (getTok().
isNot(EndToken) ||
3419 const AsmToken NextTok = peekTok();
3422 const MCExpr *
Value;
3428 "cannot repeat value a non-constant number of times");
3429 const int64_t Repetitions = MCE->
getValue();
3430 if (Repetitions < 0)
3432 "cannot repeat value a negative number of times");
3436 "parentheses required for 'dup' contents") ||
3437 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3440 for (
int i = 0; i < Repetitions; ++i)
3441 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3444 if (parseRealValue(Semantics, AsInt))
3459bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3461 if (checkForValidSection())
3465 if (parseRealInstList(Semantics, ValuesAsInt))
3468 for (
const APInt &AsInt : ValuesAsInt) {
3469 getStreamer().emitIntValue(AsInt);
3472 *
Count = ValuesAsInt.size();
3477bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3479 StructInfo &
Struct = StructInProgress.
back();
3481 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3485 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3488 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3489 Field.LengthOf = RealInfo.AsIntValues.size();
3494 Struct.NextOffset = FieldEnd;
3502bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3503 const fltSemantics &Semantics,
3505 if (StructInProgress.
empty()) {
3507 if (emitRealValues(Semantics))
3508 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3509 }
else if (addRealField(
"", Semantics,
Size)) {
3510 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3517bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3518 const fltSemantics &Semantics,
3519 unsigned Size, StringRef Name,
3521 if (StructInProgress.
empty()) {
3524 getStreamer().emitLabel(Sym);
3526 if (emitRealValues(Semantics, &
Count))
3527 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3535 }
else if (addRealField(Name, Semantics,
Size)) {
3536 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3541bool MasmParser::parseOptionalAngleBracketOpen() {
3542 const AsmToken Tok = getTok();
3544 AngleBracketDepth++;
3548 AngleBracketDepth++;
3552 AngleBracketDepth++;
3559bool MasmParser::parseAngleBracketClose(
const Twine &
Msg) {
3560 const AsmToken Tok = getTok();
3566 AngleBracketDepth--;
3570bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3571 const IntFieldInfo &Contents,
3572 FieldInitializer &Initializer) {
3573 SMLoc Loc = getTok().getLoc();
3578 return Error(Loc,
"Cannot initialize scalar field with array value");
3582 }
else if (parseOptionalAngleBracketOpen()) {
3584 return Error(Loc,
"Cannot initialize scalar field with array value");
3586 parseAngleBracketClose())
3588 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3589 return Error(Loc,
"Cannot initialize array field with scalar value");
3590 }
else if (parseScalarInitializer(
Field.Type,
Values,
3596 return Error(Loc,
"Initializer too long for field; expected at most " +
3597 std::to_string(
Field.LengthOf) +
" elements, got " +
3598 std::to_string(
Values.size()));
3601 Values.append(Contents.Values.begin() +
Values.size(), Contents.Values.end());
3603 Initializer = FieldInitializer(std::move(
Values));
3607bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3608 const RealFieldInfo &Contents,
3609 FieldInitializer &Initializer) {
3610 const fltSemantics *Semantics;
3611 switch (
Field.Type) {
3613 Semantics = &APFloat::IEEEsingle();
3616 Semantics = &APFloat::IEEEdouble();
3619 Semantics = &APFloat::x87DoubleExtended();
3625 SMLoc Loc = getTok().getLoc();
3629 if (
Field.LengthOf == 1)
3630 return Error(Loc,
"Cannot initialize scalar field with array value");
3634 }
else if (parseOptionalAngleBracketOpen()) {
3635 if (
Field.LengthOf == 1)
3636 return Error(Loc,
"Cannot initialize scalar field with array value");
3638 parseAngleBracketClose())
3640 }
else if (
Field.LengthOf > 1) {
3641 return Error(Loc,
"Cannot initialize array field with scalar value");
3644 if (parseRealValue(*Semantics, AsIntValues.
back()))
3648 if (AsIntValues.
size() >
Field.LengthOf) {
3649 return Error(Loc,
"Initializer too long for field; expected at most " +
3650 std::to_string(
Field.LengthOf) +
" elements, got " +
3651 std::to_string(AsIntValues.
size()));
3654 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3655 Contents.AsIntValues.end());
3657 Initializer = FieldInitializer(std::move(AsIntValues));
3661bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3662 const StructFieldInfo &Contents,
3663 FieldInitializer &Initializer) {
3664 SMLoc Loc = getTok().getLoc();
3666 std::vector<StructInitializer> Initializers;
3667 if (
Field.LengthOf > 1) {
3669 if (parseStructInstList(Contents.Structure, Initializers,
3673 }
else if (parseOptionalAngleBracketOpen()) {
3674 if (parseStructInstList(Contents.Structure, Initializers,
3676 parseAngleBracketClose())
3679 return Error(Loc,
"Cannot initialize array field with scalar value");
3682 Initializers.emplace_back();
3683 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3687 if (Initializers.size() >
Field.LengthOf) {
3688 return Error(Loc,
"Initializer too long for field; expected at most " +
3689 std::to_string(
Field.LengthOf) +
" elements, got " +
3690 std::to_string(Initializers.size()));
3694 Initializers.size()));
3696 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3700bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3701 FieldInitializer &Initializer) {
3702 switch (
Field.Contents.FT) {
3704 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3706 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3708 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3713bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3714 StructInitializer &Initializer) {
3715 const AsmToken FirstToken = getTok();
3717 std::optional<AsmToken::TokenKind> EndToken;
3720 }
else if (parseOptionalAngleBracketOpen()) {
3722 AngleBracketDepth++;
3729 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3732 auto &FieldInitializers = Initializer.FieldInitializers;
3733 size_t FieldIndex = 0;
3736 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3737 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3741 FieldInitializers.push_back(
Field.Contents);
3745 FieldInitializers.emplace_back(
Field.Contents.FT);
3746 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3750 SMLoc CommaLoc = getTok().getLoc();
3753 if (FieldIndex == Structure.Fields.size())
3754 return Error(CommaLoc,
"'" + Structure.Name +
3755 "' initializer initializes too many fields");
3761 FieldInitializers.push_back(
Field.Contents);
3765 return parseAngleBracketClose();
3767 return parseToken(*EndToken);
3773bool MasmParser::parseStructInstList(
3774 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3776 while (getTok().
isNot(EndToken) ||
3779 const AsmToken NextTok = peekTok();
3782 const MCExpr *
Value;
3788 "cannot repeat value a non-constant number of times");
3789 const int64_t Repetitions = MCE->
getValue();
3790 if (Repetitions < 0)
3792 "cannot repeat value a negative number of times");
3794 std::vector<StructInitializer> DuplicatedValues;
3796 "parentheses required for 'dup' contents") ||
3797 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3800 for (
int i = 0; i < Repetitions; ++i)
3803 Initializers.emplace_back();
3804 if (parseStructInitializer(Structure, Initializers.back()))
3817bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3818 const IntFieldInfo &Contents) {
3820 for (
const MCExpr *
Value : Contents.Values) {
3827bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3828 const RealFieldInfo &Contents) {
3829 for (
const APInt &AsInt : Contents.AsIntValues) {
3836bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3837 const StructFieldInfo &Contents) {
3838 for (
const auto &Initializer : Contents.Initializers) {
3840 for (
const auto &SubField : Contents.Structure.Fields) {
3841 getStreamer().emitZeros(SubField.Offset -
Offset);
3842 Offset = SubField.Offset + SubField.SizeOf;
3843 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3849bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3850 switch (
Field.Contents.FT) {
3852 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3854 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3856 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3861bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3862 const IntFieldInfo &Contents,
3863 const IntFieldInfo &Initializer) {
3864 for (
const auto &
Value : Initializer.Values) {
3869 for (
const auto &
Value :
3877bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3878 const RealFieldInfo &Contents,
3879 const RealFieldInfo &Initializer) {
3880 for (
const auto &AsInt : Initializer.AsIntValues) {
3885 for (
const auto &AsInt :
3893bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3894 const StructFieldInfo &Contents,
3895 const StructFieldInfo &Initializer) {
3896 for (
const auto &Init : Initializer.Initializers) {
3897 if (emitStructInitializer(Contents.Structure, Init))
3902 Initializer.Initializers.size())) {
3903 if (emitStructInitializer(Contents.Structure, Init))
3909bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3910 const FieldInitializer &Initializer) {
3911 switch (
Field.Contents.FT) {
3913 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3914 Initializer.IntInfo);
3916 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3917 Initializer.RealInfo);
3919 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3920 Initializer.StructInfo);
3925bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3926 const StructInitializer &Initializer) {
3927 if (!Structure.Initializable)
3928 return Error(getLexer().getLoc(),
3929 "cannot initialize a value of type '" + Structure.Name +
3930 "'; 'org' was used in the type's declaration");
3932 for (
const auto &Init : Initializer.FieldInitializers) {
3933 const auto &
Field = Structure.Fields[
Index++];
3936 if (emitFieldInitializer(
Field, Init))
3941 Structure.Fields, Initializer.FieldInitializers.size())) {
3944 if (emitFieldValue(
Field))
3948 if (
Offset != Structure.Size)
3949 getStreamer().emitZeros(Structure.Size -
Offset);
3954bool MasmParser::emitStructValues(
const StructInfo &Structure,
3956 std::vector<StructInitializer> Initializers;
3957 if (parseStructInstList(Structure, Initializers))
3960 for (
const auto &Initializer : Initializers) {
3961 if (emitStructInitializer(Structure, Initializer))
3966 *
Count = Initializers.size();
3971bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3972 StructInfo &OwningStruct = StructInProgress.
back();
3974 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3975 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3977 StructInfo.Structure = Structure;
3978 Field.Type = Structure.Size;
3980 if (parseStructInstList(Structure, StructInfo.Initializers))
3983 Field.LengthOf = StructInfo.Initializers.size();
3987 if (!OwningStruct.IsUnion) {
3988 OwningStruct.NextOffset = FieldEnd;
3990 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3998bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3999 StringRef Directive, SMLoc DirLoc) {
4000 if (StructInProgress.
empty()) {
4001 if (emitStructValues(Structure))
4003 }
else if (addStructField(
"", Structure)) {
4004 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4012bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
4013 StringRef Directive,
4014 SMLoc DirLoc, StringRef Name) {
4015 if (StructInProgress.
empty()) {
4018 getStreamer().emitLabel(Sym);
4020 if (emitStructValues(Structure, &
Count))
4023 Type.Name = Structure.Name;
4025 Type.ElementSize = Structure.Size;
4028 }
else if (addStructField(Name, Structure)) {
4029 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4041bool MasmParser::parseDirectiveStruct(StringRef Directive,
4042 DirectiveKind DirKind, StringRef Name,
4046 AsmToken NextTok = getTok();
4047 int64_t AlignmentValue = 1;
4050 parseAbsoluteExpression(AlignmentValue)) {
4051 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4055 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4056 std::to_string(AlignmentValue));
4062 QualifierLoc = getTok().getLoc();
4063 if (parseIdentifier(Qualifier))
4064 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4065 if (!
Qualifier.equals_insensitive(
"nonunique"))
4066 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4068 "' directive; expected none or NONUNIQUE");
4072 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4074 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4082bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4083 DirectiveKind DirKind) {
4084 if (StructInProgress.
empty())
4085 return TokError(
"missing name in top-level '" + Twine(Directive) +
4090 Name = getTok().getIdentifier();
4094 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4098 StructInProgress.
reserve(StructInProgress.
size() + 1);
4099 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4100 StructInProgress.
back().Alignment);
4104bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4105 if (StructInProgress.
empty())
4106 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4107 if (StructInProgress.
size() > 1)
4108 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4109 if (StructInProgress.
back().Name.compare_insensitive(Name))
4110 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4111 StructInProgress.
back().Name +
"'");
4112 StructInfo Structure = StructInProgress.
pop_back_val();
4116 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4117 Structs[
Name.lower()] = std::move(Structure);
4120 return addErrorSuffix(
" in ENDS directive");
4125bool MasmParser::parseDirectiveNestedEnds() {
4126 if (StructInProgress.
empty())
4127 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4128 if (StructInProgress.
size() == 1)
4129 return TokError(
"missing name in top-level ENDS directive");
4132 return addErrorSuffix(
" in nested ENDS directive");
4134 StructInfo Structure = StructInProgress.
pop_back_val();
4136 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4138 StructInfo &ParentStruct = StructInProgress.
back();
4139 if (Structure.Name.
empty()) {
4142 const size_t OldFields = ParentStruct.Fields.size();
4143 ParentStruct.Fields.insert(
4144 ParentStruct.Fields.end(),
4145 std::make_move_iterator(Structure.Fields.begin()),
4146 std::make_move_iterator(Structure.Fields.end()));
4147 for (
const auto &FieldByName : Structure.FieldsByName) {
4148 ParentStruct.FieldsByName[FieldByName.getKey()] =
4149 FieldByName.getValue() + OldFields;
4152 unsigned FirstFieldOffset = 0;
4153 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4155 ParentStruct.NextOffset,
4156 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4159 if (ParentStruct.IsUnion) {
4160 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4165 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4166 if (!ParentStruct.IsUnion) {
4167 ParentStruct.NextOffset = StructureEnd;
4169 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4172 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4173 Structure.AlignmentSize);
4174 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4175 Field.Type = Structure.Size;
4177 Field.SizeOf = Structure.Size;
4180 if (!ParentStruct.IsUnion) {
4181 ParentStruct.NextOffset = StructureEnd;
4183 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4185 StructInfo.Structure = Structure;
4186 StructInfo.Initializers.emplace_back();
4187 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4188 for (
const auto &SubField : Structure.Fields) {
4189 FieldInitializers.push_back(SubField.Contents);
4198bool MasmParser::parseDirectiveOrg() {
4200 SMLoc OffsetLoc = Lexer.getLoc();
4201 if (checkForValidSection() || parseExpression(
Offset))
4204 return addErrorSuffix(
" in 'org' directive");
4206 if (StructInProgress.
empty()) {
4208 if (checkForValidSection())
4209 return addErrorSuffix(
" in 'org' directive");
4211 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4214 StructInfo &Structure = StructInProgress.
back();
4216 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4217 return Error(OffsetLoc,
4218 "expected absolute expression in 'org' directive");
4222 "expected non-negative value in struct's 'org' directive; was " +
4223 std::to_string(OffsetRes));
4224 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4227 Structure.Initializable =
false;
4233bool MasmParser::emitAlignTo(int64_t Alignment) {
4234 if (StructInProgress.
empty()) {
4236 if (checkForValidSection())
4241 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4243 getStreamer().emitCodeAlignment(
Align(Alignment),
4244 getTargetParser().getSTI(),
4248 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4254 StructInfo &Structure = StructInProgress.
back();
4255 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4263bool MasmParser::parseDirectiveAlign() {
4264 SMLoc AlignmentLoc = getLexer().getLoc();
4270 "align directive with no operand is ignored") &&
4273 if (parseAbsoluteExpression(Alignment) || parseEOL())
4274 return addErrorSuffix(
" in align directive");
4277 bool ReturnVal =
false;
4284 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4285 std::to_string(Alignment));
4287 if (emitAlignTo(Alignment))
4288 ReturnVal |= addErrorSuffix(
" in align directive");
4295bool MasmParser::parseDirectiveEven() {
4296 if (parseEOL() || emitAlignTo(2))
4297 return addErrorSuffix(
" in even directive");
4308bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4312 return Error(Lexer.getLoc(),
4313 "Vararg parameter '" +
Parameters.back().Name +
4314 "' should be last in the list of parameters");
4318 return TokError(
"expected identifier in 'macro' directive");
4321 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4322 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4323 return TokError(
"macro '" + Name +
"' has multiple parameters"
4333 ParamLoc = Lexer.getLoc();
4334 if (parseMacroArgument(
nullptr,
Parameter.Value))
4340 QualLoc = Lexer.getLoc();
4341 if (parseIdentifier(Qualifier))
4342 return Error(QualLoc,
"missing parameter qualifier for "
4344 Parameter.Name +
"' in macro '" + Name +
4347 if (
Qualifier.equals_insensitive(
"req"))
4349 else if (
Qualifier.equals_insensitive(
"vararg"))
4352 return Error(QualLoc,
4353 Qualifier +
" is not a valid parameter qualifier for '" +
4354 Parameter.Name +
"' in macro '" + Name +
"'");
4367 std::vector<std::string>
Locals;
4369 getTok().getIdentifier().equals_insensitive(
"local")) {
4374 if (parseIdentifier(ID))
4386 AsmToken EndToken, StartToken = getTok();
4387 unsigned MacroDepth = 0;
4388 bool IsMacroFunction =
false;
4398 return Error(NameLoc,
"no matching 'endm' in definition");
4403 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4404 if (MacroDepth == 0) {
4405 EndToken = getTok();
4408 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4415 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4417 IsMacroFunction =
true;
4419 }
else if (isMacroLikeDirective()) {
4427 eatToEndOfStatement();
4431 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4436 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4437 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4447bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4448 StringRef Directive,
4449 std::string &
Value) {
4450 SMLoc EndLoc = getTok().getLoc();
4452 return Error(EndLoc,
4453 "unable to parse text item in '" + Directive +
"' directive");
4454 eatToEndOfStatement();
4456 if (!isInsideMacroInstantiation())
4457 return TokError(
"unexpected '" + Directive +
"' in file, "
4458 "no current macro definition");
4461 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4462 TheCondState = TheCondStack.back();
4463 TheCondStack.pop_back();
4472bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4474 return TokError(
"unexpected token in '" + Directive +
"' directive");
4478 if (isInsideMacroInstantiation()) {
4485 return TokError(
"unexpected '" + Directive +
"' in file, "
4486 "no current macro definition");
4491bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4495 if (parseTokenLoc(NameLoc) ||
4496 check(parseIdentifier(Name), NameLoc,
4497 "expected identifier in 'purge' directive"))
4501 <<
"Un-defining macro: " << Name <<
"\n");
4503 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4514bool MasmParser::parseDirectiveExtern() {
4516 auto parseOp = [&]() ->
bool {
4518 SMLoc NameLoc = getTok().getLoc();
4520 return Error(NameLoc,
"expected name");
4525 SMLoc TypeLoc = getTok().getLoc();
4526 if (parseIdentifier(TypeName))
4527 return Error(TypeLoc,
"expected type");
4528 if (!
TypeName.equals_insensitive(
"proc")) {
4530 if (lookUpType(TypeName,
Type))
4531 return Error(TypeLoc,
"unrecognized type");
4535 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4536 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4541 if (parseMany(parseOp))
4542 return addErrorSuffix(
" in directive 'extern'");
4548bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4549 auto parseOp = [&]() ->
bool {
4550 SMLoc Loc = getTok().getLoc();
4553 return Error(Loc,
"expected identifier");
4557 return Error(Loc,
"non-local symbol required");
4559 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4560 return Error(Loc,
"unable to emit symbol attribute");
4564 if (parseMany(parseOp))
4565 return addErrorSuffix(
" in directive");
4571bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4572 if (checkForValidSection())
4575 SMLoc IDLoc = getLexer().getLoc();
4578 return TokError(
"expected identifier in directive");
4581 return TokError(
"unexpected token in directive");
4585 SMLoc SizeLoc = getLexer().getLoc();
4586 if (parseAbsoluteExpression(
Size))
4589 int64_t Pow2Alignment = 0;
4590 SMLoc Pow2AlignmentLoc;
4593 Pow2AlignmentLoc = getLexer().getLoc();
4594 if (parseAbsoluteExpression(Pow2Alignment))
4599 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4602 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4605 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4606 Pow2Alignment =
Log2_64(Pow2Alignment);
4616 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4617 "be less than zero");
4622 if (Pow2Alignment < 0)
4623 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4624 "alignment, can't be less than zero");
4628 return Error(IDLoc,
"invalid symbol redefinition");
4632 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4633 Align(1ULL << Pow2Alignment));
4637 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4645bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4647 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4648 assert(DelimiterEnd != std::string::npos);
4649 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4650 if (Delimiter.
empty())
4651 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4654 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4664bool MasmParser::parseDirectiveInclude() {
4667 SMLoc IncludeLoc = getTok().getLoc();
4669 if (parseAngleBracketString(
Filename))
4671 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4673 "unexpected token in 'include' directive") ||
4676 check(enterIncludeFile(
Filename), IncludeLoc,
4677 "Could not find include file '" +
Filename +
"'"))
4685bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4686 TheCondStack.push_back(TheCondState);
4688 if (TheCondState.
Ignore) {
4689 eatToEndOfStatement();
4692 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4701 ExprValue = ExprValue == 0;
4705 TheCondState.
CondMet = ExprValue;
4714bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4715 TheCondStack.push_back(TheCondState);
4718 if (TheCondState.
Ignore) {
4719 eatToEndOfStatement();
4722 if (parseTextItem(Str))
4723 return TokError(
"expected text item parameter for 'ifb' directive");
4728 TheCondState.
CondMet = ExpectBlank == Str.empty();
4737bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4738 bool CaseInsensitive) {
4739 std::string String1, String2;
4741 if (parseTextItem(String1)) {
4743 return TokError(
"expected text item parameter for 'ifidn' directive");
4744 return TokError(
"expected text item parameter for 'ifdif' directive");
4750 "expected comma after first string for 'ifidn' directive");
4751 return TokError(
"expected comma after first string for 'ifdif' directive");
4755 if (parseTextItem(String2)) {
4757 return TokError(
"expected text item parameter for 'ifidn' directive");
4758 return TokError(
"expected text item parameter for 'ifdif' directive");
4761 TheCondStack.push_back(TheCondState);
4763 if (CaseInsensitive)
4765 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4767 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4776bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4777 TheCondStack.push_back(TheCondState);
4780 if (TheCondState.
Ignore) {
4781 eatToEndOfStatement();
4783 bool is_defined =
false;
4785 SMLoc StartLoc, EndLoc;
4787 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4790 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4794 if (BuiltinSymbolMap.contains(
Name.lower())) {
4804 TheCondState.
CondMet = (is_defined == expect_defined);
4813bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4814 DirectiveKind DirKind) {
4817 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4818 " .if or an .elseif");
4821 bool LastIgnoreState =
false;
4822 if (!TheCondStack.empty())
4823 LastIgnoreState = TheCondStack.back().Ignore;
4824 if (LastIgnoreState || TheCondState.
CondMet) {
4825 TheCondState.
Ignore =
true;
4826 eatToEndOfStatement();
4829 if (parseAbsoluteExpression(ExprValue))
4841 ExprValue = ExprValue == 0;
4845 TheCondState.
CondMet = ExprValue;
4854bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4857 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4858 " if or an elseif");
4861 bool LastIgnoreState =
false;
4862 if (!TheCondStack.empty())
4863 LastIgnoreState = TheCondStack.back().Ignore;
4864 if (LastIgnoreState || TheCondState.
CondMet) {
4865 TheCondState.
Ignore =
true;
4866 eatToEndOfStatement();
4869 if (parseTextItem(Str)) {
4871 return TokError(
"expected text item parameter for 'elseifb' directive");
4872 return TokError(
"expected text item parameter for 'elseifnb' directive");
4878 TheCondState.
CondMet = ExpectBlank == Str.empty();
4888bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4889 bool expect_defined) {
4892 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4893 " if or an elseif");
4896 bool LastIgnoreState =
false;
4897 if (!TheCondStack.empty())
4898 LastIgnoreState = TheCondStack.back().Ignore;
4899 if (LastIgnoreState || TheCondState.
CondMet) {
4900 TheCondState.
Ignore =
true;
4901 eatToEndOfStatement();
4903 bool is_defined =
false;
4905 SMLoc StartLoc, EndLoc;
4907 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4910 if (check(parseIdentifier(Name),
4911 "expected identifier after 'elseifdef'") ||
4915 if (BuiltinSymbolMap.contains(
Name.lower())) {
4925 TheCondState.
CondMet = (is_defined == expect_defined);
4934bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4935 bool CaseInsensitive) {
4938 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4939 " if or an elseif");
4942 bool LastIgnoreState =
false;
4943 if (!TheCondStack.empty())
4944 LastIgnoreState = TheCondStack.back().Ignore;
4945 if (LastIgnoreState || TheCondState.
CondMet) {
4946 TheCondState.
Ignore =
true;
4947 eatToEndOfStatement();
4949 std::string String1, String2;
4951 if (parseTextItem(String1)) {
4954 "expected text item parameter for 'elseifidn' directive");
4955 return TokError(
"expected text item parameter for 'elseifdif' directive");
4961 "expected comma after first string for 'elseifidn' directive");
4963 "expected comma after first string for 'elseifdif' directive");
4967 if (parseTextItem(String2)) {
4970 "expected text item parameter for 'elseifidn' directive");
4971 return TokError(
"expected text item parameter for 'elseifdif' directive");
4974 if (CaseInsensitive)
4976 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4978 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4987bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4993 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4996 bool LastIgnoreState =
false;
4997 if (!TheCondStack.empty())
4998 LastIgnoreState = TheCondStack.back().Ignore;
4999 if (LastIgnoreState || TheCondState.
CondMet)
5000 TheCondState.
Ignore =
true;
5002 TheCondState.
Ignore =
false;
5009bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5021bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5022 if (!TheCondStack.empty()) {
5023 if (TheCondStack.back().Ignore) {
5024 eatToEndOfStatement();
5029 std::string Message =
".err directive invoked in source file";
5034 return Error(DirectiveLoc, Message);
5039bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5040 if (!TheCondStack.empty()) {
5041 if (TheCondStack.back().Ignore) {
5042 eatToEndOfStatement();
5048 if (parseTextItem(
Text))
5049 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5051 std::string Message =
".errb directive invoked in source file";
5054 return addErrorSuffix(
" in '.errb' directive");
5059 if (
Text.empty() == ExpectBlank)
5060 return Error(DirectiveLoc, Message);
5066bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5067 bool ExpectDefined) {
5068 if (!TheCondStack.empty()) {
5069 if (TheCondStack.back().Ignore) {
5070 eatToEndOfStatement();
5075 bool IsDefined =
false;
5077 SMLoc StartLoc, EndLoc;
5079 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5082 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5085 if (BuiltinSymbolMap.contains(
Name.lower())) {
5095 std::string Message =
".errdef directive invoked in source file";
5098 return addErrorSuffix(
" in '.errdef' directive");
5103 if (IsDefined == ExpectDefined)
5104 return Error(DirectiveLoc, Message);
5110bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5111 bool CaseInsensitive) {
5112 if (!TheCondStack.empty()) {
5113 if (TheCondStack.back().Ignore) {
5114 eatToEndOfStatement();
5119 std::string String1, String2;
5121 if (parseTextItem(String1)) {
5123 return TokError(
"expected string parameter for '.erridn' directive");
5124 return TokError(
"expected string parameter for '.errdif' directive");
5130 "expected comma after first string for '.erridn' directive");
5132 "expected comma after first string for '.errdif' directive");
5136 if (parseTextItem(String2)) {
5138 return TokError(
"expected string parameter for '.erridn' directive");
5139 return TokError(
"expected string parameter for '.errdif' directive");
5142 std::string Message;
5144 Message =
".erridn directive invoked in source file";
5146 Message =
".errdif directive invoked in source file";
5149 return addErrorSuffix(
" in '.erridn' directive");
5154 if (CaseInsensitive)
5156 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5158 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5161 if ((CaseInsensitive &&
5162 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5163 (ExpectEqual == (String1 == String2)))
5164 return Error(DirectiveLoc, Message);
5170bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5171 if (!TheCondStack.empty()) {
5172 if (TheCondStack.back().Ignore) {
5173 eatToEndOfStatement();
5179 if (parseAbsoluteExpression(ExprValue))
5180 return addErrorSuffix(
" in '.erre' directive");
5182 std::string Message =
".erre directive invoked in source file";
5185 return addErrorSuffix(
" in '.erre' directive");
5190 if ((ExprValue == 0) == ExpectZero)
5191 return Error(DirectiveLoc, Message);
5197bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5202 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5204 if (!TheCondStack.empty()) {
5205 TheCondState = TheCondStack.back();
5206 TheCondStack.pop_back();
5212void MasmParser::initializeDirectiveKindMap() {
5213 DirectiveKindMap[
"="] = DK_ASSIGN;
5214 DirectiveKindMap[
"equ"] = DK_EQU;
5215 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5219 DirectiveKindMap[
"byte"] = DK_BYTE;
5220 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5221 DirectiveKindMap[
"word"] = DK_WORD;
5222 DirectiveKindMap[
"sword"] = DK_SWORD;
5223 DirectiveKindMap[
"dword"] = DK_DWORD;
5224 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5225 DirectiveKindMap[
"fword"] = DK_FWORD;
5226 DirectiveKindMap[
"qword"] = DK_QWORD;
5227 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5228 DirectiveKindMap[
"real4"] = DK_REAL4;
5229 DirectiveKindMap[
"real8"] = DK_REAL8;
5230 DirectiveKindMap[
"real10"] = DK_REAL10;
5231 DirectiveKindMap[
"align"] = DK_ALIGN;
5232 DirectiveKindMap[
"even"] = DK_EVEN;
5233 DirectiveKindMap[
"org"] = DK_ORG;
5234 DirectiveKindMap[
"extern"] = DK_EXTERN;
5235 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5236 DirectiveKindMap[
"public"] = DK_PUBLIC;
5238 DirectiveKindMap[
"comment"] = DK_COMMENT;
5239 DirectiveKindMap[
"include"] = DK_INCLUDE;
5240 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5241 DirectiveKindMap[
"rept"] = DK_REPEAT;
5242 DirectiveKindMap[
"while"] = DK_WHILE;
5243 DirectiveKindMap[
"for"] = DK_FOR;
5244 DirectiveKindMap[
"irp"] = DK_FOR;
5245 DirectiveKindMap[
"forc"] = DK_FORC;
5246 DirectiveKindMap[
"irpc"] = DK_FORC;
5247 DirectiveKindMap[
"if"] = DK_IF;
5248 DirectiveKindMap[
"ife"] = DK_IFE;
5249 DirectiveKindMap[
"ifb"] = DK_IFB;
5250 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5251 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5252 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5253 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5254 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5255 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5256 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5257 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5258 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5259 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5260 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5261 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5262 DirectiveKindMap[
"else"] = DK_ELSE;
5263 DirectiveKindMap[
"end"] = DK_END;
5264 DirectiveKindMap[
"endif"] = DK_ENDIF;
5308 DirectiveKindMap[
"macro"] = DK_MACRO;
5309 DirectiveKindMap[
"exitm"] = DK_EXITM;
5310 DirectiveKindMap[
"endm"] = DK_ENDM;
5311 DirectiveKindMap[
"purge"] = DK_PURGE;
5312 DirectiveKindMap[
".err"] = DK_ERR;
5313 DirectiveKindMap[
".errb"] = DK_ERRB;
5314 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5315 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5316 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5317 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5318 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5319 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5320 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5321 DirectiveKindMap[
".erre"] = DK_ERRE;
5322 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5323 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5324 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5325 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5326 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5327 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5328 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5329 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5330 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5331 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5332 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5333 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5334 DirectiveKindMap[
".radix"] = DK_RADIX;
5335 DirectiveKindMap[
"db"] = DK_DB;
5336 DirectiveKindMap[
"dd"] = DK_DD;
5337 DirectiveKindMap[
"df"] = DK_DF;
5338 DirectiveKindMap[
"dq"] = DK_DQ;
5339 DirectiveKindMap[
"dw"] = DK_DW;
5340 DirectiveKindMap[
"echo"] = DK_ECHO;
5341 DirectiveKindMap[
"struc"] = DK_STRUCT;
5342 DirectiveKindMap[
"struct"] = DK_STRUCT;
5343 DirectiveKindMap[
"union"] = DK_UNION;
5344 DirectiveKindMap[
"ends"] = DK_ENDS;
5347bool MasmParser::isMacroLikeDirective() {
5349 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5350 .CasesLower({
"repeat",
"rept"},
true)
5351 .CaseLower(
"while",
true)
5352 .CasesLower({
"for",
"irp"},
true)
5353 .CasesLower({
"forc",
"irpc"},
true)
5359 peekTok().getIdentifier().equals_insensitive(
"macro"))
5365MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5366 AsmToken EndToken, StartToken = getTok();
5368 unsigned NestLevel = 0;
5372 printError(DirectiveLoc,
"no matching 'endm' in definition");
5376 if (isMacroLikeDirective())
5381 getTok().getIdentifier().equals_insensitive(
"endm")) {
5382 if (NestLevel == 0) {
5383 EndToken = getTok();
5386 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5395 eatToEndOfStatement();
5400 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5404 return &MacroLikeBodies.back();
5407bool MasmParser::expandStatement(SMLoc Loc) {
5409 SMLoc EndLoc = getTok().getLoc();
5414 StringMap<std::string> BuiltinValues;
5415 for (
const auto &S : BuiltinSymbolMap) {
5416 const BuiltinSymbol &Sym = S.getValue();
5417 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5418 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5421 for (
const auto &
B : BuiltinValues) {
5422 MCAsmMacroParameter
P;
5423 MCAsmMacroArgument
A;
5424 P.Name =
B.getKey();
5432 for (
const auto &V : Variables) {
5435 MCAsmMacroParameter
P;
5436 MCAsmMacroArgument
A;
5445 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5446 MCAsmMacro
M = MacroLikeBodies.back();
5449 SmallString<80> Buf;
5450 raw_svector_ostream OS(Buf);
5451 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5453 std::unique_ptr<MemoryBuffer>
Expansion =
5459 EndStatementAtEOFStack.push_back(
false);
5464void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5465 raw_svector_ostream &OS) {
5466 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5468void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5470 raw_svector_ostream &OS) {
5473 std::unique_ptr<MemoryBuffer> Instantiation =
5478 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5479 ExitLoc, TheCondStack.size()};
5480 ActiveMacros.push_back(
MI);
5485 EndStatementAtEOFStack.push_back(
true);
5493bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5494 const MCExpr *CountExpr;
5495 SMLoc CountLoc = getTok().getLoc();
5496 if (parseExpression(CountExpr))
5500 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5501 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5504 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5508 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5514 SmallString<256> Buf;
5515 raw_svector_ostream OS(Buf);
5517 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5520 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5529bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5530 const MCExpr *CondExpr;
5531 SMLoc CondLoc = getTok().getLoc();
5532 if (parseExpression(CondExpr))
5536 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5542 SmallString<256> Buf;
5543 raw_svector_ostream OS(Buf);
5545 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5546 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5550 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5552 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5562bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5564 MCAsmMacroArguments
A;
5565 if (check(parseIdentifier(
Parameter.Name),
5566 "expected identifier in '" + Dir +
"' directive"))
5575 ParamLoc = Lexer.getLoc();
5576 if (parseMacroArgument(
nullptr,
Parameter.Value))
5582 QualLoc = Lexer.getLoc();
5583 if (parseIdentifier(Qualifier))
5584 return Error(QualLoc,
"missing parameter qualifier for "
5589 if (
Qualifier.equals_insensitive(
"req"))
5592 return Error(QualLoc,
5593 Qualifier +
" is not a valid parameter qualifier for '" +
5594 Parameter.Name +
"' in '" + Dir +
"' directive");
5599 "expected comma in '" + Dir +
"' directive") ||
5601 "values in '" + Dir +
5602 "' directive must be enclosed in angle brackets"))
5608 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5617 "values in '" + Dir +
5618 "' directive must be enclosed in angle brackets") ||
5623 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5629 SmallString<256> Buf;
5630 raw_svector_ostream OS(Buf);
5632 for (
const MCAsmMacroArgument &Arg :
A) {
5633 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5637 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5646bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5650 if (check(parseIdentifier(
Parameter.Name),
5651 "expected identifier in '" + Directive +
"' directive") ||
5653 "expected comma in '" + Directive +
"' directive"))
5655 if (parseAngleBracketString(Argument)) {
5663 for (; End <
Argument.size(); ++End) {
5673 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5679 SmallString<256> Buf;
5680 raw_svector_ostream OS(Buf);
5682 StringRef
Values(Argument);
5683 for (std::size_t
I = 0, End =
Values.size();
I != End; ++
I) {
5684 MCAsmMacroArgument Arg;
5687 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5691 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5696bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5698 const MCExpr *
Value;
5699 SMLoc ExprLoc = getLexer().getLoc();
5700 if (parseExpression(
Value))
5704 return Error(ExprLoc,
"unexpected expression in _emit");
5707 return Error(ExprLoc,
"literal value out of range for directive");
5713bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5714 const MCExpr *
Value;
5715 SMLoc ExprLoc = getLexer().getLoc();
5716 if (parseExpression(
Value))
5720 return Error(ExprLoc,
"unexpected expression in align");
5723 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5729bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5730 const SMLoc Loc = getLexer().getLoc();
5732 StringRef RadixString = StringRef(RadixStringRaw).trim();
5736 "radix must be a decimal number in the range 2 to 16; was " +
5739 if (Radix < 2 || Radix > 16)
5740 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5741 std::to_string(Radix));
5742 getLexer().setMasmDefaultRadix(Radix);
5748bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5751 if (!StringRef(Message).ends_with(
"\n"))
5779bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5781 if (Var.Name.empty())
5783 return setTextVariable(Var, Name,
Value, SMLoc(),
5784 Variable::WARN_ON_REDEFINITION);
5787bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5788 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5789 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5790 return lookUpField(
Base, Member, Info);
5793bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5794 AsmFieldInfo &Info)
const {
5798 AsmFieldInfo BaseInfo;
5799 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5802 auto StructIt = Structs.
find(
Base.lower());
5803 auto TypeIt = KnownType.
find(
Base.lower());
5804 if (TypeIt != KnownType.
end()) {
5805 StructIt = Structs.
find(TypeIt->second.Name.lower());
5807 if (StructIt != Structs.
end())
5808 return lookUpField(StructIt->second, Member, Info);
5813bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5814 AsmFieldInfo &Info)
const {
5816 Info.Type.Name = Structure.Name;
5817 Info.Type.Size = Structure.Size;
5818 Info.Type.ElementSize = Structure.Size;
5819 Info.Type.Length = 1;
5823 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5824 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5826 auto StructIt = Structs.
find(FieldName.
lower());
5827 if (StructIt != Structs.
end())
5828 return lookUpField(StructIt->second, FieldMember, Info);
5830 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5831 if (FieldIt == Structure.FieldsByName.
end())
5834 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5835 if (FieldMember.empty()) {
5840 if (
Field.Contents.FT == FT_STRUCT)
5841 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5843 Info.Type.Name =
"";
5847 if (
Field.Contents.FT != FT_STRUCT)
5849 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5851 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5858bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5859 unsigned Size = StringSwitch<unsigned>(Name)
5860 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5861 .CasesLower({
"word",
"dw",
"sword"}, 2)
5862 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5863 .CasesLower({
"fword",
"df"}, 6)
5864 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5865 .CaseLower(
"real4", 4)
5866 .CaseLower(
"real8", 8)
5867 .CaseLower(
"real10", 10)
5877 auto StructIt = Structs.
find(
Name.lower());
5878 if (StructIt != Structs.
end()) {
5879 const StructInfo &Structure = StructIt->second;
5881 Info.ElementSize = Structure.Size;
5883 Info.Size = Structure.Size;
5890bool MasmParser::parseMSInlineAsm(
5891 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5892 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5893 SmallVectorImpl<std::string> &Constraints,
5894 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5895 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5896 SmallVector<void *, 4> InputDecls;
5897 SmallVector<void *, 4> OutputDecls;
5898 SmallVector<bool, 4> InputDeclsAddressOf;
5899 SmallVector<bool, 4> OutputDeclsAddressOf;
5900 SmallVector<std::string, 4> InputConstraints;
5901 SmallVector<std::string, 4> OutputConstraints;
5910 unsigned InputIdx = 0;
5911 unsigned OutputIdx = 0;
5914 if (parseCurlyBlockScope(AsmStrRewrites))
5917 ParseStatementInfo
Info(&AsmStrRewrites);
5918 bool StatementErr = parseStatement(Info, &SI);
5920 if (StatementErr ||
Info.ParseError) {
5922 printPendingErrors();
5927 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5929 if (
Info.Opcode == ~0U)
5935 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5936 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5940 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5941 unsigned NumDefs =
Desc.getNumDefs();
5950 if (SymName.
empty())
5958 if (Operand.
isImm()) {
5966 bool isOutput = (i == 1) &&
Desc.mayStore();
5972 OutputConstraints.
push_back((
"=" + Constraint).str());
5978 if (
Desc.operands()[i - 1].isBranchTarget())
5990 NumOutputs = OutputDecls.
size();
5991 NumInputs = InputDecls.
size();
5996 Clobbers.
assign(ClobberRegs.
size(), std::string());
5997 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5998 raw_string_ostream OS(Clobbers[
I]);
6003 if (NumOutputs || NumInputs) {
6004 unsigned NumExprs = NumOutputs + NumInputs;
6005 OpDecls.resize(NumExprs);
6006 Constraints.
resize(NumExprs);
6007 for (
unsigned i = 0; i < NumOutputs; ++i) {
6008 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6009 Constraints[i] = OutputConstraints[i];
6011 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6012 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6013 Constraints[
j] = InputConstraints[i];
6018 std::string AsmStringIR;
6019 raw_string_ostream OS(AsmStringIR);
6020 StringRef ASMString =
6022 const char *AsmStart = ASMString.
begin();
6023 const char *AsmEnd = ASMString.
end();
6025 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6026 const AsmRewrite &AR = *
I;
6033 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6036 if (
unsigned Len = Loc - AsmStart)
6037 OS << StringRef(AsmStart, Len);
6041 AsmStart = Loc + AR.
Len;
6045 unsigned AdditionalSkip = 0;
6067 size_t OffsetLen = OffsetName.
size();
6068 auto rewrite_it = std::find_if(
6069 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6070 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6071 (FusingAR.Kind == AOK_Input ||
6072 FusingAR.Kind == AOK_CallInput);
6074 if (rewrite_it == AsmStrRewrites.
end()) {
6075 OS <<
"offset " << OffsetName;
6077 OS <<
"${" << InputIdx++ <<
":P}";
6078 rewrite_it->Done =
true;
6080 OS <<
'$' << InputIdx++;
6081 rewrite_it->Done =
true;
6093 OS <<
'$' << InputIdx++;
6096 OS <<
"${" << InputIdx++ <<
":P}";
6099 OS <<
'$' << OutputIdx++;
6104 case 8: OS <<
"byte ptr ";
break;
6105 case 16: OS <<
"word ptr ";
break;
6106 case 32: OS <<
"dword ptr ";
break;
6107 case 64: OS <<
"qword ptr ";
break;
6108 case 80: OS <<
"xword ptr ";
break;
6109 case 128: OS <<
"xmmword ptr ";
break;
6110 case 256: OS <<
"ymmword ptr ";
break;
6120 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6125 unsigned Val = AR.
Val;
6127 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6128 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6140 AsmStart = Loc + AR.
Len + AdditionalSkip;
6144 if (AsmStart != AsmEnd)
6145 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6147 AsmString = OS.
str();
6151void MasmParser::initializeBuiltinSymbolMaps() {
6153 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6154 BuiltinSymbolMap[
"@line"] = BI_LINE;
6155 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6158 BuiltinSymbolMap[
"@date"] = BI_DATE;
6159 BuiltinSymbolMap[
"@time"] = BI_TIME;
6160 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6161 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6162 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6165 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6168 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6186const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6196 if (ActiveMacros.empty())
6200 ActiveMacros.front()->ExitBuffer);
6203 case BI_UNWINDVERSION:
6210std::optional<std::string>
6211MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6217 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6218 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6219 return std::string(TmpBuffer, Len);
6223 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6224 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6225 return std::string(TmpBuffer, Len);
6230 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6238 return getStreamer().getCurrentSectionOnly()->getName().str();
6243bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction
Function,
6247 "' requires arguments in parentheses")) {
6258 MCAsmMacro
M(Name,
"",
P, {},
true);
6260 MCAsmMacroArguments
A;
6269 for (
const MCAsmMacroArgument &Arg :
A) {
6270 for (
const AsmToken &Tok : Arg) {
6288 struct tm TM,
unsigned CB) {
6289 return new MasmParser(SM,
C, Out, MAI, TM, CB);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
AMDGPU Lower Kernel Arguments
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
bool shouldUseLogicalShr() const
StringRef getInternalSymbolPrefix() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo & getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI void printIncludeStackForDiagnostic(SMLoc Loc, raw_ostream &OS) const
Prints the include stack of a buffer unless it is a macro instantiation buffer.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
RelativeUniformCounterPtr Values
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI SourceMgr SrcMgr
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ 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.