40#define DEBUG_TYPE "wasm-asm-parser"
49 : Parser(Parser), MII(MII), is64(is64) {}
59 LocalTypes.
insert(LocalTypes.
end(), Locals.begin(), Locals.end());
62void WebAssemblyAsmTypeCheck::dumpTypeStack(
Twine Msg) {
65 for (
auto VT : Stack) {
69 dbgs() << Msg << s <<
'\n';
73bool WebAssemblyAsmTypeCheck::typeError(
SMLoc ErrorLoc,
const Twine &Msg) {
76 if (TypeErrorThisFunction)
81 TypeErrorThisFunction =
true;
82 dumpTypeStack(
"current stack: ");
83 return Parser.
Error(ErrorLoc, Msg);
86bool WebAssemblyAsmTypeCheck::popType(
SMLoc ErrorLoc,
87 std::optional<wasm::ValType>
EVT) {
89 return typeError(ErrorLoc,
92 :
StringRef(
"empty stack while popping value"));
96 return typeError(ErrorLoc,
103bool WebAssemblyAsmTypeCheck::popRefType(
SMLoc ErrorLoc) {
105 return typeError(ErrorLoc,
StringRef(
"empty stack while popping reftype"));
109 return typeError(ErrorLoc,
StringRef(
"popped ") +
111 ", expected reftype");
116bool WebAssemblyAsmTypeCheck::getLocal(
SMLoc ErrorLoc,
const MCInst &Inst,
119 if (Local >= LocalTypes.
size())
120 return typeError(ErrorLoc,
StringRef(
"no local type specified for index ") +
121 std::to_string(Local));
126static std::optional<std::string>
129 for (
size_t I = 0;
I < ExpectedStackTop.
size();
I++) {
130 auto EVT = ExpectedStackTop[
I];
131 auto PVT = Got[Got.
size() - ExpectedStackTop.
size() +
I];
139bool WebAssemblyAsmTypeCheck::checkBr(
SMLoc ErrorLoc,
size_t Level) {
140 if (Level >= BrStack.size())
141 return typeError(ErrorLoc,
142 StringRef(
"br: invalid depth ") + std::to_string(Level));
144 BrStack[BrStack.size() - Level - 1];
146 return typeError(ErrorLoc,
"br: insufficient values on the type stack");
148 if (IsStackTopInvalid)
149 return typeError(ErrorLoc,
"br " + IsStackTopInvalid.value());
153bool WebAssemblyAsmTypeCheck::checkEnd(
SMLoc ErrorLoc,
bool PopVals) {
157 return typeError(ErrorLoc,
"end: insufficient values on the type stack");
161 if (popType(ErrorLoc, VT))
168 if (IsStackTopInvalid)
169 return typeError(ErrorLoc,
"end " + IsStackTopInvalid.value());
173bool WebAssemblyAsmTypeCheck::checkSig(
SMLoc ErrorLoc,
176 if (popType(ErrorLoc, VT))
182bool WebAssemblyAsmTypeCheck::getSymRef(
SMLoc ErrorLoc,
const MCInst &Inst,
186 return typeError(ErrorLoc,
StringRef(
"expected expression operand"));
187 SymRef = dyn_cast<MCSymbolRefExpr>(
Op.getExpr());
189 return typeError(ErrorLoc,
StringRef(
"expected symbol operand"));
193bool WebAssemblyAsmTypeCheck::getGlobal(
SMLoc ErrorLoc,
const MCInst &Inst,
196 if (getSymRef(ErrorLoc, Inst, SymRef))
198 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
215 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
216 " missing .globaltype");
221bool WebAssemblyAsmTypeCheck::getTable(
SMLoc ErrorLoc,
const MCInst &Inst,
224 if (getSymRef(ErrorLoc, Inst, SymRef))
226 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
229 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
230 " missing .tabletype");
238 if (popType(ErrorLoc, RVT))
241 if (!Stack.
empty()) {
242 return typeError(ErrorLoc, std::to_string(Stack.
size()) +
243 " superfluous return values");
253 dumpTypeStack(
"typechecking " +
Name +
": ");
255 if (
Name ==
"local.get") {
259 }
else if (
Name ==
"local.set") {
262 if (popType(ErrorLoc,
Type))
264 }
else if (
Name ==
"local.tee") {
267 if (popType(ErrorLoc,
Type))
270 }
else if (
Name ==
"global.get") {
274 }
else if (
Name ==
"global.set") {
277 if (popType(ErrorLoc,
Type))
279 }
else if (
Name ==
"table.get") {
285 }
else if (
Name ==
"table.set") {
288 if (popType(ErrorLoc,
Type))
292 }
else if (
Name ==
"table.fill") {
297 if (popType(ErrorLoc,
Type))
301 }
else if (
Name ==
"memory.fill") {
303 if (popType(ErrorLoc,
Type))
307 if (popType(ErrorLoc,
Type))
309 }
else if (
Name ==
"memory.copy") {
311 if (popType(ErrorLoc,
Type))
313 if (popType(ErrorLoc,
Type))
315 if (popType(ErrorLoc,
Type))
317 }
else if (
Name ==
"memory.init") {
323 if (popType(ErrorLoc,
Type))
325 }
else if (
Name ==
"drop") {
326 if (popType(ErrorLoc, {}))
328 }
else if (
Name ==
"try" ||
Name ==
"block" ||
Name ==
"loop" ||
336 }
else if (
Name ==
"end_block" ||
Name ==
"end_loop" ||
Name ==
"end_if" ||
337 Name ==
"else" ||
Name ==
"end_try" ||
Name ==
"catch" ||
338 Name ==
"catch_all" ||
Name ==
"delegate") {
339 if (checkEnd(ErrorLoc,
340 Name ==
"else" ||
Name ==
"catch" ||
Name ==
"catch_all"))
343 if (
Name ==
"catch") {
345 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
347 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
348 const auto *Sig = WasmSym->getSignature();
352 " missing .tagtype");
357 }
else if (
Name ==
"br") {
359 if (!Operand.
isImm())
361 if (checkBr(ErrorLoc,
static_cast<size_t>(Operand.
getImm())))
363 }
else if (
Name ==
"return") {
366 }
else if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
370 if (checkSig(ErrorLoc, LastSig))
374 }
else if (
Name ==
"call" ||
Name ==
"return_call") {
376 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
378 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
379 auto Sig = WasmSym->getSignature();
383 " missing .functype");
384 if (checkSig(ErrorLoc, *Sig))
388 }
else if (
Name ==
"unreachable") {
390 }
else if (
Name ==
"ref.is_null") {
391 if (popRefType(ErrorLoc))
399 assert(RegOpc != -1 &&
"Failed to get register version of MC instruction");
400 const auto &II = MII.
get(RegOpc);
402 for (
unsigned I = II.getNumOperands();
I > II.getNumDefs();
I--) {
403 const auto &
Op = II.operands()[
I - 1];
406 if (popType(ErrorLoc, VT))
411 for (
unsigned I = 0;
I < II.getNumDefs();
I++) {
412 const auto &
Op = II.operands()[
I];
mir Rename Register Operands
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.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
This class represents an Operation in the Expression.
Tagged union holding either a T or a Error.
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.
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)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
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)
void funcDecl(const wasm::WasmSignature &Sig)
void localDecl(const SmallVectorImpl< wasm::ValType > &Locals)
WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool is64)
bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst, OperandVector &Operands)
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
This is an optimization pass for GlobalISel generic memory operations.
static std::optional< std::string > checkStackTop(const SmallVectorImpl< wasm::ValType > &ExpectedStackTop, const SmallVectorImpl< wasm::ValType > &Got)
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params