@@ -59,7 +59,7 @@ void WebAssemblyAsmTypeCheck::localDecl(
59
59
}
60
60
61
61
void WebAssemblyAsmTypeCheck::dumpTypeStack (Twine Msg) {
62
- LLVM_DEBUG ({ dbgs () << Msg << getTypesString (Stack, 0 ) << " \n " ; });
62
+ LLVM_DEBUG ({ dbgs () << Msg << getTypesString (Stack) << " \n " ; });
63
63
}
64
64
65
65
bool WebAssemblyAsmTypeCheck::typeError (SMLoc ErrorLoc, const Twine &Msg) {
@@ -116,8 +116,15 @@ std::string WebAssemblyAsmTypeCheck::getTypesString(ArrayRef<StackType> Types,
116
116
return SS.str ();
117
117
}
118
118
119
+ std::string
120
+ WebAssemblyAsmTypeCheck::getTypesString (ArrayRef<wasm::ValType> Types,
121
+ size_t StartPos) {
122
+ return getTypesString (valTypesToStackTypes (Types), StartPos);
123
+ }
124
+
119
125
SmallVector<WebAssemblyAsmTypeCheck::StackType, 4 >
120
- WebAssemblyAsmTypeCheck::valTypeToStackType (ArrayRef<wasm::ValType> ValTypes) {
126
+ WebAssemblyAsmTypeCheck::valTypesToStackTypes (
127
+ ArrayRef<wasm::ValType> ValTypes) {
121
128
SmallVector<StackType, 4 > Types (ValTypes.size ());
122
129
std::transform (ValTypes.begin (), ValTypes.end (), Types.begin (),
123
130
[](wasm::ValType Val) -> StackType { return Val; });
@@ -127,7 +134,7 @@ WebAssemblyAsmTypeCheck::valTypeToStackType(ArrayRef<wasm::ValType> ValTypes) {
127
134
bool WebAssemblyAsmTypeCheck::checkTypes (SMLoc ErrorLoc,
128
135
ArrayRef<wasm::ValType> ValTypes,
129
136
bool ExactMatch) {
130
- return checkTypes (ErrorLoc, valTypeToStackType (ValTypes), ExactMatch);
137
+ return checkTypes (ErrorLoc, valTypesToStackTypes (ValTypes), ExactMatch);
131
138
}
132
139
133
140
bool WebAssemblyAsmTypeCheck::checkTypes (SMLoc ErrorLoc,
@@ -178,14 +185,14 @@ bool WebAssemblyAsmTypeCheck::checkTypes(SMLoc ErrorLoc,
178
185
: std::max ((int )BlockStackStartPos,
179
186
(int )Stack.size () - (int )Types.size ());
180
187
return typeError (ErrorLoc, " type mismatch, expected " +
181
- getTypesString (Types, 0 ) + " but got " +
188
+ getTypesString (Types) + " but got " +
182
189
getTypesString (Stack, StackStartPos));
183
190
}
184
191
185
192
bool WebAssemblyAsmTypeCheck::popTypes (SMLoc ErrorLoc,
186
193
ArrayRef<wasm::ValType> ValTypes,
187
194
bool ExactMatch) {
188
- return popTypes (ErrorLoc, valTypeToStackType (ValTypes), ExactMatch);
195
+ return popTypes (ErrorLoc, valTypesToStackTypes (ValTypes), ExactMatch);
189
196
}
190
197
191
198
bool WebAssemblyAsmTypeCheck::popTypes (SMLoc ErrorLoc,
@@ -215,7 +222,7 @@ bool WebAssemblyAsmTypeCheck::popAnyType(SMLoc ErrorLoc) {
215
222
}
216
223
217
224
void WebAssemblyAsmTypeCheck::pushTypes (ArrayRef<wasm::ValType> ValTypes) {
218
- Stack.append (valTypeToStackType (ValTypes));
225
+ Stack.append (valTypesToStackTypes (ValTypes));
219
226
}
220
227
221
228
bool WebAssemblyAsmTypeCheck::getLocal (SMLoc ErrorLoc, const MCOperand &LocalOp,
@@ -322,6 +329,63 @@ bool WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc, bool ExactMatch) {
322
329
return checkTypes (ErrorLoc, FuncInfo.Sig .Returns , ExactMatch);
323
330
}
324
331
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
+
325
389
bool WebAssemblyAsmTypeCheck::typeCheck (SMLoc ErrorLoc, const MCInst &Inst,
326
390
OperandVector &Operands) {
327
391
auto Opc = Inst.getOpcode ();
@@ -460,10 +524,13 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
460
524
return popType (ErrorLoc, Any{});
461
525
}
462
526
463
- if (Name == " block" || Name == " loop" || Name == " if" || Name == " try" ) {
527
+ if (Name == " block" || Name == " loop" || Name == " if" || Name == " try" ||
528
+ Name == " try_table" ) {
464
529
bool Error = Name == " if" && popType (ErrorLoc, wasm::ValType::I32);
465
530
// Pop block input parameters and check their types are correct
466
531
Error |= popTypes (ErrorLoc, LastSig.Params );
532
+ if (Name == " try_table" )
533
+ Error |= checkTryTable (ErrorLoc, Inst);
467
534
// Push a new block info
468
535
BlockInfoStack.push_back ({LastSig, Stack.size (), Name == " loop" });
469
536
// Push back block input parameters
@@ -472,8 +539,8 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
472
539
}
473
540
474
541
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" ) {
477
544
assert (!BlockInfoStack.empty ());
478
545
// Check if the types on the stack match with the block return type
479
546
const auto &LastBlockInfo = BlockInfoStack.back ();
@@ -586,6 +653,12 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
586
653
return Error;
587
654
}
588
655
656
+ if (Name == " throw_ref" ) {
657
+ bool Error = popType (ErrorLoc, wasm::ValType::EXNREF);
658
+ pushType (Polymorphic{});
659
+ return Error;
660
+ }
661
+
589
662
// The current instruction is a stack instruction which doesn't have
590
663
// explicit operands that indicate push/pop types, so we get those from
591
664
// the register version of the same instruction.
0 commit comments