39#define DEBUG_TYPE "wasm-asm-parser"
48 : Parser(Parser), MII(MII), is64(is64) {}
58 LocalTypes.
insert(LocalTypes.
end(), Locals.begin(), Locals.end());
61void WebAssemblyAsmTypeCheck::dumpTypeStack(
Twine Msg) {
64 for (
auto VT : Stack) {
68 dbgs() << Msg << s <<
'\n';
72bool WebAssemblyAsmTypeCheck::typeError(
SMLoc ErrorLoc,
const Twine &Msg) {
75 if (TypeErrorThisFunction)
80 TypeErrorThisFunction =
true;
81 dumpTypeStack(
"current stack: ");
82 return Parser.
Error(ErrorLoc, Msg);
85bool WebAssemblyAsmTypeCheck::popType(
SMLoc ErrorLoc,
86 std::optional<wasm::ValType>
EVT) {
88 return typeError(ErrorLoc,
91 :
StringRef(
"empty stack while popping value"));
95 return typeError(ErrorLoc,
102bool WebAssemblyAsmTypeCheck::popRefType(
SMLoc ErrorLoc) {
104 return typeError(ErrorLoc,
StringRef(
"empty stack while popping reftype"));
108 return typeError(ErrorLoc,
StringRef(
"popped ") +
110 ", expected reftype");
115bool WebAssemblyAsmTypeCheck::getLocal(
SMLoc ErrorLoc,
const MCInst &Inst,
118 if (Local >= LocalTypes.
size())
119 return typeError(ErrorLoc,
StringRef(
"no local type specified for index ") +
120 std::to_string(Local));
125static std::optional<std::string>
128 for (
size_t I = 0;
I < ExpectedStackTop.
size();
I++) {
129 auto EVT = ExpectedStackTop[
I];
130 auto PVT = Got[Got.
size() - ExpectedStackTop.
size() +
I];
138bool WebAssemblyAsmTypeCheck::checkBr(
SMLoc ErrorLoc,
size_t Level) {
139 if (Level >= BrStack.size())
140 return typeError(ErrorLoc,
141 StringRef(
"br: invalid depth ") + std::to_string(Level));
143 BrStack[BrStack.size() - Level - 1];
145 return typeError(ErrorLoc,
"br: insufficient values on the type stack");
147 if (IsStackTopInvalid)
148 return typeError(ErrorLoc,
"br " + IsStackTopInvalid.value());
152bool WebAssemblyAsmTypeCheck::checkEnd(
SMLoc ErrorLoc,
bool PopVals) {
156 return typeError(ErrorLoc,
"end: insufficient values on the type stack");
160 if (popType(ErrorLoc, VT))
167 if (IsStackTopInvalid)
168 return typeError(ErrorLoc,
"end " + IsStackTopInvalid.value());
172bool WebAssemblyAsmTypeCheck::checkSig(
SMLoc ErrorLoc,
175 if (popType(ErrorLoc, VT))
181bool WebAssemblyAsmTypeCheck::getSymRef(
SMLoc ErrorLoc,
const MCInst &Inst,
185 return typeError(ErrorLoc,
StringRef(
"expected expression operand"));
186 SymRef = dyn_cast<MCSymbolRefExpr>(
Op.getExpr());
188 return typeError(ErrorLoc,
StringRef(
"expected symbol operand"));
192bool WebAssemblyAsmTypeCheck::getGlobal(
SMLoc ErrorLoc,
const MCInst &Inst,
195 if (getSymRef(ErrorLoc, Inst, SymRef))
197 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
214 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
215 " missing .globaltype");
220bool WebAssemblyAsmTypeCheck::getTable(
SMLoc ErrorLoc,
const MCInst &Inst,
223 if (getSymRef(ErrorLoc, Inst, SymRef))
225 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
228 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
229 " missing .tabletype");
237 if (popType(ErrorLoc, RVT))
240 if (!Stack.
empty()) {
241 return typeError(ErrorLoc, std::to_string(Stack.
size()) +
242 " superfluous return values");
252 dumpTypeStack(
"typechecking " +
Name +
": ");
254 if (
Name ==
"local.get") {
258 }
else if (
Name ==
"local.set") {
261 if (popType(ErrorLoc,
Type))
263 }
else if (
Name ==
"local.tee") {
266 if (popType(ErrorLoc,
Type))
269 }
else if (
Name ==
"global.get") {
273 }
else if (
Name ==
"global.set") {
276 if (popType(ErrorLoc,
Type))
278 }
else if (
Name ==
"table.get") {
284 }
else if (
Name ==
"table.set") {
287 if (popType(ErrorLoc,
Type))
291 }
else if (
Name ==
"table.size") {
295 }
else if (
Name ==
"table.grow") {
300 if (popType(ErrorLoc,
Type))
303 }
else if (
Name ==
"table.fill") {
308 if (popType(ErrorLoc,
Type))
312 }
else if (
Name ==
"memory.fill") {
314 if (popType(ErrorLoc,
Type))
318 if (popType(ErrorLoc,
Type))
320 }
else if (
Name ==
"memory.copy") {
322 if (popType(ErrorLoc,
Type))
324 if (popType(ErrorLoc,
Type))
326 if (popType(ErrorLoc,
Type))
328 }
else if (
Name ==
"memory.init") {
334 if (popType(ErrorLoc,
Type))
336 }
else if (
Name ==
"drop") {
337 if (popType(ErrorLoc, {}))
339 }
else if (
Name ==
"try" ||
Name ==
"block" ||
Name ==
"loop" ||
347 }
else if (
Name ==
"end_block" ||
Name ==
"end_loop" ||
Name ==
"end_if" ||
348 Name ==
"else" ||
Name ==
"end_try" ||
Name ==
"catch" ||
349 Name ==
"catch_all" ||
Name ==
"delegate") {
350 if (checkEnd(ErrorLoc,
351 Name ==
"else" ||
Name ==
"catch" ||
Name ==
"catch_all"))
354 if (
Name ==
"catch") {
356 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
358 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
359 const auto *Sig = WasmSym->getSignature();
363 " missing .tagtype");
368 }
else if (
Name ==
"br") {
370 if (!Operand.
isImm())
372 if (checkBr(ErrorLoc,
static_cast<size_t>(Operand.
getImm())))
374 }
else if (
Name ==
"return") {
377 }
else if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
381 if (checkSig(ErrorLoc, LastSig))
385 }
else if (
Name ==
"call" ||
Name ==
"return_call") {
387 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
389 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
390 auto Sig = WasmSym->getSignature();
394 " missing .functype");
395 if (checkSig(ErrorLoc, *Sig))
399 }
else if (
Name ==
"unreachable") {
401 }
else if (
Name ==
"ref.is_null") {
402 if (popRefType(ErrorLoc))
410 assert(RegOpc != -1 &&
"Failed to get register version of MC instruction");
411 const auto &
II = MII.
get(RegOpc);
413 for (
unsigned I =
II.getNumOperands();
I >
II.getNumDefs();
I--) {
414 const auto &
Op =
II.operands()[
I - 1];
417 if (popType(ErrorLoc, VT))
422 for (
unsigned I = 0;
I <
II.getNumDefs();
I++) {
423 const auto &
Op =
II.operands()[
I];
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.
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