| 109 | } |
| 110 | |
| 111 | Expect<void> Executor::runBrOnCastOp(Runtime::StackManager &StackMgr, |
| 112 | const AST::Instruction &Instr, |
| 113 | AST::InstrView::iterator &PC, |
| 114 | bool IsReverse) noexcept { |
| 115 | // Get the value on top of the stack. |
| 116 | const auto *ModInst = StackMgr.getModule(); |
| 117 | const auto &Val = StackMgr.getTop().get<RefVariant>(); |
| 118 | const auto &VT = Val.getType(); |
| 119 | Span<const AST::SubType *const> GotTypeList = ModInst->getTypeList(); |
| 120 | if (!VT.isAbsHeapType()) { |
| 121 | auto *Inst = Val.getPtr<Runtime::Instance::CompositeBase>(); |
| 122 | // Reference must not be nullptr here because the null references are typed |
| 123 | // with the least abstract heap type. |
| 124 | if (Inst->getModule()) { |
| 125 | GotTypeList = Inst->getModule()->getTypeList(); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | ValType NormalizedVT = VT; |
| 130 | if (NormalizedVT.isExternalized()) { |
| 131 | // An externalized reference must appear as an 'externref' to the matcher. |
| 132 | // We preserve the nullability (Ref vs RefNull). |
| 133 | NormalizedVT = |
| 134 | ValType(VT.isNullableRefType() ? TypeCode::RefNull : TypeCode::Ref, |
| 135 | TypeCode::ExternRef); |
| 136 | } |
| 137 | |
| 138 | bool MatchResult = AST::TypeMatcher::matchType(ModInst->getTypeList(), |
| 139 | Instr.getBrCast().RType2, |
| 140 | GotTypeList, NormalizedVT); |
| 141 | if (MatchResult != IsReverse) { |
| 142 | return branchToLabel(StackMgr, Instr.getBrCast().Jump, PC); |
| 143 | } |
| 144 | return {}; |
| 145 | } |
| 146 | |
| 147 | Expect<void> Executor::runReturnOp(Runtime::StackManager &StackMgr, |
| 148 | AST::InstrView::iterator &PC) noexcept { |
nothing calls this directly
no test coverage detected