authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-03 20:46:07+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-05 10:37:08+02:00
log779770cff58923e5113b5419accf910059fddea7
tree7efe360930ba89b7666e45f1c11af43370324611
parentf4ac37f55da7258c25194e66e1cfe3270ca9d419

wasm: Implement `try` instruction


1 files changed, 67 insertions(+), 2 deletions(-)

src/arch/wasm/CodeGen.zig+67-2
...@@ -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),
14921492
1493 .@"try" => @panic("TODO"),1493 .@"try" => self.airTry(inst),
1494 .try_ptr => @panic("TODO"),1494 .try_ptr => self.airTryPtr(inst),
14951495
1496 // TODO1496 // 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
4630fn 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
4639fn 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
4648fn 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}