| ... | ... | @@ -1490,8 +1490,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1490 | 1490 | .int_to_float => self.airIntToFloat(inst), |
| 1491 | 1491 | .get_union_tag => self.airGetUnionTag(inst), |
| 1492 | 1492 | |
| 1493 | | .@"try" => @panic("TODO"), |
| 1494 | | .try_ptr => @panic("TODO"), |
| 1493 | .@"try" => self.airTry(inst), |
| 1494 | .try_ptr => self.airTryPtr(inst), |
| 1495 | 1495 | |
| 1496 | 1496 | // TODO |
| 1497 | 1497 | .dbg_inline_begin, |
| ... | ... | @@ -4626,3 +4626,68 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue { |
| 4626 | 4626 | } }); |
| 4627 | 4627 | return WValue{ .none = {} }; |
| 4628 | 4628 | } |
| 4629 | |
| 4630 | fn airTry(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4631 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 4632 | const err_union = try self.resolveInst(pl_op.operand); |
| 4633 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 4634 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 4635 | const err_union_ty = self.air.typeOf(pl_op.operand); |
| 4636 | return lowerTry(self, err_union, body, err_union_ty, false); |
| 4637 | } |
| 4638 | |
| 4639 | fn airTryPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4640 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4641 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| 4642 | const err_union_ptr = try self.resolveInst(extra.data.ptr); |
| 4643 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 4644 | const err_union_ty = self.air.typeOf(extra.data.ptr).childType(); |
| 4645 | return lowerTry(self, err_union_ptr, body, err_union_ty, true); |
| 4646 | } |
| 4647 | |
| 4648 | fn lowerTry( |
| 4649 | self: *Self, |
| 4650 | err_union: WValue, |
| 4651 | body: []const Air.Inst.Index, |
| 4652 | err_union_ty: Type, |
| 4653 | operand_is_ptr: bool, |
| 4654 | ) InnerError!WValue { |
| 4655 | if (operand_is_ptr) { |
| 4656 | return self.fail("TODO: lowerTry for pointers", .{}); |
| 4657 | } |
| 4658 | |
| 4659 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { |
| 4660 | return err_union; |
| 4661 | } |
| 4662 | |
| 4663 | const pl_ty = err_union_ty.errorUnionPayload(); |
| 4664 | const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(); |
| 4665 | |
| 4666 | // Block we can jump out of when error is not set |
| 4667 | try self.startBlock(.block, wasm.block_empty); |
| 4668 | |
| 4669 | // check if the error tag is set for the error union. |
| 4670 | try self.emitWValue(err_union); |
| 4671 | if (pl_has_bits) { |
| 4672 | const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, self.target)); |
| 4673 | try self.addMemArg(.i32_load16_u, .{ |
| 4674 | .offset = err_union.offset() + err_offset, |
| 4675 | .alignment = Type.anyerror.abiAlignment(self.target), |
| 4676 | }); |
| 4677 | } |
| 4678 | try self.addTag(.i32_eqz); |
| 4679 | try self.addLabel(.br_if, 0); // jump out of block when error is '0' |
| 4680 | try self.genBody(body); |
| 4681 | try self.endBlock(); |
| 4682 | |
| 4683 | // if we reach here it means error was not set, and we want the payload |
| 4684 | if (!pl_has_bits) { |
| 4685 | return WValue{ .none = {} }; |
| 4686 | } |
| 4687 | |
| 4688 | const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, self.target)); |
| 4689 | if (isByRef(pl_ty, self.target)) { |
| 4690 | return buildPointerOffset(self, err_union, pl_offset, .new); |
| 4691 | } |
| 4692 | return self.load(err_union, pl_ty, pl_offset); |
| 4693 | } |