39#define DEBUG_TYPE "wasm-asm-parser"
48 : Parser(Parser), MII(MII), Is64(Is64) {}
52 BlockInfoStack.
push_back({Sig, 0,
false});
57 LocalTypes.
insert(LocalTypes.
end(), Locals.begin(), Locals.end());
60void WebAssemblyAsmTypeCheck::dumpTypeStack(
Twine Msg) {
64bool WebAssemblyAsmTypeCheck::typeError(
SMLoc ErrorLoc,
const Twine &Msg) {
65 dumpTypeStack(
"current stack: ");
66 return Parser.
Error(ErrorLoc, Msg);
69bool WebAssemblyAsmTypeCheck::match(StackType TypeA, StackType TypeB) {
71 assert(!std::get_if<Polymorphic>(&TypeA) &&
72 !std::get_if<Polymorphic>(&TypeB));
76 if (std::get_if<Any>(&TypeA) || std::get_if<Any>(&TypeB))
79 if (std::get_if<Ref>(&TypeB))
81 assert(std::get_if<wasm::ValType>(&TypeB));
82 if (std::get_if<Ref>(&TypeA) &&
91 for (
auto I =
Types.size();
I > StartPos;
I--) {
92 if (std::get_if<Polymorphic>(&Types[
I - 1])) {
96 if (std::get_if<Any>(&Types[
I - 1]))
98 else if (std::get_if<Ref>(&Types[
I - 1]))
105 std::stringstream
SS;
108 for (
auto It = TypeStrs.
rbegin(); It != TypeStrs.
rend(); ++It) {
121 return getTypesString(valTypesToStackTypes(Types), StartPos);
125WebAssemblyAsmTypeCheck::valTypesToStackTypes(
128 std::transform(ValTypes.
begin(), ValTypes.
end(),
Types.begin(),
133bool WebAssemblyAsmTypeCheck::checkTypes(
SMLoc ErrorLoc,
136 return checkTypes(ErrorLoc, valTypesToStackTypes(ValTypes), ExactMatch);
139bool WebAssemblyAsmTypeCheck::checkTypes(
SMLoc ErrorLoc,
142 auto StackI = Stack.
size();
143 auto TypeI =
Types.size();
145 auto BlockStackStartPos = BlockInfoStack.
back().StackStartPos;
147 bool PolymorphicStack =
false;
149 for (; StackI > BlockStackStartPos && TypeI > 0; StackI--, TypeI--) {
152 if (std::get_if<Polymorphic>(&Stack[StackI - 1])) {
156 if (match(Stack[StackI - 1], Types[TypeI - 1])) {
163 if (StackI > BlockStackStartPos &&
164 std::get_if<Polymorphic>(&Stack[StackI - 1]))
165 PolymorphicStack =
true;
176 (ExactMatch && !PolymorphicStack && StackI > BlockStackStartPos))
182 auto StackStartPos = ExactMatch
184 : std::max((
int)BlockStackStartPos,
186 return typeError(ErrorLoc,
"type mismatch, expected " +
187 getTypesString(Types) +
" but got " +
188 getTypesString(Stack, StackStartPos));
191bool WebAssemblyAsmTypeCheck::popTypes(
SMLoc ErrorLoc,
194 return popTypes(ErrorLoc, valTypesToStackTypes(ValTypes), ExactMatch);
197bool WebAssemblyAsmTypeCheck::popTypes(
SMLoc ErrorLoc,
200 bool Error = checkTypes(ErrorLoc, Types, ExactMatch);
201 auto NumPops = std::min(Stack.
size() - BlockInfoStack.
back().StackStartPos,
203 for (
size_t I = 0, E = NumPops;
I != E;
I++) {
204 if (std::get_if<Polymorphic>(&Stack.
back()))
211bool WebAssemblyAsmTypeCheck::popType(
SMLoc ErrorLoc, StackType
Type) {
212 return popTypes(ErrorLoc, {
Type});
215bool WebAssemblyAsmTypeCheck::popRefType(
SMLoc ErrorLoc) {
216 return popType(ErrorLoc, Ref{});
219bool WebAssemblyAsmTypeCheck::popAnyType(
SMLoc ErrorLoc) {
220 return popType(ErrorLoc,
Any{});
224 Stack.
append(valTypesToStackTypes(ValTypes));
227bool WebAssemblyAsmTypeCheck::getLocal(
SMLoc ErrorLoc,
const MCOperand &LocalOp,
229 auto Local =
static_cast<size_t>(LocalOp.
getImm());
231 return typeError(ErrorLoc,
StringRef(
"no local type specified for index ") +
232 std::to_string(
Local));
237bool WebAssemblyAsmTypeCheck::checkSig(
SMLoc ErrorLoc,
244bool WebAssemblyAsmTypeCheck::getSymRef(
SMLoc ErrorLoc,
const MCOperand &SymOp,
247 return typeError(ErrorLoc,
StringRef(
"expected expression operand"));
248 SymRef = dyn_cast<MCSymbolRefExpr>(SymOp.
getExpr());
250 return typeError(ErrorLoc,
StringRef(
"expected symbol operand"));
254bool WebAssemblyAsmTypeCheck::getGlobal(
SMLoc ErrorLoc,
258 if (getSymRef(ErrorLoc, GlobalOp, SymRef))
260 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
277 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
278 ": missing .globaltype");
283bool WebAssemblyAsmTypeCheck::getTable(
SMLoc ErrorLoc,
const MCOperand &TableOp,
286 if (getSymRef(ErrorLoc, TableOp, SymRef))
288 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
291 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
292 ": missing .tabletype");
297bool WebAssemblyAsmTypeCheck::getSignature(
SMLoc ErrorLoc,
302 if (getSymRef(ErrorLoc, SigOp, SymRef))
304 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
305 Sig = WasmSym->getSignature();
307 if (!Sig || WasmSym->getType() !=
Type) {
319 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
320 ": missing ." + TypeName +
"type");
327 const auto &FuncInfo = BlockInfoStack[0];
328 return checkTypes(ErrorLoc, FuncInfo.Sig.Returns, ExactMatch);
337 for (
size_t I = 0, E = TypesA.
size();
I < E;
I++)
338 if (TypesA[
I] != TypesB[
I])
343bool WebAssemblyAsmTypeCheck::checkTryTable(
SMLoc ErrorLoc,
348 for (int64_t
I = 0;
I < NumCatches;
I++) {
350 std::string ErrorMsgBase =
351 "try_table: catch index " + std::to_string(
I) +
": ";
357 if (!getSignature(ErrorLoc, Inst.
getOperand(OpIdx++),
370 if (Level < BlockInfoStack.
size()) {
371 const auto &DestBlockInfo =
372 BlockInfoStack[BlockInfoStack.
size() - Level - 1];
374 if (DestBlockInfo.IsLoop)
375 DestTypes = DestBlockInfo.Sig.Params;
377 DestTypes = DestBlockInfo.Sig.Returns;
379 std::string ErrorMsg =
380 ErrorMsgBase +
"type mismatch, catch tag type is " +
381 getTypesString(SentTypes) +
", but destination's type is " +
382 getTypesString(DestTypes);
383 Error |= typeError(ErrorLoc, ErrorMsg);
386 Error = typeError(ErrorLoc, ErrorMsgBase +
"invalid depth " +
387 std::to_string(Level));
397 dumpTypeStack(
"typechecking " +
Name +
": ");
400 if (
Name ==
"local.get") {
409 if (
Name ==
"local.set") {
411 return popType(ErrorLoc,
Type);
412 popType(ErrorLoc,
Any{});
416 if (
Name ==
"local.tee") {
422 popType(ErrorLoc,
Any{});
427 if (
Name ==
"global.get") {
436 if (
Name ==
"global.set") {
438 return popType(ErrorLoc,
Type);
439 popType(ErrorLoc,
Any{});
443 if (
Name ==
"table.get") {
453 if (
Name ==
"table.set") {
463 Error |= popTypes(ErrorLoc, PopTypes);
467 if (
Name ==
"table.size") {
473 if (
Name ==
"table.grow") {
483 Error |= popTypes(ErrorLoc, PopTypes);
488 if (
Name ==
"table.fill") {
499 Error |= popTypes(ErrorLoc, PopTypes);
503 if (
Name ==
"memory.fill") {
511 if (
Name ==
"memory.copy") {
519 if (
Name ==
"memory.init") {
527 if (
Name ==
"drop") {
528 return popType(ErrorLoc,
Any{});
532 Name ==
"try_table") {
536 if (
Name ==
"try_table")
537 Error |= checkTryTable(ErrorLoc, Inst);
541 pushTypes(LastSig.
Params);
545 if (
Name ==
"end_block" ||
Name ==
"end_loop" ||
Name ==
"end_if" ||
546 Name ==
"end_try" ||
Name ==
"delegate" ||
Name ==
"end_try_table" ||
547 Name ==
"else" ||
Name ==
"catch" ||
Name ==
"catch_all") {
550 const auto &LastBlockInfo = BlockInfoStack.
back();
551 bool Error = checkTypes(ErrorLoc, LastBlockInfo.Sig.Returns,
true);
553 Stack.
truncate(LastBlockInfo.StackStartPos);
554 if (
Name ==
"else") {
557 pushTypes(LastBlockInfo.Sig.Params);
558 }
else if (
Name ==
"catch") {
567 }
else if (
Name ==
"catch_all") {
572 pushTypes(LastBlockInfo.Sig.Returns);
578 if (
Name ==
"br" ||
Name ==
"br_if") {
583 if (Operand.
isImm()) {
584 unsigned Level = Operand.
getImm();
585 if (Level < BlockInfoStack.
size()) {
586 const auto &DestBlockInfo =
587 BlockInfoStack[BlockInfoStack.
size() - Level - 1];
588 if (DestBlockInfo.IsLoop)
589 Error |= checkTypes(ErrorLoc, DestBlockInfo.Sig.Params,
false);
591 Error |= checkTypes(ErrorLoc, DestBlockInfo.Sig.Returns,
false);
594 std::to_string(Level));
598 typeError(
Operands[1]->getStartLoc(),
"depth should be an integer");
601 pushType(Polymorphic{});
605 if (
Name ==
"return") {
607 pushType(Polymorphic{});
611 if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
614 Error |= checkSig(ErrorLoc, LastSig);
615 if (
Name ==
"return_call_indirect") {
617 pushType(Polymorphic{});
622 if (
Name ==
"call" ||
Name ==
"return_call") {
627 Error |= checkSig(ErrorLoc, *Sig);
630 if (
Name ==
"return_call") {
632 pushType(Polymorphic{});
637 if (
Name ==
"unreachable") {
638 pushType(Polymorphic{});
642 if (
Name ==
"ref.is_null") {
643 bool Error = popRefType(ErrorLoc);
648 if (
Name ==
"throw") {
653 Error |= checkSig(ErrorLoc, *Sig);
656 pushType(Polymorphic{});
660 if (
Name ==
"throw_ref") {
662 pushType(Polymorphic{});
670 assert(RegOpc != -1 &&
"Failed to get register version of MC instruction");
671 const auto &
II = MII.
get(RegOpc);
674 for (
unsigned I =
II.getNumDefs();
I <
II.getNumOperands();
I++) {
675 const auto &
Op =
II.operands()[
I];
679 bool Error = popTypes(ErrorLoc, PopTypes);
682 for (
unsigned I = 0;
I <
II.getNumDefs();
I++) {
683 const auto &
Op =
II.operands()[
I];
687 pushTypes(PushTypes);
mir Rename Register Operands
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef getMnemonic(unsigned Opc)
StringRef getMnemonic(unsigned Opc)
This file is part of the WebAssembly Assembler.
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class represents an Operation in the Expression.
Lightweight error class with error context and mandatory checking.
Generic assembler parser interface, for use by target specific assembly parsers.
bool Error(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)
Return an error at the location L, with the message Msg.
Instances of this class represent a single low-level machine instruction.
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Instances of this class represent operands of the MCInst class.
const MCExpr * getExpr() const
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
Represents a location in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void truncate(size_type N)
Like resize, but requires that N is less than size().
void push_back(const T &Elt)
reverse_iterator rbegin()
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool endOfFunction(SMLoc ErrorLoc, bool ExactMatch)
WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool Is64)
void funcDecl(const wasm::WasmSignature &Sig)
void localDecl(const SmallVectorImpl< wasm::ValType > &Locals)
bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst, OperandVector &Operands)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
const char * typeToString(wasm::ValType Type)
wasm::ValType regClassToValType(unsigned RC)
bool isRefType(wasm::ValType Type)
int getRegisterOpcode(unsigned short Opcode)
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_FUNCTION
@ WASM_OPCODE_CATCH_ALL_REF
This is an optimization pass for GlobalISel generic memory operations.
static bool compareTypes(ArrayRef< wasm::ValType > TypesA, ArrayRef< wasm::ValType > TypesB)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params