@@ -59,7 +59,7 @@ void WebAssemblyAsmTypeCheck::localDecl(
5959}
6060
6161void WebAssemblyAsmTypeCheck::dumpTypeStack (Twine Msg) {
62- LLVM_DEBUG ({ dbgs () << Msg << getTypesString (Stack, 0 ) << " \n " ; });
62+ LLVM_DEBUG ({ dbgs () << Msg << getTypesString (Stack) << " \n " ; });
6363}
6464
6565bool WebAssemblyAsmTypeCheck::typeError (SMLoc ErrorLoc, const Twine &Msg) {
@@ -116,8 +116,15 @@ std::string WebAssemblyAsmTypeCheck::getTypesString(ArrayRef<StackType> Types,
116116 return SS.str ();
117117}
118118
119+ std::string
120+ WebAssemblyAsmTypeCheck::getTypesString (ArrayRef<wasm::ValType> Types,
121+ size_t StartPos) {
122+ return getTypesString (valTypesToStackTypes (Types), StartPos);
123+ }
124+
119125SmallVector<WebAssemblyAsmTypeCheck::StackType, 4 >
120- WebAssemblyAsmTypeCheck::valTypeToStackType (ArrayRef<wasm::ValType> ValTypes) {
126+ WebAssemblyAsmTypeCheck::valTypesToStackTypes (
127+ ArrayRef<wasm::ValType> ValTypes) {
121128 SmallVector<StackType, 4 > Types (ValTypes.size ());
122129 std::transform (ValTypes.begin (), ValTypes.end (), Types.begin (),
123130 [](wasm::ValType Val) -> StackType { return Val; });
@@ -127,7 +134,7 @@ WebAssemblyAsmTypeCheck::valTypeToStackType(ArrayRef<wasm::ValType> ValTypes) {
127134bool WebAssemblyAsmTypeCheck::checkTypes (SMLoc ErrorLoc,
128135 ArrayRef<wasm::ValType> ValTypes,
129136 bool ExactMatch) {
130- return checkTypes (ErrorLoc, valTypeToStackType (ValTypes), ExactMatch);
137+ return checkTypes (ErrorLoc, valTypesToStackTypes (ValTypes), ExactMatch);
131138}
132139
133140bool WebAssemblyAsmTypeCheck::checkTypes (SMLoc ErrorLoc,
@@ -178,14 +185,14 @@ bool WebAssemblyAsmTypeCheck::checkTypes(SMLoc ErrorLoc,
178185 : std::max ((int )BlockStackStartPos,
179186 (int )Stack.size () - (int )Types.size ());
180187 return typeError (ErrorLoc, " type mismatch, expected " +
181- getTypesString (Types, 0 ) + " but got " +
188+ getTypesString (Types) + " but got " +
182189 getTypesString (Stack, StackStartPos));
183190}
184191
185192bool WebAssemblyAsmTypeCheck::popTypes (SMLoc ErrorLoc,
186193 ArrayRef<wasm::ValType> ValTypes,
187194 bool ExactMatch) {
188- return popTypes (ErrorLoc, valTypeToStackType (ValTypes), ExactMatch);
195+ return popTypes (ErrorLoc, valTypesToStackTypes (ValTypes), ExactMatch);
189196}
190197
191198bool WebAssemblyAsmTypeCheck::popTypes (SMLoc ErrorLoc,
@@ -215,7 +222,7 @@ bool WebAssemblyAsmTypeCheck::popAnyType(SMLoc ErrorLoc) {
215222}
216223
217224void WebAssemblyAsmTypeCheck::pushTypes (ArrayRef<wasm::ValType> ValTypes) {
218- Stack.append (valTypeToStackType (ValTypes));
225+ Stack.append (valTypesToStackTypes (ValTypes));
219226}
220227
221228bool WebAssemblyAsmTypeCheck::getLocal (SMLoc ErrorLoc, const MCOperand &LocalOp,
@@ -322,6 +329,63 @@ bool WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc, bool ExactMatch) {
322329 return checkTypes (ErrorLoc, FuncInfo.Sig .Returns , ExactMatch);
323330}
324331
332+ // Unlike checkTypes() family, this just compare the equivalence of the two
333+ // ValType vectors
334+ static bool compareTypes (ArrayRef<wasm::ValType> TypesA,
335+ ArrayRef<wasm::ValType> TypesB) {
336+ if (TypesA.size () != TypesB.size ())
337+ return true ;
338+ for (size_t I = 0 , E = TypesA.size (); I < E; I++)
339+ if (TypesA[I] != TypesB[I])
340+ return true ;
341+ return false ;
342+ }
343+
344+ bool WebAssemblyAsmTypeCheck::checkTryTable (SMLoc ErrorLoc,
345+ const MCInst &Inst) {
346+ bool Error = false ;
347+ unsigned OpIdx = 1 ; // OpIdx 0 is the block type
348+ int64_t NumCatches = Inst.getOperand (OpIdx++).getImm ();
349+ for (int64_t I = 0 ; I < NumCatches; I++) {
350+ int64_t Opcode = Inst.getOperand (OpIdx++).getImm ();
351+ std::string ErrorMsgBase =
352+ " try_table: catch index " + std::to_string (I) + " : " ;
353+
354+ const wasm::WasmSignature *Sig = nullptr ;
355+ SmallVector<wasm::ValType> SentTypes;
356+ if (Opcode == wasm::WASM_OPCODE_CATCH ||
357+ Opcode == wasm::WASM_OPCODE_CATCH_REF) {
358+ if (!getSignature (ErrorLoc, Inst.getOperand (OpIdx++),
359+ wasm::WASM_SYMBOL_TYPE_TAG, Sig))
360+ SentTypes.insert (SentTypes.end (), Sig->Params .begin (),
361+ Sig->Params .end ());
362+ else
363+ Error = true ;
364+ }
365+ if (Opcode == wasm::WASM_OPCODE_CATCH_REF ||
366+ Opcode == wasm::WASM_OPCODE_CATCH_ALL_REF) {
367+ SentTypes.push_back (wasm::ValType::EXNREF);
368+ }
369+
370+ unsigned Level = Inst.getOperand (OpIdx++).getImm ();
371+ if (Level < BlockInfoStack.size ()) {
372+ const auto &DestBlockInfo =
373+ BlockInfoStack[BlockInfoStack.size () - Level - 1 ];
374+ if (compareTypes (SentTypes, DestBlockInfo.Sig .Returns )) {
375+ std::string ErrorMsg =
376+ ErrorMsgBase + " type mismatch, catch tag type is " +
377+ getTypesString (SentTypes) + " , but destination's type is " +
378+ getTypesString (DestBlockInfo.Sig .Returns );
379+ Error |= typeError (ErrorLoc, ErrorMsg);
380+ }
381+ } else {
382+ Error = typeError (ErrorLoc, ErrorMsgBase + " invalid depth " +
383+ std::to_string (Level));
384+ }
385+ }
386+ return Error;
387+ }
388+
325389bool WebAssemblyAsmTypeCheck::typeCheck (SMLoc ErrorLoc, const MCInst &Inst,
326390 OperandVector &Operands) {
327391 auto Opc = Inst.getOpcode ();
@@ -460,10 +524,13 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
460524 return popType (ErrorLoc, Any{});
461525 }
462526
463- if (Name == " block" || Name == " loop" || Name == " if" || Name == " try" ) {
527+ if (Name == " block" || Name == " loop" || Name == " if" || Name == " try" ||
528+ Name == " try_table" ) {
464529 bool Error = Name == " if" && popType (ErrorLoc, wasm::ValType::I32);
465530 // Pop block input parameters and check their types are correct
466531 Error |= popTypes (ErrorLoc, LastSig.Params );
532+ if (Name == " try_table" )
533+ Error |= checkTryTable (ErrorLoc, Inst);
467534 // Push a new block info
468535 BlockInfoStack.push_back ({LastSig, Stack.size (), Name == " loop" });
469536 // Push back block input parameters
@@ -472,8 +539,8 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
472539 }
473540
474541 if (Name == " end_block" || Name == " end_loop" || Name == " end_if" ||
475- Name == " end_try" || Name == " delegate" || Name == " else " ||
476- Name == " catch" || Name == " catch_all" ) {
542+ Name == " end_try" || Name == " delegate" || Name == " end_try_table " ||
543+ Name == " else " || Name == " catch" || Name == " catch_all" ) {
477544 assert (!BlockInfoStack.empty ());
478545 // Check if the types on the stack match with the block return type
479546 const auto &LastBlockInfo = BlockInfoStack.back ();
@@ -586,6 +653,12 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
586653 return Error;
587654 }
588655
656+ if (Name == " throw_ref" ) {
657+ bool Error = popType (ErrorLoc, wasm::ValType::EXNREF);
658+ pushType (Polymorphic{});
659+ return Error;
660+ }
661+
589662 // The current instruction is a stack instruction which doesn't have
590663 // explicit operands that indicate push/pop types, so we get those from
591664 // the register version of the same instruction.
0 commit comments