| ... | ... | @@ -2715,20 +2715,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, ptr_child_ty: Type) InnerError |
| 2715 | 2715 | }, |
| 2716 | 2716 | .opt_payload_ptr => { |
| 2717 | 2717 | const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| 2718 | | const parent_ptr = try func.lowerParentPtr(payload_ptr.container_ptr, payload_ptr.container_ty); |
| 2719 | | var buf: Type.Payload.ElemType = undefined; |
| 2720 | | const payload_ty = payload_ptr.container_ty.optionalChild(&buf); |
| 2721 | | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or payload_ty.optionalReprIsPayload()) { |
| 2722 | | return parent_ptr; |
| 2723 | | } |
| 2724 | | |
| 2725 | | const abi_size = payload_ptr.container_ty.abiSize(func.target); |
| 2726 | | const offset = abi_size - payload_ty.abiSize(func.target); |
| 2727 | | |
| 2728 | | return WValue{ .memory_offset = .{ |
| 2729 | | .pointer = parent_ptr.memory, |
| 2730 | | .offset = @intCast(u32, offset), |
| 2731 | | } }; |
| 2718 | return func.lowerParentPtr(payload_ptr.container_ptr, payload_ptr.container_ty); |
| 2732 | 2719 | }, |
| 2733 | 2720 | else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}), |
| 2734 | 2721 | } |
| ... | ... | @@ -2889,7 +2876,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 2889 | 2876 | } |
| 2890 | 2877 | } else { |
| 2891 | 2878 | const is_pl = val.tag() == .opt_payload; |
| 2892 | | return WValue{ .imm32 = if (is_pl) @as(u32, 1) else 0 }; |
| 2879 | return WValue{ .imm32 = @boolToInt(is_pl) }; |
| 2893 | 2880 | }, |
| 2894 | 2881 | .Struct => { |
| 2895 | 2882 | const struct_obj = ty.castTag(.@"struct").?.data; |
| ... | ... | @@ -3882,7 +3869,11 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod |
| 3882 | 3869 | // When payload is zero-bits, we can treat operand as a value, rather than |
| 3883 | 3870 | // a pointer to the stack value |
| 3884 | 3871 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3885 | | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset(), .alignment = 1 }); |
| 3872 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { |
| 3873 | const module = func.bin_file.base.options.module.?; |
| 3874 | return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(module)}); |
| 3875 | }; |
| 3876 | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 }); |
| 3886 | 3877 | } |
| 3887 | 3878 | } else if (payload_ty.isSlice()) { |
| 3888 | 3879 | switch (func.arch()) { |
| ... | ... | @@ -3911,13 +3902,11 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3911 | 3902 | const operand = try func.resolveInst(ty_op.operand); |
| 3912 | 3903 | if (opt_ty.optionalReprIsPayload()) break :result func.reuseOperand(ty_op.operand, operand); |
| 3913 | 3904 | |
| 3914 | | const offset = opt_ty.abiSize(func.target) - payload_ty.abiSize(func.target); |
| 3915 | | |
| 3916 | 3905 | if (isByRef(payload_ty, func.target)) { |
| 3917 | | break :result try func.buildPointerOffset(operand, offset, .new); |
| 3906 | break :result try func.buildPointerOffset(operand, 0, .new); |
| 3918 | 3907 | } |
| 3919 | 3908 | |
| 3920 | | const payload = try func.load(operand, payload_ty, @intCast(u32, offset)); |
| 3909 | const payload = try func.load(operand, payload_ty, 0); |
| 3921 | 3910 | break :result try payload.toLocal(func, payload_ty); |
| 3922 | 3911 | }; |
| 3923 | 3912 | func.finishAir(inst, result, &.{ty_op.operand}); |
| ... | ... | @@ -3936,8 +3925,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3936 | 3925 | break :result func.reuseOperand(ty_op.operand, operand); |
| 3937 | 3926 | } |
| 3938 | 3927 | |
| 3939 | | const offset = opt_ty.abiSize(func.target) - payload_ty.abiSize(func.target); |
| 3940 | | break :result try func.buildPointerOffset(operand, offset, .new); |
| 3928 | break :result try func.buildPointerOffset(operand, 0, .new); |
| 3941 | 3929 | }; |
| 3942 | 3930 | func.finishAir(inst, result, &.{ty_op.operand}); |
| 3943 | 3931 | } |
| ... | ... | @@ -3956,16 +3944,16 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi |
| 3956 | 3944 | return func.finishAir(inst, operand, &.{ty_op.operand}); |
| 3957 | 3945 | } |
| 3958 | 3946 | |
| 3959 | | const offset = std.math.cast(u32, opt_ty.abiSize(func.target) - payload_ty.abiSize(func.target)) orelse { |
| 3947 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { |
| 3960 | 3948 | const module = func.bin_file.base.options.module.?; |
| 3961 | 3949 | return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)}); |
| 3962 | 3950 | }; |
| 3963 | 3951 | |
| 3964 | 3952 | try func.emitWValue(operand); |
| 3965 | 3953 | try func.addImm32(1); |
| 3966 | | try func.addMemArg(.i32_store8, .{ .offset = operand.offset(), .alignment = 1 }); |
| 3954 | try func.addMemArg(.i32_store8, .{ .offset = operand.offset() + offset, .alignment = 1 }); |
| 3967 | 3955 | |
| 3968 | | const result = try func.buildPointerOffset(operand, offset, .new); |
| 3956 | const result = try func.buildPointerOffset(operand, 0, .new); |
| 3969 | 3957 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 3970 | 3958 | } |
| 3971 | 3959 | |
| ... | ... | @@ -3988,7 +3976,7 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3988 | 3976 | if (op_ty.optionalReprIsPayload()) { |
| 3989 | 3977 | break :result func.reuseOperand(ty_op.operand, operand); |
| 3990 | 3978 | } |
| 3991 | | const offset = std.math.cast(u32, op_ty.abiSize(func.target) - payload_ty.abiSize(func.target)) orelse { |
| 3979 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { |
| 3992 | 3980 | const module = func.bin_file.base.options.module.?; |
| 3993 | 3981 | return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)}); |
| 3994 | 3982 | }; |
| ... | ... | @@ -3997,9 +3985,9 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3997 | 3985 | const result_ptr = try func.allocStack(op_ty); |
| 3998 | 3986 | try func.emitWValue(result_ptr); |
| 3999 | 3987 | try func.addImm32(1); |
| 4000 | | try func.addMemArg(.i32_store8, .{ .offset = result_ptr.offset(), .alignment = 1 }); |
| 3988 | try func.addMemArg(.i32_store8, .{ .offset = result_ptr.offset() + offset, .alignment = 1 }); |
| 4001 | 3989 | |
| 4002 | | const payload_ptr = try func.buildPointerOffset(result_ptr, offset, .new); |
| 3990 | const payload_ptr = try func.buildPointerOffset(result_ptr, 0, .new); |
| 4003 | 3991 | try func.store(payload_ptr, operand, payload_ty, 0); |
| 4004 | 3992 | break :result result_ptr; |
| 4005 | 3993 | }; |
| ... | ... | @@ -4719,7 +4707,6 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 4719 | 4707 | assert(op == .eq or op == .neq); |
| 4720 | 4708 | var buf: Type.Payload.ElemType = undefined; |
| 4721 | 4709 | const payload_ty = operand_ty.optionalChild(&buf); |
| 4722 | | const offset = @intCast(u32, operand_ty.abiSize(func.target) - payload_ty.abiSize(func.target)); |
| 4723 | 4710 | |
| 4724 | 4711 | // We store the final result in here that will be validated |
| 4725 | 4712 | // if the optional is truly equal. |
| ... | ... | @@ -4732,8 +4719,8 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 4732 | 4719 | try func.addTag(.i32_ne); // inverse so we can exit early |
| 4733 | 4720 | try func.addLabel(.br_if, 0); |
| 4734 | 4721 | |
| 4735 | | _ = try func.load(lhs, payload_ty, offset); |
| 4736 | | _ = try func.load(rhs, payload_ty, offset); |
| 4722 | _ = try func.load(lhs, payload_ty, 0); |
| 4723 | _ = try func.load(rhs, payload_ty, 0); |
| 4737 | 4724 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, func.target) }); |
| 4738 | 4725 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 4739 | 4726 | try func.addLabel(.br_if, 0); |