| ... | @@ -2715,20 +2715,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, ptr_child_ty: Type) InnerError | ... | @@ -2715,20 +2715,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, ptr_child_ty: Type) InnerError |
| 2715 | }, | 2715 | }, |
| 2716 | .opt_payload_ptr => { | 2716 | .opt_payload_ptr => { |
| 2717 | const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; | 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); | 2718 | return 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 | } }; | | |
| 2732 | }, | 2719 | }, |
| 2733 | else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}), | 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,7 +2876,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 2889 | } | 2876 | } |
| 2890 | } else { | 2877 | } else { |
| 2891 | const is_pl = val.tag() == .opt_payload; | 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 | .Struct => { | 2881 | .Struct => { |
| 2895 | const struct_obj = ty.castTag(.@"struct").?.data; | 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,7 +3869,11 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod |
| 3882 | // When payload is zero-bits, we can treat operand as a value, rather than | 3869 | // When payload is zero-bits, we can treat operand as a value, rather than |
| 3883 | // a pointer to the stack value | 3870 | // a pointer to the stack value |
| 3884 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { | 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 | } else if (payload_ty.isSlice()) { | 3878 | } else if (payload_ty.isSlice()) { |
| 3888 | switch (func.arch()) { | 3879 | switch (func.arch()) { |
| ... | @@ -3911,13 +3902,11 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3911,13 +3902,11 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3911 | const operand = try func.resolveInst(ty_op.operand); | 3902 | const operand = try func.resolveInst(ty_op.operand); |
| 3912 | if (opt_ty.optionalReprIsPayload()) break :result func.reuseOperand(ty_op.operand, operand); | 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 | if (isByRef(payload_ty, func.target)) { | 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 | break :result try payload.toLocal(func, payload_ty); | 3910 | break :result try payload.toLocal(func, payload_ty); |
| 3922 | }; | 3911 | }; |
| 3923 | func.finishAir(inst, result, &.{ty_op.operand}); | 3912 | func.finishAir(inst, result, &.{ty_op.operand}); |
| ... | @@ -3936,8 +3925,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3936,8 +3925,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3936 | break :result func.reuseOperand(ty_op.operand, operand); | 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); | 3928 | break :result try func.buildPointerOffset(operand, 0, .new); |
| 3940 | break :result try func.buildPointerOffset(operand, offset, .new); | | |
| 3941 | }; | 3929 | }; |
| 3942 | func.finishAir(inst, result, &.{ty_op.operand}); | 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,16 +3944,16 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi |
| 3956 | return func.finishAir(inst, operand, &.{ty_op.operand}); | 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 | const module = func.bin_file.base.options.module.?; | 3948 | const module = func.bin_file.base.options.module.?; |
| 3961 | return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)}); | 3949 | return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)}); |
| 3962 | }; | 3950 | }; |
| 3963 | | 3951 | |
| 3964 | try func.emitWValue(operand); | 3952 | try func.emitWValue(operand); |
| 3965 | try func.addImm32(1); | 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 | return func.finishAir(inst, result, &.{ty_op.operand}); | 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,7 +3976,7 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3988 | if (op_ty.optionalReprIsPayload()) { | 3976 | if (op_ty.optionalReprIsPayload()) { |
| 3989 | break :result func.reuseOperand(ty_op.operand, operand); | 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 | const module = func.bin_file.base.options.module.?; | 3980 | const module = func.bin_file.base.options.module.?; |
| 3993 | return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)}); | 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,9 +3985,9 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3997 | const result_ptr = try func.allocStack(op_ty); | 3985 | const result_ptr = try func.allocStack(op_ty); |
| 3998 | try func.emitWValue(result_ptr); | 3986 | try func.emitWValue(result_ptr); |
| 3999 | try func.addImm32(1); | 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 | try func.store(payload_ptr, operand, payload_ty, 0); | 3991 | try func.store(payload_ptr, operand, payload_ty, 0); |
| 4004 | break :result result_ptr; | 3992 | break :result result_ptr; |
| 4005 | }; | 3993 | }; |
| ... | @@ -4719,7 +4707,6 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: | ... | @@ -4719,7 +4707,6 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 4719 | assert(op == .eq or op == .neq); | 4707 | assert(op == .eq or op == .neq); |
| 4720 | var buf: Type.Payload.ElemType = undefined; | 4708 | var buf: Type.Payload.ElemType = undefined; |
| 4721 | const payload_ty = operand_ty.optionalChild(&buf); | 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 | // We store the final result in here that will be validated | 4711 | // We store the final result in here that will be validated |
| 4725 | // if the optional is truly equal. | 4712 | // if the optional is truly equal. |
| ... | @@ -4732,8 +4719,8 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: | ... | @@ -4732,8 +4719,8 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 4732 | try func.addTag(.i32_ne); // inverse so we can exit early | 4719 | try func.addTag(.i32_ne); // inverse so we can exit early |
| 4733 | try func.addLabel(.br_if, 0); | 4720 | try func.addLabel(.br_if, 0); |
| 4734 | | 4721 | |
| 4735 | _ = try func.load(lhs, payload_ty, offset); | 4722 | _ = try func.load(lhs, payload_ty, 0); |
| 4736 | _ = try func.load(rhs, payload_ty, offset); | 4723 | _ = try func.load(rhs, payload_ty, 0); |
| 4737 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, func.target) }); | 4724 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, func.target) }); |
| 4738 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 4725 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 4739 | try func.addLabel(.br_if, 0); | 4726 | try func.addLabel(.br_if, 0); |