40#define DEBUG_TYPE "wasm-asm-parser"
59 SMLoc StartLoc, EndLoc;
78 std::vector<unsigned> List;
88 std::vector<CaLOpElem> List;
92 std::vector<uint8_t> List;
105 WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp
T)
106 : Kind(Token), StartLoc(
Start), EndLoc(End), Tok(
T) {}
107 WebAssemblyOperand(SMLoc Start, SMLoc End, IntOp
I)
108 : Kind(Integer), StartLoc(
Start), EndLoc(End),
Int(
I) {}
109 WebAssemblyOperand(SMLoc Start, SMLoc End, FltOp
F)
110 : Kind(Float), StartLoc(
Start), EndLoc(End), Flt(
F) {}
111 WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)
112 : Kind(Symbol), StartLoc(
Start), EndLoc(End), Sym(S) {}
113 WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp
B)
114 : Kind(BrList), StartLoc(
Start), EndLoc(End), BrL(
B) {}
115 WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp
C)
116 : Kind(CatchList), StartLoc(
Start), EndLoc(End), CaL(
C) {}
117 WebAssemblyOperand(SMLoc Start, SMLoc End, TyLOp
T)
118 : Kind(TypeList), StartLoc(
Start), EndLoc(End), TyL(
T) {}
120 ~WebAssemblyOperand()
override {
129 bool isToken()
const override {
return Kind == Token; }
130 bool isImm()
const override {
return Kind == Integer || Kind == Symbol; }
131 bool isFPImm()
const {
return Kind == Float; }
132 bool isMem()
const override {
return false; }
133 bool isReg()
const override {
return false; }
134 bool isBrList()
const {
return Kind == BrList; }
135 bool isCatchList()
const {
return Kind == CatchList; }
136 bool isTypeList()
const {
return Kind == TypeList; }
138 MCRegister
getReg()
const override {
148 SMLoc getStartLoc()
const override {
return StartLoc; }
149 SMLoc getEndLoc()
const override {
return EndLoc; }
151 void addRegOperands(MCInst &,
unsigned)
const {
156 void addImmOperands(MCInst &Inst,
unsigned N)
const {
157 assert(
N == 1 &&
"Invalid number of operands!");
160 else if (Kind == Symbol)
166 void addFPImmf32Operands(MCInst &Inst,
unsigned N)
const {
167 assert(
N == 1 &&
"Invalid number of operands!");
175 void addFPImmf64Operands(MCInst &Inst,
unsigned N)
const {
176 assert(
N == 1 &&
"Invalid number of operands!");
183 void addBrListOperands(MCInst &Inst,
unsigned N)
const {
184 assert(
N == 1 && isBrList() &&
"Invalid BrList!");
185 for (
auto Br : BrL.List)
189 void addCatchListOperands(MCInst &Inst,
unsigned N)
const {
190 assert(
N == 1 && isCatchList() &&
"Invalid CatchList!");
192 for (
auto Ca : CaL.List) {
201 void addTypeListOperands(MCInst &Inst,
unsigned N)
const {
202 assert(
N == 1 && isTypeList() &&
"Invalid TypeList!");
204 for (
auto Ty : TyL.List)
208 void print(raw_ostream &OS,
const MCAsmInfo &MAI)
const override {
211 OS <<
"Tok:" << Tok.Tok;
214 OS <<
"Int:" <<
Int.Val;
217 OS <<
"Flt:" << Flt.Val;
220 OS <<
"Sym:" << Sym.Exp;
223 OS <<
"BrList:" << BrL.List.size();
226 OS <<
"CaList:" << CaL.List.size();
229 OS <<
"TyList:" << TyL.List.size();
243 auto *Sym =
static_cast<MCSymbolWasm *
>(Ctx.lookupSymbol(Name));
245 if (!Sym->isFunctionTable())
246 Ctx.reportError(
SMLoc(),
"symbol is not a wasm funcref table");
248 Sym =
static_cast<MCSymbolWasm *
>(Ctx.getOrCreateSymbol(Name));
273 } CurrentState = FileStart;
289 wasm::WasmSignature Sig;
291 std::vector<Nested> NestingStack;
293 MCSymbolWasm *DefaultFunctionTable =
nullptr;
294 MCSymbol *LastFunctionLabel =
nullptr;
298 WebAssemblyAsmTypeCheck TC;
303 WebAssemblyAsmParser(
const MCSubtargetInfo &STI, MCAsmParser &Parser,
304 const MCInstrInfo &MII)
305 : MCTargetAsmParser(STI, MII), Parser(Parser), Lexer(Parser.getLexer()),
306 Is64(STI.getTargetTriple().isArch64Bit()), TC(Parser, MII, Is64),
307 SkipTypeCheck(Parser.
getContext().getTargetOptions().MCNoTypeCheck) {
308 FeatureBitset FBS = ComputeAvailableFeatures(STI.
getFeatureBits());
311 if (FBS.
test(WebAssembly::FeatureBulkMemory)) {
312 FBS.
set(WebAssembly::FeatureBulkMemoryOpt);
315 if (FBS.
test(WebAssembly::FeatureReferenceTypes)) {
316 FBS.
set(WebAssembly::FeatureCallIndirectOverlong);
319 setAvailableFeatures(FBS);
322 auto &
SM = Parser.getSourceManager();
324 SM.getBufferInfo(
SM.getMainFileID()).Buffer->getBufferIdentifier();
325 if (BufferName ==
"<inline asm>")
326 SkipTypeCheck =
true;
329 void Initialize(MCAsmParser &Parser)
override {
333 getContext(),
"__indirect_function_table", Is64);
336 DefaultFunctionTable->setOmitFromLinkingSection();
339#define GET_ASSEMBLER_HEADER
340#include "WebAssemblyGenAsmMatcher.inc"
346 ParseStatus tryParseRegister(MCRegister &
Reg, SMLoc &StartLoc,
347 SMLoc &EndLoc)
override {
351 bool error(
const Twine &Msg,
const AsmToken &Tok) {
355 bool error(
const Twine &Msg, SMLoc Loc = SMLoc()) {
356 return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg);
359 std::pair<StringRef, StringRef> nestingString(NestingType NT) {
362 return {
"function",
"end_function"};
364 return {
"block",
"end_block"};
366 return {
"loop",
"end_loop"};
368 return {
"try",
"end_try/delegate"};
370 return {
"catch_all",
"end_try"};
372 return {
"try_table",
"end_try_table"};
374 return {
"if",
"end_if"};
376 return {
"else",
"end_if"};
382 void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) {
383 NestingStack.push_back({
NT, Sig});
386 bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
387 if (NestingStack.empty())
388 return error(Twine(
"End of block construct with no start: ") + Ins);
389 auto Top = NestingStack.back();
390 if (Top.NT != NT1 && Top.NT != NT2)
391 return error(Twine(
"Block construct type mismatch, expected: ") +
392 nestingString(Top.NT).second +
", instead got: " + Ins);
393 TC.setLastSig(Top.Sig);
394 NestingStack.pop_back();
400 bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT,
401 NestingType PushNT) {
402 if (NestingStack.empty())
403 return error(Twine(
"End of block construct with no start: ") + Ins);
404 auto Sig = NestingStack.back().Sig;
411 bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {
412 auto Err = !NestingStack.empty();
413 while (!NestingStack.empty()) {
414 error(Twine(
"Unmatched block construct(s) at function end: ") +
415 nestingString(NestingStack.back().NT).first,
417 NestingStack.pop_back();
423 auto Ok = Lexer.is(Kind);
431 return error(std::string(
"Expected ") + KindName +
", instead got: ",
436 StringRef expectIdent() {
438 error(
"Expected identifier, got: ", Lexer.getTok());
441 auto Name = Lexer.getTok().getString();
446 StringRef expectStringOrIdent() {
448 auto Str = Lexer.getTok().getStringContents();
453 auto Name = Lexer.getTok().getString();
457 error(
"Expected string or identifier, got: ", Lexer.getTok());
461 bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
465 return error(
"unknown type: ", Lexer.getTok());
474 void parseSingleInteger(
bool IsNegative,
OperandVector &Operands) {
475 auto &
Int = Lexer.getTok();
476 int64_t Val =
Int.getIntVal();
479 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
480 Int.getLoc(),
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
484 bool parseSingleFloat(
bool IsNegative,
OperandVector &Operands) {
485 auto &Flt = Lexer.getTok();
487 if (Flt.getString().getAsDouble(Val,
false))
488 return error(
"Cannot parse real: ", Flt);
491 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
492 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
497 bool parseSpecialFloatMaybe(
bool IsNegative,
OperandVector &Operands) {
500 auto &Flt = Lexer.getTok();
501 auto S = Flt.getString();
503 if (S.compare_insensitive(
"infinity") == 0) {
504 Val = std::numeric_limits<double>::infinity();
505 }
else if (S.compare_insensitive(
"nan") == 0) {
506 Val = std::numeric_limits<double>::quiet_NaN();
512 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
513 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
519 auto &Tok = Lexer.getTok();
523 Order = StringSwitch<int64_t>(S)
529 return error(
"memory ordering requires relaxed-atomics feature: ",
536 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
541 bool checkForP2AlignIfLoadStore(
OperandVector &Operands, StringRef InstName) {
543 auto IsLoadStore = InstName.
contains(
".load") ||
546 auto IsAtomic = InstName.
contains(
"atomic.");
547 if (IsLoadStore || IsAtomic) {
550 auto Id = expectIdent();
552 return error(
"Expected p2align, instead got: " + Id);
556 return error(
"Expected integer constant");
557 parseSingleInteger(
false, Operands);
562 auto IsLoadStoreLane = InstName.
contains(
"_lane");
563 if (IsLoadStoreLane && Operands.
size() == 4)
569 auto Tok = Lexer.getTok();
570 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
577 void addBlockTypeOperand(
OperandVector &Operands, SMLoc NameLoc,
579 if (
BT == WebAssembly::BlockType::Void) {
580 TC.setLastSig(wasm::WasmSignature{});
584 NestingStack.back().Sig = Sig;
586 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
587 NameLoc, NameLoc, WebAssemblyOperand::IntOp{
static_cast<int64_t
>(
BT)}));
590 bool parseLimits(wasm::WasmLimits *Limits) {
591 auto Tok = Lexer.getTok();
593 return error(
"Expected integer constant, instead got: ", Tok);
601 auto Tok = Lexer.getTok();
603 return error(
"Expected integer constant, instead got: ", Tok);
612 bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *
Op) {
620 auto &Tok = Lexer.getTok();
625 *
Op = std::make_unique<WebAssemblyOperand>(
632 *
Op = std::make_unique<WebAssemblyOperand>(
633 SMLoc(), SMLoc(), WebAssemblyOperand::SymOp{Val});
640 *
Op = std::make_unique<WebAssemblyOperand>(SMLoc(), SMLoc(),
641 WebAssemblyOperand::IntOp{0});
645 bool parseInstruction(ParseInstructionInfo & , StringRef Name,
655 auto &Sep = Lexer.getTok();
656 if (Sep.getLoc().getPointer() !=
Name.end() ||
660 Name = StringRef(
Name.begin(),
Name.size() + Sep.getString().size());
663 auto &
Id = Lexer.getTok();
665 Id.getLoc().getPointer() !=
Name.end())
666 return error(
"Incomplete instruction name: ", Id);
667 Name = StringRef(
Name.begin(),
Name.size() +
Id.getString().size());
672 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
674 WebAssemblyOperand::TokOp{Name}));
678 bool ExpectBlockType =
false;
679 bool ExpectFuncType =
false;
680 bool ExpectCatchList =
false;
681 std::unique_ptr<WebAssemblyOperand> FunctionTable;
682 if (Name ==
"block") {
684 ExpectBlockType =
true;
685 }
else if (Name ==
"loop") {
687 ExpectBlockType =
true;
688 }
else if (Name ==
"try") {
690 ExpectBlockType =
true;
691 }
else if (Name ==
"if") {
693 ExpectBlockType =
true;
694 }
else if (Name ==
"else") {
695 if (popAndPushWithSameSignature(Name, If, Else))
697 }
else if (Name ==
"catch") {
698 if (popAndPushWithSameSignature(Name, Try, Try))
700 }
else if (Name ==
"catch_all") {
701 if (popAndPushWithSameSignature(Name, Try, CatchAll))
703 }
else if (Name ==
"try_table") {
705 ExpectBlockType =
true;
706 ExpectCatchList =
true;
707 }
else if (Name ==
"end_if") {
708 if (pop(Name, If, Else))
710 }
else if (Name ==
"end_try") {
711 if (pop(Name, Try, CatchAll))
713 }
else if (Name ==
"end_try_table") {
714 if (pop(Name, TryTable))
716 }
else if (Name ==
"delegate") {
719 }
else if (Name ==
"end_loop") {
722 }
else if (Name ==
"end_block") {
723 if (pop(Name, Block))
725 }
else if (Name ==
"end_function") {
726 ensureLocals(getStreamer());
727 CurrentState = EndFunction;
728 if (pop(Name, Function) || ensureEmptyNestingStack())
730 }
else if (Name ==
"call_indirect" || Name ==
"return_call_indirect") {
734 if (parseFunctionTableOperand(&FunctionTable))
736 ExpectFuncType =
true;
737 }
else if (Name ==
"call_ref" || Name ==
"return_call_ref") {
740 ExpectFuncType =
true;
741 }
else if (Name ==
"ref.test") {
744 ExpectFuncType =
true;
745 }
else if (Name ==
"ref.cast") {
748 ExpectFuncType =
true;
749 }
else if (Name ==
"select") {
753 auto Op = std::make_unique<WebAssemblyOperand>(
754 Lexer.getLoc(), Lexer.getLoc(), WebAssemblyOperand::TyLOp{});
756 auto &
Id = Lexer.getTok();
759 return error(
"unknown value type in select operand list: ", Id);
760 Op->TyL.List.push_back(
static_cast<uint8_t
>(*Ty));
761 Op->EndLoc =
Id.getEndLoc();
767 if (
Name.contains(
"atomic.")) {
768 if (addMemOrderOrDefault(Operands))
773 auto PeekCatchList = [&]() {
776 AsmToken NextTok = Lexer.peekTok();
782 if (ExpectFuncType ||
789 auto Loc = Parser.getTok();
791 if (parseSignature(Signature))
794 TC.setLastSig(*Signature);
796 NestingStack.back().Sig = *Signature;
797 ExpectBlockType =
false;
800 auto *WasmSym =
static_cast<MCSymbolWasm *
>(Sym);
801 WasmSym->setSignature(Signature);
805 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
806 Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
816 if (ExpectCatchList && PeekCatchList()) {
817 if (ExpectBlockType) {
818 ExpectBlockType =
false;
819 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
821 if (parseCatchList(Operands))
823 ExpectCatchList =
false;
827 auto &Tok = Lexer.getTok();
830 if (!parseSpecialFloatMaybe(
false, Operands))
832 auto &
Id = Lexer.getTok();
833 if (ExpectBlockType) {
836 if (
BT == WebAssembly::BlockType::Invalid)
837 return error(
"Unknown block type: ", Id);
838 addBlockTypeOperand(Operands, NameLoc,
BT);
839 ExpectBlockType =
false;
843 if (ExpectCatchList && PeekCatchList()) {
844 if (parseCatchList(Operands))
846 ExpectCatchList =
false;
853 if (Parser.parseExpression(Val, End))
854 return error(
"Cannot parse symbol: ", Lexer.getTok());
855 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
856 Start, End, WebAssemblyOperand::SymOp{Val}));
857 if (checkForP2AlignIfLoadStore(Operands, Name))
865 parseSingleInteger(
true, Operands);
866 if (checkForP2AlignIfLoadStore(Operands, Name))
869 if (parseSingleFloat(
true, Operands))
871 }
else if (!parseSpecialFloatMaybe(
true, Operands)) {
873 return error(
"Expected numeric constant instead got: ",
878 parseSingleInteger(
false, Operands);
879 if (checkForP2AlignIfLoadStore(Operands, Name))
883 if (parseSingleFloat(
false, Operands))
889 auto Op = std::make_unique<WebAssemblyOperand>(
893 Op->BrL.List.push_back(Lexer.getTok().getIntVal());
903 return error(
"Unexpected token in operand: ", Tok);
916 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
919 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
920 NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));
923 Operands.
push_back(std::move(FunctionTable));
928 bool parseSignature(wasm::WasmSignature *Signature) {
931 if (parseRegTypeList(Signature->
Params))
939 if (parseRegTypeList(Signature->
Returns))
947 auto Op = std::make_unique<WebAssemblyOperand>(
948 Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});
955 auto CatchStr = expectIdent();
956 if (CatchStr.empty())
958 uint8_t CatchOpcode =
959 StringSwitch<uint8_t>(CatchStr)
965 if (CatchOpcode == 0xff)
967 "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
970 const MCExpr *
Tag =
nullptr;
973 if (Parser.parseExpression(
Tag))
974 return error(
"Cannot parse symbol: ", Lexer.getTok());
977 auto &DestTok = Lexer.getTok();
979 return error(
"Expected integer constant, instead got: ", DestTok);
980 unsigned Dest = DestTok.getIntVal();
983 EndLoc = Lexer.getTok().getEndLoc();
987 Op->CaL.List.push_back({CatchOpcode,
Tag, Dest});
995 bool checkDataSection() {
996 if (CurrentState != DataSection) {
997 auto *WS =
static_cast<const MCSectionWasm *
>(
998 getStreamer().getCurrentSectionOnly());
999 if (WS && WS->isText())
1000 return error(
"data directive must occur in a data segment: ",
1003 CurrentState = DataSection;
1010 ParseStatus parseDirective(AsmToken DirectiveID)
override {
1012 auto &Out = getStreamer();
1014 reinterpret_cast<WebAssemblyTargetStreamer &
>(*Out.getTargetStreamer());
1015 auto &Ctx = Out.getContext();
1017 if (DirectiveID.
getString() ==
".globaltype") {
1018 auto SymName = expectIdent();
1019 if (SymName.empty())
1023 auto TypeTok = Lexer.getTok();
1029 return error(
"Unknown type in .globaltype directive: ", TypeTok);
1033 bool Mutable =
true;
1035 TypeTok = Lexer.getTok();
1036 auto Id = expectIdent();
1039 if (Id ==
"immutable")
1043 return error(
"Unknown type in .globaltype modifier: ", TypeTok);
1049 WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(*
Type), Mutable});
1051 TOut.emitGlobalType(WasmSym);
1055 if (DirectiveID.
getString() ==
".tabletype") {
1057 auto SymName = expectIdent();
1058 if (SymName.empty())
1063 auto ElemTypeTok = Lexer.getTok();
1064 auto ElemTypeName = expectIdent();
1065 if (ElemTypeName.empty())
1067 std::optional<wasm::ValType> ElemType =
1070 return error(
"Unknown type in .tabletype directive: ", ElemTypeTok);
1072 wasm::WasmLimits Limits = defaultLimits();
1084 wasm::WasmTableType
Type = {*ElemType, Limits};
1085 WasmSym->setTableType(
Type);
1086 TOut.emitTableType(WasmSym);
1090 if (DirectiveID.
getString() ==
".functype") {
1096 auto SymName = expectIdent();
1097 if (SymName.empty())
1101 if (WasmSym->isDefined()) {
1112 if (CurrentState != FunctionLabel) {
1114 if (ensureEmptyNestingStack())
1118 CurrentState = FunctionStart;
1119 LastFunctionLabel = WasmSym;
1122 if (parseSignature(Signature))
1124 if (CurrentState == FunctionStart)
1125 TC.funcDecl(*Signature);
1126 WasmSym->setSignature(Signature);
1128 TOut.emitFunctionType(WasmSym);
1133 if (DirectiveID.
getString() ==
".export_name") {
1134 auto SymName = expectIdent();
1135 if (SymName.empty())
1139 auto ExportName = expectStringOrIdent();
1140 if (ExportName.empty())
1145 TOut.emitExportName(WasmSym, ExportName);
1149 if (DirectiveID.
getString() ==
".import_module") {
1150 auto SymName = expectIdent();
1151 if (SymName.empty())
1155 auto ImportModule = expectStringOrIdent();
1156 if (ImportModule.empty())
1161 TOut.emitImportModule(WasmSym, ImportModule);
1165 if (DirectiveID.
getString() ==
".import_name") {
1166 auto SymName = expectIdent();
1167 if (SymName.empty())
1171 StringRef ImportName = expectStringOrIdent();
1172 if (ImportName.
empty())
1177 TOut.emitImportName(WasmSym, ImportName);
1181 if (DirectiveID.
getString() ==
".tagtype") {
1182 auto SymName = expectIdent();
1183 if (SymName.empty())
1188 if (parseRegTypeList(Signature->
Params))
1190 WasmSym->setSignature(Signature);
1192 TOut.emitTagType(WasmSym);
1197 if (DirectiveID.
getString() ==
".local") {
1198 if (CurrentState != FunctionStart)
1199 return error(
".local directive should follow the start of a function: ",
1202 if (parseRegTypeList(Locals))
1204 TC.localDecl(Locals);
1205 TOut.emitLocal(Locals);
1206 CurrentState = FunctionLocals;
1210 if (DirectiveID.
getString() ==
".int8" ||
1214 if (checkDataSection())
1218 if (Parser.parseExpression(Val, End))
1219 return error(
"Cannot parse .int expression: ", Lexer.getTok());
1222 Out.emitValue(Val, NumBits / 8, End);
1226 if (DirectiveID.
getString() ==
".asciz") {
1227 if (checkDataSection())
1230 if (Parser.parseEscapedString(S))
1231 return error(
"Cannot parse string constant: ", Lexer.getTok());
1232 Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
1240 void ensureLocals(MCStreamer &Out) {
1241 if (CurrentState == FunctionStart) {
1245 auto &TOut =
reinterpret_cast<WebAssemblyTargetStreamer &
>(
1248 CurrentState = FunctionLocals;
1252 bool matchAndEmitInstruction(SMLoc IDLoc,
unsigned & ,
1254 uint64_t &ErrorInfo,
1255 bool MatchingInlineAsm)
override {
1258 FeatureBitset MissingFeatures;
1259 unsigned MatchResult = MatchInstructionImpl(
1260 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
1261 switch (MatchResult) {
1262 case Match_Success: {
1270 for (
unsigned E =
Desc.getNumOperands();
I <
E; ++
I) {
1273 if (
Op.getImm() == -1) {
1279 assert(
I < 2 &&
"Default p2align set but operand not found");
1286 static_cast<uint16_t
>(Inst.
getOpcode()));
1292 TC.typeCheck(IDLoc, Inst, Operands);
1294 if (CurrentState == EndFunction) {
1295 onEndOfFunction(IDLoc);
1297 CurrentState = Instructions;
1301 case Match_MissingFeature: {
1302 assert(MissingFeatures.
count() > 0 &&
"Expected missing features");
1303 SmallString<128> Message;
1304 raw_svector_ostream OS(Message);
1305 OS <<
"instruction requires:";
1306 for (
unsigned I = 0,
E = MissingFeatures.
size();
I !=
E; ++
I)
1307 if (MissingFeatures.
test(
I))
1309 return Parser.Error(IDLoc, Message);
1311 case Match_MnemonicFail:
1312 return Parser.Error(IDLoc,
"invalid instruction");
1313 case Match_NearMisses:
1314 return Parser.Error(IDLoc,
"ambiguous instruction");
1315 case Match_InvalidTiedOperand:
1316 case Match_InvalidOperand: {
1317 SMLoc ErrorLoc = IDLoc;
1318 if (ErrorInfo != ~0ULL) {
1319 if (ErrorInfo >= Operands.
size())
1320 return Parser.Error(IDLoc,
"too few operands for instruction");
1321 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
1322 if (ErrorLoc == SMLoc())
1325 return Parser.Error(ErrorLoc,
"invalid operand for instruction");
1331 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc)
override {
1333 auto *CWS =
static_cast<const MCSectionWasm *
>(
1334 getStreamer().getCurrentSectionOnly());
1338 auto *WasmSym =
static_cast<MCSymbolWasm *
>(
Symbol);
1343 "Wasm doesn\'t support data symbols in text sections");
1350 auto SymName =
Symbol->getName();
1351 if (SymName.starts_with(
".L"))
1358 std::string SecName = (
".text." + SymName).str();
1360 auto *Group = CWS->getGroup();
1366 WasmSym->setComdat(
true);
1369 getStreamer().switchSection(WS);
1374 if (WasmSym->isFunction()) {
1384 ensureEmptyNestingStack(IDLoc);
1385 CurrentState = FunctionLabel;
1386 LastFunctionLabel =
Symbol;
1391 void onEndOfFunction(SMLoc ErrorLoc) {
1393 TC.endOfFunction(ErrorLoc,
true);
1398 void onEndOfFile()
override { ensureEmptyNestingStack(); }
1409#define GET_REGISTER_MATCHER
1410#define GET_SUBTARGET_FEATURE_NAME
1411#define GET_MATCHER_IMPLEMENTATION
1412#include "WebAssemblyGenAsmMatcher.inc"
1416 for (
auto &ME : MatchTable0) {
1417 if (ME.Opcode ==
Opc) {
1418 return ME.getMnemonic();
1421 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")
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)
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
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