| ... | @@ -1490,8 +1490,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1490,8 +1490,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1490 | .int_to_float => self.airIntToFloat(inst), | 1490 | .int_to_float => self.airIntToFloat(inst), |
| 1491 | .get_union_tag => self.airGetUnionTag(inst), | 1491 | .get_union_tag => self.airGetUnionTag(inst), |
| 1492 | | 1492 | |
| 1493 | .@"try" => @panic("TODO"), | 1493 | .@"try" => self.airTry(inst), |
| 1494 | .try_ptr => @panic("TODO"), | 1494 | .try_ptr => self.airTryPtr(inst), |
| 1495 | | 1495 | |
| 1496 | // TODO | 1496 | // TODO |
| 1497 | .dbg_inline_begin, | 1497 | .dbg_inline_begin, |
| ... | @@ -4626,3 +4626,68 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -4626,3 +4626,68 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue { |
| 4626 | } }); | 4626 | } }); |
| 4627 | return WValue{ .none = {} }; | 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 | } |