| 263 | } |
| 264 | |
| 265 | Expect<void> Executor::throwException( |
| 266 | Runtime::StackManager &StackMgr, Runtime::Instance::TagInstance &TagInst, |
| 267 | AST::InstrView::iterator &PC, |
| 268 | const Runtime::Instance::ExceptionInstance *ExnInst) noexcept { |
| 269 | StackMgr.removeInactiveHandler(PC); |
| 270 | auto AssocValSize = TagInst.getTagType().getAssocValSize(); |
| 271 | while (true) { |
| 272 | // Pop the top handler. |
| 273 | auto Handler = StackMgr.popTopHandler(AssocValSize); |
| 274 | if (!Handler.has_value()) { |
| 275 | break; |
| 276 | } |
| 277 | // Checking through the catch clause. |
| 278 | for (const auto &C : Handler->CatchClause) { |
| 279 | if (!C.IsAll && getTagInstByIdx(StackMgr, C.TagIndex) != &TagInst) { |
| 280 | // Specific-tag clauses require tag-address equivalence; skip the |
| 281 | // ones that do not match. |
| 282 | continue; |
| 283 | } |
| 284 | if (C.IsRef) { |
| 285 | // Allocate the exception instance lazily on the first catch_ref; |
| 286 | // reuse the one passed in by throw_ref to preserve exnref identity. |
| 287 | const Runtime::Instance::ExceptionInstance *Inst = ExnInst; |
| 288 | if (Inst == nullptr) { |
| 289 | auto Payload = StackMgr.getTopSpan(AssocValSize); |
| 290 | std::vector<ValVariant> Vec(Payload.begin(), Payload.end()); |
| 291 | auto *ModInst = const_cast<Runtime::Instance::ModuleInstance *>( |
| 292 | StackMgr.getModule()); |
| 293 | Inst = ModInst->newException(&TagInst, std::move(Vec)); |
| 294 | } |
| 295 | StackMgr.push( |
| 296 | RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), Inst)); |
| 297 | } |
| 298 | // When an exception is caught, move the PC to the try block and branch to |
| 299 | // the label. |
| 300 | |
| 301 | PC = Handler->Try; |
| 302 | return branchToLabel(StackMgr, C.Jump, PC); |
| 303 | } |
| 304 | } |
| 305 | spdlog::error(ErrCode::Value::UncaughtException); |
| 306 | return Unexpect(ErrCode::Value::UncaughtException); |
| 307 | } |
| 308 | |
| 309 | Expect<void> |
| 310 | Executor::checkOffsetOverflow(const Runtime::Instance::MemoryInstance &MemInst, |
nothing calls this directly
no test coverage detected