40#define DEBUG_TYPE "wasm-asm-parser"
49 enum KindTy { Token,
Integer,
Float, Symbol, BrList, CatchList } Kind;
51 SMLoc StartLoc, EndLoc;
70 std::vector<unsigned> List;
80 std::vector<CaLOpElem> List;
92 WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp
T)
93 : Kind(Token), StartLoc(
Start), EndLoc(End), Tok(
T) {}
94 WebAssemblyOperand(SMLoc Start, SMLoc End, IntOp
I)
95 : Kind(Integer), StartLoc(
Start), EndLoc(End),
Int(
I) {}
96 WebAssemblyOperand(SMLoc Start, SMLoc End, FltOp
F)
97 : Kind(Float), StartLoc(
Start), EndLoc(End), Flt(
F) {}
98 WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)
99 : Kind(Symbol), StartLoc(
Start), EndLoc(End), Sym(S) {}
100 WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp
B)
101 : Kind(BrList), StartLoc(
Start), EndLoc(End), BrL(
B) {}
102 WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp
C)
103 : Kind(CatchList), StartLoc(
Start), EndLoc(End), CaL(
C) {}
105 ~WebAssemblyOperand()
override {
112 bool isToken()
const override {
return Kind == Token; }
113 bool isImm()
const override {
return Kind == Integer || Kind == Symbol; }
114 bool isFPImm()
const {
return Kind == Float; }
115 bool isMem()
const override {
return false; }
116 bool isReg()
const override {
return false; }
117 bool isBrList()
const {
return Kind == BrList; }
118 bool isCatchList()
const {
return Kind == CatchList; }
120 MCRegister
getReg()
const override {
130 SMLoc getStartLoc()
const override {
return StartLoc; }
131 SMLoc getEndLoc()
const override {
return EndLoc; }
133 void addRegOperands(MCInst &,
unsigned)
const {
138 void addImmOperands(MCInst &Inst,
unsigned N)
const {
139 assert(
N == 1 &&
"Invalid number of operands!");
142 else if (Kind == Symbol)
148 void addFPImmf32Operands(MCInst &Inst,
unsigned N)
const {
149 assert(
N == 1 &&
"Invalid number of operands!");
157 void addFPImmf64Operands(MCInst &Inst,
unsigned N)
const {
158 assert(
N == 1 &&
"Invalid number of operands!");
165 void addBrListOperands(MCInst &Inst,
unsigned N)
const {
166 assert(
N == 1 && isBrList() &&
"Invalid BrList!");
167 for (
auto Br : BrL.List)
171 void addCatchListOperands(MCInst &Inst,
unsigned N)
const {
172 assert(
N == 1 && isCatchList() &&
"Invalid CatchList!");
174 for (
auto Ca : CaL.List) {
183 void print(raw_ostream &OS,
const MCAsmInfo &MAI)
const override {
186 OS <<
"Tok:" << Tok.Tok;
189 OS <<
"Int:" <<
Int.Val;
192 OS <<
"Flt:" << Flt.Val;
195 OS <<
"Sym:" << Sym.Exp;
198 OS <<
"BrList:" << BrL.List.size();
201 OS <<
"CaList:" << CaL.List.size();
215 auto *Sym =
static_cast<MCSymbolWasm *
>(Ctx.lookupSymbol(Name));
217 if (!Sym->isFunctionTable())
218 Ctx.reportError(
SMLoc(),
"symbol is not a wasm funcref table");
220 Sym =
static_cast<MCSymbolWasm *
>(Ctx.getOrCreateSymbol(Name));
245 } CurrentState = FileStart;
261 wasm::WasmSignature Sig;
263 std::vector<Nested> NestingStack;
265 MCSymbolWasm *DefaultFunctionTable =
nullptr;
266 MCSymbol *LastFunctionLabel =
nullptr;
270 WebAssemblyAsmTypeCheck TC;
275 WebAssemblyAsmParser(
const MCSubtargetInfo &STI, MCAsmParser &Parser,
276 const MCInstrInfo &MII,
const MCTargetOptions &
Options)
277 : MCTargetAsmParser(
Options, STI, MII), Parser(Parser),
278 Lexer(Parser.getLexer()), Is64(STI.getTargetTriple().isArch64Bit()),
279 TC(Parser, MII, Is64), SkipTypeCheck(
Options.MCNoTypeCheck) {
280 FeatureBitset FBS = ComputeAvailableFeatures(STI.
getFeatureBits());
283 if (FBS.
test(WebAssembly::FeatureBulkMemory)) {
284 FBS.
set(WebAssembly::FeatureBulkMemoryOpt);
287 if (FBS.
test(WebAssembly::FeatureReferenceTypes)) {
288 FBS.
set(WebAssembly::FeatureCallIndirectOverlong);
291 setAvailableFeatures(FBS);
294 auto &
SM = Parser.getSourceManager();
296 SM.getBufferInfo(
SM.getMainFileID()).Buffer->getBufferIdentifier();
297 if (BufferName ==
"<inline asm>")
298 SkipTypeCheck =
true;
301 void Initialize(MCAsmParser &Parser)
override {
305 getContext(),
"__indirect_function_table", Is64);
308 DefaultFunctionTable->setOmitFromLinkingSection();
311#define GET_ASSEMBLER_HEADER
312#include "WebAssemblyGenAsmMatcher.inc"
318 ParseStatus tryParseRegister(MCRegister &
Reg, SMLoc &StartLoc,
319 SMLoc &EndLoc)
override {
323 bool error(
const Twine &Msg,
const AsmToken &Tok) {
327 bool error(
const Twine &Msg, SMLoc Loc = SMLoc()) {
328 return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg);
331 std::pair<StringRef, StringRef> nestingString(NestingType NT) {
334 return {
"function",
"end_function"};
336 return {
"block",
"end_block"};
338 return {
"loop",
"end_loop"};
340 return {
"try",
"end_try/delegate"};
342 return {
"catch_all",
"end_try"};
344 return {
"try_table",
"end_try_table"};
346 return {
"if",
"end_if"};
348 return {
"else",
"end_if"};
354 void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) {
355 NestingStack.push_back({
NT, Sig});
358 bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
359 if (NestingStack.empty())
360 return error(Twine(
"End of block construct with no start: ") + Ins);
361 auto Top = NestingStack.back();
362 if (Top.NT != NT1 && Top.NT != NT2)
363 return error(Twine(
"Block construct type mismatch, expected: ") +
364 nestingString(Top.NT).second +
", instead got: " + Ins);
365 TC.setLastSig(Top.Sig);
366 NestingStack.pop_back();
372 bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT,
373 NestingType PushNT) {
374 if (NestingStack.empty())
375 return error(Twine(
"End of block construct with no start: ") + Ins);
376 auto Sig = NestingStack.back().Sig;
383 bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {
384 auto Err = !NestingStack.empty();
385 while (!NestingStack.empty()) {
386 error(Twine(
"Unmatched block construct(s) at function end: ") +
387 nestingString(NestingStack.back().NT).first,
389 NestingStack.pop_back();
395 auto Ok = Lexer.is(Kind);
403 return error(std::string(
"Expected ") + KindName +
", instead got: ",
408 StringRef expectIdent() {
410 error(
"Expected identifier, got: ", Lexer.getTok());
413 auto Name = Lexer.getTok().getString();
418 StringRef expectStringOrIdent() {
420 auto Str = Lexer.getTok().getStringContents();
425 auto Name = Lexer.getTok().getString();
429 error(
"Expected string or identifier, got: ", Lexer.getTok());
433 bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
437 return error(
"unknown type: ", Lexer.getTok());
446 void parseSingleInteger(
bool IsNegative,
OperandVector &Operands) {
447 auto &
Int = Lexer.getTok();
448 int64_t Val =
Int.getIntVal();
451 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
452 Int.getLoc(),
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
456 bool parseSingleFloat(
bool IsNegative,
OperandVector &Operands) {
457 auto &Flt = Lexer.getTok();
459 if (Flt.getString().getAsDouble(Val,
false))
460 return error(
"Cannot parse real: ", Flt);
463 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
464 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
469 bool parseSpecialFloatMaybe(
bool IsNegative,
OperandVector &Operands) {
472 auto &Flt = Lexer.getTok();
473 auto S = Flt.getString();
475 if (S.compare_insensitive(
"infinity") == 0) {
476 Val = std::numeric_limits<double>::infinity();
477 }
else if (S.compare_insensitive(
"nan") == 0) {
478 Val = std::numeric_limits<double>::quiet_NaN();
484 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
485 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
491 auto &Tok = Lexer.getTok();
495 Order = StringSwitch<int64_t>(S)
501 return error(
"memory ordering requires relaxed-atomics feature: ",
508 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
513 bool checkForP2AlignIfLoadStore(
OperandVector &Operands, StringRef InstName) {
515 auto IsLoadStore = InstName.
contains(
".load") ||
518 auto IsAtomic = InstName.
contains(
"atomic.");
519 if (IsLoadStore || IsAtomic) {
522 auto Id = expectIdent();
524 return error(
"Expected p2align, instead got: " + Id);
528 return error(
"Expected integer constant");
529 parseSingleInteger(
false, Operands);
534 auto IsLoadStoreLane = InstName.
contains(
"_lane");
535 if (IsLoadStoreLane && Operands.
size() == 4)
541 auto Tok = Lexer.getTok();
542 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
549 void addBlockTypeOperand(
OperandVector &Operands, SMLoc NameLoc,
551 if (
BT == WebAssembly::BlockType::Void) {
552 TC.setLastSig(wasm::WasmSignature{});
556 NestingStack.back().Sig = Sig;
558 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
559 NameLoc, NameLoc, WebAssemblyOperand::IntOp{
static_cast<int64_t
>(
BT)}));
562 bool parseLimits(wasm::WasmLimits *Limits) {
563 auto Tok = Lexer.getTok();
565 return error(
"Expected integer constant, instead got: ", Tok);
573 auto Tok = Lexer.getTok();
575 return error(
"Expected integer constant, instead got: ", Tok);
584 bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *
Op) {
592 auto &Tok = Lexer.getTok();
597 *
Op = std::make_unique<WebAssemblyOperand>(
604 *
Op = std::make_unique<WebAssemblyOperand>(
605 SMLoc(), SMLoc(), WebAssemblyOperand::SymOp{Val});
612 *
Op = std::make_unique<WebAssemblyOperand>(SMLoc(), SMLoc(),
613 WebAssemblyOperand::IntOp{0});
617 bool parseInstruction(ParseInstructionInfo & , StringRef Name,
627 auto &Sep = Lexer.getTok();
628 if (Sep.getLoc().getPointer() !=
Name.end() ||
632 Name = StringRef(
Name.begin(),
Name.size() + Sep.getString().size());
635 auto &
Id = Lexer.getTok();
637 Id.getLoc().getPointer() !=
Name.end())
638 return error(
"Incomplete instruction name: ", Id);
639 Name = StringRef(
Name.begin(),
Name.size() +
Id.getString().size());
644 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
646 WebAssemblyOperand::TokOp{Name}));
650 bool ExpectBlockType =
false;
651 bool ExpectFuncType =
false;
652 bool ExpectCatchList =
false;
653 std::unique_ptr<WebAssemblyOperand> FunctionTable;
654 if (Name ==
"block") {
656 ExpectBlockType =
true;
657 }
else if (Name ==
"loop") {
659 ExpectBlockType =
true;
660 }
else if (Name ==
"try") {
662 ExpectBlockType =
true;
663 }
else if (Name ==
"if") {
665 ExpectBlockType =
true;
666 }
else if (Name ==
"else") {
667 if (popAndPushWithSameSignature(Name, If, Else))
669 }
else if (Name ==
"catch") {
670 if (popAndPushWithSameSignature(Name, Try, Try))
672 }
else if (Name ==
"catch_all") {
673 if (popAndPushWithSameSignature(Name, Try, CatchAll))
675 }
else if (Name ==
"try_table") {
677 ExpectBlockType =
true;
678 ExpectCatchList =
true;
679 }
else if (Name ==
"end_if") {
680 if (pop(Name, If, Else))
682 }
else if (Name ==
"end_try") {
683 if (pop(Name, Try, CatchAll))
685 }
else if (Name ==
"end_try_table") {
686 if (pop(Name, TryTable))
688 }
else if (Name ==
"delegate") {
691 }
else if (Name ==
"end_loop") {
694 }
else if (Name ==
"end_block") {
695 if (pop(Name, Block))
697 }
else if (Name ==
"end_function") {
698 ensureLocals(getStreamer());
699 CurrentState = EndFunction;
700 if (pop(Name, Function) || ensureEmptyNestingStack())
702 }
else if (Name ==
"call_indirect" || Name ==
"return_call_indirect") {
706 if (parseFunctionTableOperand(&FunctionTable))
708 ExpectFuncType =
true;
709 }
else if (Name ==
"ref.test") {
712 ExpectFuncType =
true;
715 if (
Name.contains(
"atomic.")) {
716 if (addMemOrderOrDefault(Operands))
721 auto PeekCatchList = [&]() {
724 AsmToken NextTok = Lexer.peekTok();
730 if (ExpectFuncType ||
737 auto Loc = Parser.getTok();
739 if (parseSignature(Signature))
742 TC.setLastSig(*Signature);
744 NestingStack.back().Sig = *Signature;
745 ExpectBlockType =
false;
748 auto *WasmSym =
static_cast<MCSymbolWasm *
>(Sym);
749 WasmSym->setSignature(Signature);
753 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
754 Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
764 if (ExpectCatchList && PeekCatchList()) {
765 if (ExpectBlockType) {
766 ExpectBlockType =
false;
767 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
769 if (parseCatchList(Operands))
771 ExpectCatchList =
false;
775 auto &Tok = Lexer.getTok();
778 if (!parseSpecialFloatMaybe(
false, Operands))
780 auto &
Id = Lexer.getTok();
781 if (ExpectBlockType) {
784 if (
BT == WebAssembly::BlockType::Invalid)
785 return error(
"Unknown block type: ", Id);
786 addBlockTypeOperand(Operands, NameLoc,
BT);
787 ExpectBlockType =
false;
791 if (ExpectCatchList && PeekCatchList()) {
792 if (parseCatchList(Operands))
794 ExpectCatchList =
false;
801 if (Parser.parseExpression(Val, End))
802 return error(
"Cannot parse symbol: ", Lexer.getTok());
803 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
804 Start, End, WebAssemblyOperand::SymOp{Val}));
805 if (checkForP2AlignIfLoadStore(Operands, Name))
813 parseSingleInteger(
true, Operands);
814 if (checkForP2AlignIfLoadStore(Operands, Name))
817 if (parseSingleFloat(
true, Operands))
819 }
else if (!parseSpecialFloatMaybe(
true, Operands)) {
821 return error(
"Expected numeric constant instead got: ",
826 parseSingleInteger(
false, Operands);
827 if (checkForP2AlignIfLoadStore(Operands, Name))
831 if (parseSingleFloat(
false, Operands))
837 auto Op = std::make_unique<WebAssemblyOperand>(
841 Op->BrL.List.push_back(Lexer.getTok().getIntVal());
851 return error(
"Unexpected token in operand: ", Tok);
864 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
867 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
868 NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));
871 Operands.
push_back(std::move(FunctionTable));
876 bool parseSignature(wasm::WasmSignature *Signature) {
879 if (parseRegTypeList(Signature->
Params))
887 if (parseRegTypeList(Signature->
Returns))
895 auto Op = std::make_unique<WebAssemblyOperand>(
896 Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});
903 auto CatchStr = expectIdent();
904 if (CatchStr.empty())
906 uint8_t CatchOpcode =
907 StringSwitch<uint8_t>(CatchStr)
913 if (CatchOpcode == 0xff)
915 "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
918 const MCExpr *
Tag =
nullptr;
921 if (Parser.parseExpression(
Tag))
922 return error(
"Cannot parse symbol: ", Lexer.getTok());
925 auto &DestTok = Lexer.getTok();
927 return error(
"Expected integer constant, instead got: ", DestTok);
928 unsigned Dest = DestTok.getIntVal();
931 EndLoc = Lexer.getTok().getEndLoc();
935 Op->CaL.List.push_back({CatchOpcode,
Tag, Dest});
943 bool checkDataSection() {
944 if (CurrentState != DataSection) {
945 auto *WS =
static_cast<const MCSectionWasm *
>(
946 getStreamer().getCurrentSectionOnly());
947 if (WS && WS->isText())
948 return error(
"data directive must occur in a data segment: ",
951 CurrentState = DataSection;
958 ParseStatus parseDirective(AsmToken DirectiveID)
override {
960 auto &Out = getStreamer();
962 reinterpret_cast<WebAssemblyTargetStreamer &
>(*Out.getTargetStreamer());
963 auto &Ctx = Out.getContext();
965 if (DirectiveID.
getString() ==
".globaltype") {
966 auto SymName = expectIdent();
971 auto TypeTok = Lexer.getTok();
977 return error(
"Unknown type in .globaltype directive: ", TypeTok);
983 TypeTok = Lexer.getTok();
984 auto Id = expectIdent();
987 if (Id ==
"immutable")
991 return error(
"Unknown type in .globaltype modifier: ", TypeTok);
997 WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(*
Type), Mutable});
999 TOut.emitGlobalType(WasmSym);
1003 if (DirectiveID.
getString() ==
".tabletype") {
1005 auto SymName = expectIdent();
1006 if (SymName.empty())
1011 auto ElemTypeTok = Lexer.getTok();
1012 auto ElemTypeName = expectIdent();
1013 if (ElemTypeName.empty())
1015 std::optional<wasm::ValType> ElemType =
1018 return error(
"Unknown type in .tabletype directive: ", ElemTypeTok);
1020 wasm::WasmLimits Limits = defaultLimits();
1032 wasm::WasmTableType
Type = {*ElemType, Limits};
1033 WasmSym->setTableType(
Type);
1034 TOut.emitTableType(WasmSym);
1038 if (DirectiveID.
getString() ==
".functype") {
1044 auto SymName = expectIdent();
1045 if (SymName.empty())
1049 if (WasmSym->isDefined()) {
1060 if (CurrentState != FunctionLabel) {
1062 if (ensureEmptyNestingStack())
1066 CurrentState = FunctionStart;
1067 LastFunctionLabel = WasmSym;
1070 if (parseSignature(Signature))
1072 if (CurrentState == FunctionStart)
1073 TC.funcDecl(*Signature);
1074 WasmSym->setSignature(Signature);
1076 TOut.emitFunctionType(WasmSym);
1081 if (DirectiveID.
getString() ==
".export_name") {
1082 auto SymName = expectIdent();
1083 if (SymName.empty())
1087 auto ExportName = expectStringOrIdent();
1088 if (ExportName.empty())
1093 TOut.emitExportName(WasmSym, ExportName);
1097 if (DirectiveID.
getString() ==
".import_module") {
1098 auto SymName = expectIdent();
1099 if (SymName.empty())
1103 auto ImportModule = expectStringOrIdent();
1104 if (ImportModule.empty())
1109 TOut.emitImportModule(WasmSym, ImportModule);
1113 if (DirectiveID.
getString() ==
".import_name") {
1114 auto SymName = expectIdent();
1115 if (SymName.empty())
1119 StringRef ImportName = expectStringOrIdent();
1120 if (ImportName.
empty())
1125 TOut.emitImportName(WasmSym, ImportName);
1129 if (DirectiveID.
getString() ==
".tagtype") {
1130 auto SymName = expectIdent();
1131 if (SymName.empty())
1136 if (parseRegTypeList(Signature->
Params))
1138 WasmSym->setSignature(Signature);
1140 TOut.emitTagType(WasmSym);
1145 if (DirectiveID.
getString() ==
".local") {
1146 if (CurrentState != FunctionStart)
1147 return error(
".local directive should follow the start of a function: ",
1150 if (parseRegTypeList(Locals))
1152 TC.localDecl(Locals);
1153 TOut.emitLocal(Locals);
1154 CurrentState = FunctionLocals;
1158 if (DirectiveID.
getString() ==
".int8" ||
1162 if (checkDataSection())
1166 if (Parser.parseExpression(Val, End))
1167 return error(
"Cannot parse .int expression: ", Lexer.getTok());
1170 Out.emitValue(Val, NumBits / 8, End);
1174 if (DirectiveID.
getString() ==
".asciz") {
1175 if (checkDataSection())
1178 if (Parser.parseEscapedString(S))
1179 return error(
"Cannot parse string constant: ", Lexer.getTok());
1180 Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
1188 void ensureLocals(MCStreamer &Out) {
1189 if (CurrentState == FunctionStart) {
1193 auto &TOut =
reinterpret_cast<WebAssemblyTargetStreamer &
>(
1196 CurrentState = FunctionLocals;
1200 bool matchAndEmitInstruction(SMLoc IDLoc,
unsigned & ,
1202 uint64_t &ErrorInfo,
1203 bool MatchingInlineAsm)
override {
1206 FeatureBitset MissingFeatures;
1207 unsigned MatchResult = MatchInstructionImpl(
1208 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
1209 switch (MatchResult) {
1210 case Match_Success: {
1218 for (
unsigned E =
Desc.getNumOperands();
I <
E; ++
I) {
1221 if (
Op.getImm() == -1) {
1227 assert(
I < 2 &&
"Default p2align set but operand not found");
1234 static_cast<uint16_t
>(Inst.
getOpcode()));
1240 TC.typeCheck(IDLoc, Inst, Operands);
1242 if (CurrentState == EndFunction) {
1243 onEndOfFunction(IDLoc);
1245 CurrentState = Instructions;
1249 case Match_MissingFeature: {
1250 assert(MissingFeatures.
count() > 0 &&
"Expected missing features");
1251 SmallString<128> Message;
1252 raw_svector_ostream OS(Message);
1253 OS <<
"instruction requires:";
1254 for (
unsigned I = 0,
E = MissingFeatures.
size();
I !=
E; ++
I)
1255 if (MissingFeatures.
test(
I))
1257 return Parser.Error(IDLoc, Message);
1259 case Match_MnemonicFail:
1260 return Parser.Error(IDLoc,
"invalid instruction");
1261 case Match_NearMisses:
1262 return Parser.Error(IDLoc,
"ambiguous instruction");
1263 case Match_InvalidTiedOperand:
1264 case Match_InvalidOperand: {
1265 SMLoc ErrorLoc = IDLoc;
1266 if (ErrorInfo != ~0ULL) {
1267 if (ErrorInfo >= Operands.
size())
1268 return Parser.Error(IDLoc,
"too few operands for instruction");
1269 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
1270 if (ErrorLoc == SMLoc())
1273 return Parser.Error(ErrorLoc,
"invalid operand for instruction");
1279 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc)
override {
1281 auto *CWS =
static_cast<const MCSectionWasm *
>(
1282 getStreamer().getCurrentSectionOnly());
1286 auto *WasmSym =
static_cast<MCSymbolWasm *
>(
Symbol);
1291 "Wasm doesn\'t support data symbols in text sections");
1298 auto SymName =
Symbol->getName();
1299 if (SymName.starts_with(
".L"))
1306 std::string SecName = (
".text." + SymName).str();
1308 auto *Group = CWS->getGroup();
1314 WasmSym->setComdat(
true);
1317 getStreamer().switchSection(WS);
1322 if (WasmSym->isFunction()) {
1332 ensureEmptyNestingStack(IDLoc);
1333 CurrentState = FunctionLabel;
1334 LastFunctionLabel =
Symbol;
1339 void onEndOfFunction(SMLoc ErrorLoc) {
1341 TC.endOfFunction(ErrorLoc,
true);
1346 void onEndOfFile()
override { ensureEmptyNestingStack(); }
1357#define GET_REGISTER_MATCHER
1358#define GET_SUBTARGET_FEATURE_NAME
1359#define GET_MATCHER_IMPLEMENTATION
1360#include "WebAssemblyGenAsmMatcher.inc"
1364 for (
auto &ME : MatchTable0) {
1365 if (ME.Opcode ==
Opc) {
1366 return ME.getMnemonic();
1369 assert(
false &&
"mnemonic not found");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static constexpr unsigned SM(unsigned Version)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmParser()
StringRef getMnemonic(unsigned Opc)
static const char * getSubtargetFeatureName(uint64_t Val)
This file is part of the WebAssembly Assembler.
This file contains the declaration of the WebAssemblyMCAsmInfo class.
This file provides WebAssembly-specific target descriptions.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file registers the WebAssembly target.
This file declares WebAssembly-specific target streamer classes.
LLVM_ABI SMLoc getLoc() const
int64_t getIntVal() const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() 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.
constexpr bool test(unsigned I) const
constexpr size_t size() const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI wasm::WasmSignature * createWasmSignature()
Allocates and returns a new WasmSignature instance (with empty parameter and return type lists).
StringRef allocateString(StringRef s)
Allocates a copy of the given string on the allocator managed by this context and returns the result.
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createSFPImm(uint32_t Val)
static MCOperand createImm(int64_t Val)
static MCOperand createDFPImm(uint64_t Val)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Wrapper class representing physical registers. Should be passed by value.
static constexpr unsigned NonUniqueID
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
bool checkFeatures(StringRef FS) const
Check whether the subtarget features are enabled/disabled as per the provided string,...
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
void setFunctionTable(bool is64)
MCTargetAsmParser - Generic interface to target specific assembly parsers.
static constexpr StatusTy Failure
static constexpr StatusTy NoMatch
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
static SectionKind getText()
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
LLVM_ABI void clear()
Clears function-level state.
#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.
@ C
The default llvm calling convention, compatible with C.
int32_t getWasm64Opcode(uint32_t Opcode)
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
BlockType parseBlockType(StringRef Type)
BlockType
Used as immediate MachineOperands for block signatures.
@ OPERAND_P2ALIGN
p2align immediate for load and store address alignment.
unsigned GetDefaultP2AlignAny(unsigned Opc)
Return the default p2align value for a load or store with the given opcode.
std::optional< wasm::ValType > parseType(StringRef Type)
Context & getContext() const
@ WASM_OPCODE_CATCH_ALL_REF
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_FUNCTION
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
Target & getTheWebAssemblyTarget32()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Target & getTheWebAssemblyTarget64()
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params