authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-08 06:38:47-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:47:30-05:00
log63730441d01a860a53d190e88079452947a4149d
tree54c74892ce56e92a69d821ca543f70b3deddc9a2
parent5069f574f43f1c9fe7ced12f9fd5f05bdedf6abb

x86_64: implement union access


4 files changed, 286 insertions(+), 71 deletions(-)

lib/std/debug.zig+1
...@@ -23,6 +23,7 @@ pub const Coverage = @import("debug/Coverage.zig");...@@ -23,6 +23,7 @@ pub const Coverage = @import("debug/Coverage.zig");
2323
24pub const FormattedPanic = @import("debug/FormattedPanic.zig");24pub const FormattedPanic = @import("debug/FormattedPanic.zig");
25pub const SimplePanic = @import("debug/SimplePanic.zig");25pub const SimplePanic = @import("debug/SimplePanic.zig");
26pub const NoPanic = @import("debug/NoPanic.zig");
2627
27/// Unresolved source locations can be represented with a single `usize` that28/// Unresolved source locations can be represented with a single `usize` that
28/// corresponds to a virtual memory address of the program counter. Combined29/// corresponds to a virtual memory address of the program counter. Combined
lib/std/debug/NoPanic.zig created+59
...@@ -0,0 +1,59 @@
1//! This namespace can be used with `pub const Panic = std.debug.NoPanic;` in the root file.
2//! It emits as little code as possible, for testing purposes.
3//!
4//! For a functional alternative, see `std.debug.FormattedPanic`.
5
6const std = @import("../std.zig");
7
8pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
9 @branchHint(.cold);
10 @trap();
11}
12
13pub inline fn sentinelMismatch(_: anytype, _: anytype) noreturn {
14 @branchHint(.cold);
15 @trap();
16}
17
18pub inline fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
19 @branchHint(.cold);
20 @trap();
21}
22
23pub inline fn outOfBounds(_: usize, _: usize) noreturn {
24 @branchHint(.cold);
25 @trap();
26}
27
28pub inline fn startGreaterThanEnd(_: usize, _: usize) noreturn {
29 @branchHint(.cold);
30 @trap();
31}
32
33pub inline fn inactiveUnionField(_: anytype, _: anytype) noreturn {
34 @branchHint(.cold);
35 @trap();
36}
37
38pub const messages = struct {
39 pub const reached_unreachable = "";
40 pub const unwrap_null = "";
41 pub const cast_to_null = "";
42 pub const incorrect_alignment = "";
43 pub const invalid_error_code = "";
44 pub const cast_truncated_data = "";
45 pub const negative_to_unsigned = "";
46 pub const integer_overflow = "";
47 pub const shl_overflow = "";
48 pub const shr_overflow = "";
49 pub const divide_by_zero = "";
50 pub const exact_division_remainder = "";
51 pub const integer_part_out_of_bounds = "";
52 pub const corrupt_switch = "";
53 pub const shift_rhs_too_big = "";
54 pub const invalid_enum_value = "";
55 pub const for_len_mismatch = "";
56 pub const memcpy_len_mismatch = "";
57 pub const memcpy_alias = "";
58 pub const noreturn_returned = "";
59};
src/arch/x86_64/CodeGen.zig+225-70
...@@ -2467,8 +2467,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2467,8 +2467,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2467 .memcpy => try cg.airMemcpy(inst),2467 .memcpy => try cg.airMemcpy(inst),
2468 .memset => try cg.airMemset(inst, false),2468 .memset => try cg.airMemset(inst, false),
2469 .memset_safe => try cg.airMemset(inst, true),2469 .memset_safe => try cg.airMemset(inst, true),
2470 .set_union_tag => try cg.airSetUnionTag(inst),
2471 .get_union_tag => try cg.airGetUnionTag(inst),
2472 .ctz => try cg.airCtz(inst),2470 .ctz => try cg.airCtz(inst),
2473 .popcount => try cg.airPopCount(inst),2471 .popcount => try cg.airPopCount(inst),
2474 .byte_swap => try cg.airByteSwap(inst),2472 .byte_swap => try cg.airByteSwap(inst),
...@@ -2480,7 +2478,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2480,7 +2478,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2480 .shuffle => try cg.airShuffle(inst),2478 .shuffle => try cg.airShuffle(inst),
2481 .reduce => try cg.airReduce(inst),2479 .reduce => try cg.airReduce(inst),
2482 .aggregate_init => try cg.airAggregateInit(inst),2480 .aggregate_init => try cg.airAggregateInit(inst),
2483 .union_init => try cg.airUnionInit(inst),
2484 .prefetch => try cg.airPrefetch(inst),2481 .prefetch => try cg.airPrefetch(inst),
2485 .mul_add => try cg.airMulAdd(inst),2482 .mul_add => try cg.airMulAdd(inst),
24862483
...@@ -2528,7 +2525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2528,7 +2525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2528 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2525 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2529 try ops[0].toSlicePtr(cg);2526 try ops[0].toSlicePtr(cg);
2530 var res: [1]Temp = undefined;2527 var res: [1]Temp = undefined;
2531 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, comptime &.{ .{2528 cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
2532 .patterns = &.{2529 .patterns = &.{
2533 .{ .src = .{ .to_gpr, .simm32 } },2530 .{ .src = .{ .to_gpr, .simm32 } },
2534 },2531 },
...@@ -2645,7 +2642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2645,7 +2642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2645 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2642 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2646 try ops[0].toSlicePtr(cg);2643 try ops[0].toSlicePtr(cg);
2647 var res: [1]Temp = undefined;2644 var res: [1]Temp = undefined;
2648 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, comptime &.{ .{2645 cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
2649 .patterns = &.{2646 .patterns = &.{
2650 .{ .src = .{ .to_gpr, .simm32 } },2647 .{ .src = .{ .to_gpr, .simm32 } },
2651 },2648 },
...@@ -2772,20 +2769,22 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2772,20 +2769,22 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2772 try res[0].moveTo(inst, cg);2769 try res[0].moveTo(inst, cg);
2773 },2770 },
2774 .alloc => if (use_old) try cg.airAlloc(inst) else {2771 .alloc => if (use_old) try cg.airAlloc(inst) else {
2775 var slot = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .lea_frame = .{2772 const ty = air_datas[@intFromEnum(inst)].ty;
2773 var slot = try cg.tempInit(ty, .{ .lea_frame = .{
2776 .index = try cg.allocMemPtr(inst),2774 .index = try cg.allocMemPtr(inst),
2777 } });2775 } });
2778 try slot.moveTo(inst, cg);2776 try slot.moveTo(inst, cg);
2779 },2777 },
2780 .inferred_alloc, .inferred_alloc_comptime => unreachable,2778 .inferred_alloc, .inferred_alloc_comptime => unreachable,
2781 .ret_ptr => if (use_old) try cg.airRetPtr(inst) else {2779 .ret_ptr => if (use_old) try cg.airRetPtr(inst) else {
2780 const ty = air_datas[@intFromEnum(inst)].ty;
2782 var slot = switch (cg.ret_mcv.long) {2781 var slot = switch (cg.ret_mcv.long) {
2783 else => unreachable,2782 else => unreachable,
2784 .none => try cg.tempFromValue(cg.typeOfIndex(inst), .{ .lea_frame = .{2783 .none => try cg.tempInit(ty, .{ .lea_frame = .{
2785 .index = try cg.allocMemPtr(inst),2784 .index = try cg.allocMemPtr(inst),
2786 } }),2785 } }),
2787 .load_frame => slot: {2786 .load_frame => slot: {
2788 var slot = try cg.tempFromValue(cg.typeOfIndex(inst), cg.ret_mcv.long);2787 var slot = try cg.tempInit(ty, cg.ret_mcv.long);
2789 try slot.toOffset(cg.ret_mcv.short.indirect.off, cg);2788 try slot.toOffset(cg.ret_mcv.short.indirect.off, cg);
2790 break :slot slot;2789 break :slot slot;
2791 },2790 },
...@@ -2797,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2797,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2797 const bin_op = air_datas[@intFromEnum(inst)].bin_op;2796 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
2798 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2797 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2799 var res: [1]Temp = undefined;2798 var res: [1]Temp = undefined;
2800 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Mir.Inst.Tag, switch (air_tag) {2799 cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, switch (@as(Mir.Inst.Tag, switch (air_tag) {
2801 else => unreachable,2800 else => unreachable,
2802 .bit_and => .@"and",2801 .bit_and => .@"and",
2803 .bit_or => .@"or",2802 .bit_or => .@"or",
...@@ -3156,7 +3155,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3156,7 +3155,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3156 const ty_op = air_datas[@intFromEnum(inst)].ty_op;3155 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
3157 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});3156 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
3158 var res: [1]Temp = undefined;3157 var res: [1]Temp = undefined;
3159 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, comptime &.{ .{3158 cg.select(&res, &.{ty_op.ty.toType()}, &ops, comptime &.{ .{
3160 .src_constraints = .{ .{ .signed_or_exact_int = .byte }, .any },3159 .src_constraints = .{ .{ .signed_or_exact_int = .byte }, .any },
3161 .patterns = &.{3160 .patterns = &.{
3162 .{ .src = .{ .mut_mem, .none } },3161 .{ .src = .{ .mut_mem, .none } },
...@@ -4239,14 +4238,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4239,14 +4238,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4239 .trap => try cg.asmOpOnly(.{ ._, .ud2 }),4238 .trap => try cg.asmOpOnly(.{ ._, .ud2 }),
4240 .breakpoint => try cg.asmOpOnly(.{ ._, .int3 }),4239 .breakpoint => try cg.asmOpOnly(.{ ._, .int3 }),
4241 .ret_addr => if (use_old) try cg.airRetAddr(inst) else {4240 .ret_addr => if (use_old) try cg.airRetAddr(inst) else {
4242 var slot = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .load_frame = .{4241 var slot = try cg.tempInit(.usize, .{ .load_frame = .{
4243 .index = .ret_addr,4242 .index = .ret_addr,
4244 } });4243 } });
4245 while (try slot.toRegClass(true, .general_purpose, cg)) {}4244 while (try slot.toRegClass(true, .general_purpose, cg)) {}
4246 try slot.moveTo(inst, cg);4245 try slot.moveTo(inst, cg);
4247 },4246 },
4248 .frame_addr => if (use_old) try cg.airFrameAddress(inst) else {4247 .frame_addr => if (use_old) try cg.airFrameAddress(inst) else {
4249 var slot = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .lea_frame = .{4248 var slot = try cg.tempInit(.usize, .{ .lea_frame = .{
4250 .index = .base_ptr,4249 .index = .base_ptr,
4251 } });4250 } });
4252 try slot.moveTo(inst, cg);4251 try slot.moveTo(inst, cg);
...@@ -4260,7 +4259,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4260,7 +4259,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4260 const ty_op = air_datas[@intFromEnum(inst)].ty_op;4259 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
4261 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});4260 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
4262 var res: [1]Temp = undefined;4261 var res: [1]Temp = undefined;
4263 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, comptime &.{ .{4262 cg.select(&res, &.{ty_op.ty.toType()}, &ops, comptime &.{ .{
4264 .required_features = .{ .slow_incdec, null, null, null },4263 .required_features = .{ .slow_incdec, null, null, null },
4265 .src_constraints = .{ .{ .exact_signed_int = 1 }, .any },4264 .src_constraints = .{ .{ .exact_signed_int = 1 }, .any },
4266 .patterns = &.{4265 .patterns = &.{
...@@ -6997,7 +6996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -6997,7 +6996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
6997 switch (extra.compareOperator()) {6996 switch (extra.compareOperator()) {
6998 .lt => unreachable,6997 .lt => unreachable,
6999 .lte => unreachable,6998 .lte => unreachable,
7000 .eq, .neq => |cmp_op| cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (cmp_op) {6999 .eq, .neq => |cmp_op| cg.select(&res, &.{ty_pl.ty.toType()}, &ops, switch (@as(Condition, switch (cmp_op) {
7001 else => unreachable,7000 else => unreachable,
7002 .eq => .e,7001 .eq => .e,
7003 .neq => .ne,7002 .neq => .ne,
...@@ -8825,7 +8824,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -8825,7 +8824,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8825 .unsigned;8824 .unsigned;
8826 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });8825 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
8827 var res: [1]Temp = undefined;8826 var res: [1]Temp = undefined;
8828 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (signedness) {8827 cg.select(&res, &.{.bool}, &ops, switch (@as(Condition, switch (signedness) {
8829 .signed => switch (air_tag) {8828 .signed => switch (air_tag) {
8830 else => unreachable,8829 else => unreachable,
8831 .cmp_lt, .cmp_lt_optimized => .l,8830 .cmp_lt, .cmp_lt_optimized => .l,
...@@ -9011,7 +9010,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9011,7 +9010,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9011 });9010 });
9012 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });9011 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9013 var res: [1]Temp = undefined;9012 var res: [1]Temp = undefined;
9014 cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (air_tag) {9013 cg.select(&res, &.{.bool}, &ops, switch (@as(Condition, switch (air_tag) {
9015 else => unreachable,9014 else => unreachable,
9016 .cmp_eq, .cmp_eq_optimized => .e,9015 .cmp_eq, .cmp_eq_optimized => .e,
9017 .cmp_neq, .cmp_neq_optimized => .ne,9016 .cmp_neq, .cmp_neq_optimized => .ne,
...@@ -9540,7 +9539,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9540,7 +9539,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9540 .fromSize(opt_child_abi_size) }),9539 .fromSize(opt_child_abi_size) }),
9541 .u(0),9540 .u(0),
9542 );9541 );
9543 var is_null = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .eflags = .e });9542 var is_null = try cg.tempInit(.bool, .{ .eflags = .e });
9544 try ops[0].die(cg);9543 try ops[0].die(cg);
9545 try is_null.moveTo(inst, cg);9544 try is_null.moveTo(inst, cg);
9546 },9545 },
...@@ -9563,7 +9562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9563,7 +9562,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9563 .fromSize(opt_child_abi_size) }),9562 .fromSize(opt_child_abi_size) }),
9564 .u(0),9563 .u(0),
9565 );9564 );
9566 var is_non_null = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .eflags = .ne });9565 var is_non_null = try cg.tempInit(.bool, .{ .eflags = .ne });
9567 try ops[0].die(cg);9566 try ops[0].die(cg);
9568 try is_non_null.moveTo(inst, cg);9567 try is_non_null.moveTo(inst, cg);
9569 },9568 },
...@@ -9581,7 +9580,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9581,7 +9580,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9581 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),9580 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
9582 .u(0),9581 .u(0),
9583 );9582 );
9584 var is_err = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .eflags = .ne });9583 var is_err = try cg.tempInit(.bool, .{ .eflags = .ne });
9585 try ops[0].die(cg);9584 try ops[0].die(cg);
9586 try is_err.moveTo(inst, cg);9585 try is_err.moveTo(inst, cg);
9587 },9586 },
...@@ -9599,7 +9598,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9599,7 +9598,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9599 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),9598 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
9600 .u(0),9599 .u(0),
9601 );9600 );
9602 var is_non_err = try cg.tempFromValue(cg.typeOfIndex(inst), .{ .eflags = .e });9601 var is_non_err = try cg.tempInit(.bool, .{ .eflags = .e });
9603 try ops[0].die(cg);9602 try ops[0].die(cg);
9604 try is_non_err.moveTo(inst, cg);9603 try is_non_err.moveTo(inst, cg);
9605 },9604 },
...@@ -9631,8 +9630,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9631,8 +9630,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9631 const opt_child_ty = opt_ty.optionalChild(zcu);9630 const opt_child_ty = opt_ty.optionalChild(zcu);
9632 const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));9631 const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));
9633 try ops[0].toOffset(opt_child_abi_size, cg);9632 try ops[0].toOffset(opt_child_abi_size, cg);
9634 var has_value = try cg.tempFromValue(.bool, .{ .immediate = 1 });9633 var has_value = try cg.tempInit(.bool, .{ .immediate = 1 });
9635 try ops[0].store(&has_value, cg);9634 try ops[0].store(0, &has_value, cg);
9636 try has_value.die(cg);9635 try has_value.die(cg);
9637 try ops[0].toOffset(-opt_child_abi_size, cg);9636 try ops[0].toOffset(-opt_child_abi_size, cg);
9638 }9637 }
...@@ -9654,7 +9653,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9654,7 +9653,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9654 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));9653 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
9655 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9654 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9656 try ops[0].toOffset(eu_err_off, cg);9655 try ops[0].toOffset(eu_err_off, cg);
9657 var err = try ops[0].load(eu_ty.errorUnionSet(zcu), cg);9656 var err = try ops[0].load(0, eu_ty.errorUnionSet(zcu), cg);
9658 try ops[0].die(cg);9657 try ops[0].die(cg);
9659 try err.moveTo(inst, cg);9658 try err.moveTo(inst, cg);
9660 },9659 },
...@@ -9667,8 +9666,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9667,8 +9666,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9667 const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));9666 const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
9668 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9667 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9669 try ops[0].toOffset(eu_err_off, cg);9668 try ops[0].toOffset(eu_err_off, cg);
9670 var no_err = try cg.tempFromValue(eu_err_ty, .{ .immediate = 0 });9669 var no_err = try cg.tempInit(eu_err_ty, .{ .immediate = 0 });
9671 try ops[0].store(&no_err, cg);9670 try ops[0].store(0, &no_err, cg);
9672 try no_err.die(cg);9671 try no_err.die(cg);
9673 try ops[0].toOffset(eu_pl_off - eu_err_off, cg);9672 try ops[0].toOffset(eu_pl_off - eu_err_off, cg);
9674 try ops[0].moveTo(inst, cg);9673 try ops[0].moveTo(inst, cg);
...@@ -9679,7 +9678,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9679,7 +9678,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9679 var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand});9678 var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand});
9680 try ops[0].toOffset(cg.fieldOffset(9679 try ops[0].toOffset(cg.fieldOffset(
9681 cg.typeOf(extra.struct_operand),9680 cg.typeOf(extra.struct_operand),
9682 cg.typeOfIndex(inst),9681 ty_pl.ty.toType(),
9683 extra.field_index,9682 extra.field_index,
9684 ), cg);9683 ), cg);
9685 try ops[0].moveTo(inst, cg);9684 try ops[0].moveTo(inst, cg);
...@@ -9689,7 +9688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9689,7 +9688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9689 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9688 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9690 try ops[0].toOffset(cg.fieldOffset(9689 try ops[0].toOffset(cg.fieldOffset(
9691 cg.typeOf(ty_op.operand),9690 cg.typeOf(ty_op.operand),
9692 cg.typeOfIndex(inst),9691 ty_op.ty.toType(),
9693 0,9692 0,
9694 ), cg);9693 ), cg);
9695 try ops[0].moveTo(inst, cg);9694 try ops[0].moveTo(inst, cg);
...@@ -9699,7 +9698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9699,7 +9698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9699 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9698 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9700 try ops[0].toOffset(cg.fieldOffset(9699 try ops[0].toOffset(cg.fieldOffset(
9701 cg.typeOf(ty_op.operand),9700 cg.typeOf(ty_op.operand),
9702 cg.typeOfIndex(inst),9701 ty_op.ty.toType(),
9703 1,9702 1,
9704 ), cg);9703 ), cg);
9705 try ops[0].moveTo(inst, cg);9704 try ops[0].moveTo(inst, cg);
...@@ -9709,7 +9708,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9709,7 +9708,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9709 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9708 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9710 try ops[0].toOffset(cg.fieldOffset(9709 try ops[0].toOffset(cg.fieldOffset(
9711 cg.typeOf(ty_op.operand),9710 cg.typeOf(ty_op.operand),
9712 cg.typeOfIndex(inst),9711 ty_op.ty.toType(),
9713 2,9712 2,
9714 ), cg);9713 ), cg);
9715 try ops[0].moveTo(inst, cg);9714 try ops[0].moveTo(inst, cg);
...@@ -9719,11 +9718,29 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9719,11 +9718,29 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9719 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9718 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9720 try ops[0].toOffset(cg.fieldOffset(9719 try ops[0].toOffset(cg.fieldOffset(
9721 cg.typeOf(ty_op.operand),9720 cg.typeOf(ty_op.operand),
9722 cg.typeOfIndex(inst),9721 ty_op.ty.toType(),
9723 3,9722 3,
9724 ), cg);9723 ), cg);
9725 try ops[0].moveTo(inst, cg);9724 try ops[0].moveTo(inst, cg);
9726 },9725 },
9726 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
9727 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
9728 const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);
9729 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9730 const union_layout = union_ty.unionGetLayout(zcu);
9731 if (union_layout.tag_size > 0) try ops[0].store(@intCast(union_layout.tagOffset()), &ops[1], cg);
9732 for (ops) |op| try op.die(cg);
9733 },
9734 .get_union_tag => if (use_old) try cg.airGetUnionTag(inst) else {
9735 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
9736 const union_ty = cg.typeOf(ty_op.operand);
9737 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9738 const union_layout = union_ty.unionGetLayout(zcu);
9739 assert(union_layout.tag_size > 0);
9740 var res = try ops[0].read(@intCast(union_layout.tagOffset()), ty_op.ty.toType(), cg);
9741 for (ops) |op| if (op.index != res.index) try op.die(cg);
9742 try res.moveTo(inst, cg);
9743 },
9727 .slice => if (use_old) try cg.airSlice(inst) else {9744 .slice => if (use_old) try cg.airSlice(inst) else {
9728 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;9745 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
9729 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;9746 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -9764,7 +9781,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9764,7 +9781,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9764 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });9781 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9765 try ops[0].toSlicePtr(cg);9782 try ops[0].toSlicePtr(cg);
9766 var res: [1]Temp = undefined;9783 var res: [1]Temp = undefined;
9767 const res_ty = cg.typeOfIndex(inst);9784 const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu);
9768 cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{9785 cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{
9769 .dst_constraints = .{.{ .int = .byte }},9786 .dst_constraints = .{.{ .int = .byte }},
9770 .patterns = &.{9787 .patterns = &.{
...@@ -9840,7 +9857,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9840,7 +9857,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9840 } },9857 } },
9841 } }) catch |err| switch (err) {9858 } }) catch |err| switch (err) {
9842 error.SelectFailed => switch (res_ty.abiSize(zcu)) {9859 error.SelectFailed => switch (res_ty.abiSize(zcu)) {
9843 0 => res[0] = try cg.tempFromValue(res_ty, .none),9860 0 => res[0] = try cg.tempInit(res_ty, .none),
9844 else => |elem_size| {9861 else => |elem_size| {
9845 while (true) for (&ops) |*op| {9862 while (true) for (&ops) |*op| {
9846 if (try op.toRegClass(true, .general_purpose, cg)) break;9863 if (try op.toRegClass(true, .general_purpose, cg)) break;
...@@ -9878,7 +9895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9878,7 +9895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9878 .scale = .fromFactor(@intCast(elem_size)),9895 .scale = .fromFactor(@intCast(elem_size)),
9879 } },9896 } },
9880 });9897 });
9881 res[0] = try ops[0].load(res_ty, cg);9898 res[0] = try ops[0].load(0, res_ty, cg);
9882 },9899 },
9883 },9900 },
9884 else => |e| return e,9901 else => |e| return e,
...@@ -9897,7 +9914,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9897,7 +9914,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9897 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;9914 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
9898 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });9915 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9899 try ops[0].toSlicePtr(cg);9916 try ops[0].toSlicePtr(cg);
9900 const dst_ty = cg.typeOfIndex(inst);9917 const dst_ty = ty_pl.ty.toType();
9901 if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {9918 if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
9902 const elem_size = dst_ty.childType(zcu).abiSize(zcu);9919 const elem_size = dst_ty.childType(zcu).abiSize(zcu);
9903 if (elem_size == 0) break :zero_offset;9920 if (elem_size == 0) break :zero_offset;
...@@ -9944,19 +9961,38 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9944,19 +9961,38 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9944 .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else {9961 .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else {
9945 const ty_op = air_datas[@intFromEnum(inst)].ty_op;9962 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
9946 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});9963 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
9947 var len = try cg.tempFromValue(.usize, .{9964 var len = try cg.tempInit(.usize, .{
9948 .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),9965 .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),
9949 });9966 });
9950 try ops[0].toPair(&len, cg);9967 try ops[0].toPair(&len, cg);
9951 try ops[0].moveTo(inst, cg);9968 try ops[0].moveTo(inst, cg);
9952 },9969 },
9953 .error_set_has_value => return cg.fail("TODO implement error_set_has_value", .{}),9970 .error_set_has_value => return cg.fail("TODO implement error_set_has_value", .{}),
9971 .union_init => if (use_old) try cg.airUnionInit(inst) else {
9972 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
9973 const extra = cg.air.extraData(Air.UnionInit, ty_pl.payload).data;
9974 const union_ty = ty_pl.ty.toType();
9975 var ops = try cg.tempsFromOperands(inst, .{extra.init});
9976 var res = try cg.tempAllocMem(union_ty);
9977 const union_layout = union_ty.unionGetLayout(zcu);
9978 if (union_layout.tag_size > 0) {
9979 var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex(
9980 union_ty.unionTagTypeSafety(zcu).?,
9981 extra.field_index,
9982 ));
9983 try res.write(@intCast(union_layout.tagOffset()), &tag_temp, cg);
9984 try tag_temp.die(cg);
9985 }
9986 try res.write(@intCast(union_layout.payloadOffset()), &ops[0], cg);
9987 try ops[0].die(cg);
9988 try res.moveTo(inst, cg);
9989 },
9954 .field_parent_ptr => if (use_old) try cg.airFieldParentPtr(inst) else {9990 .field_parent_ptr => if (use_old) try cg.airFieldParentPtr(inst) else {
9955 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;9991 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
9956 const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;9992 const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
9957 var ops = try cg.tempsFromOperands(inst, .{extra.field_ptr});9993 var ops = try cg.tempsFromOperands(inst, .{extra.field_ptr});
9958 try ops[0].toOffset(-cg.fieldOffset(9994 try ops[0].toOffset(-cg.fieldOffset(
9959 cg.typeOfIndex(inst),9995 ty_pl.ty.toType(),
9960 cg.typeOf(extra.field_ptr),9996 cg.typeOf(extra.field_ptr),
9961 extra.field_index,9997 extra.field_index,
9962 ), cg);9998 ), cg);
...@@ -10273,7 +10309,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok...@@ -10273,7 +10309,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok
10273 };10309 };
1027410310
10275 if (reg_ok) need_mem: {10311 if (reg_ok) need_mem: {
10276 if (abi_size <= @as(u32, switch (ty.zigTypeTag(zcu)) {10312 if (std.math.isPowerOfTwo(abi_size) and abi_size <= @as(u32, switch (ty.zigTypeTag(zcu)) {
10277 .float => switch (ty.floatBits(self.target.*)) {10313 .float => switch (ty.floatBits(self.target.*)) {
10278 16, 32, 64, 128 => 16,10314 16, 32, 64, 128 => 16,
10279 80 => break :need_mem,10315 80 => break :need_mem,
...@@ -11042,7 +11078,8 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -11042,7 +11078,8 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
11042 if (src_mcv.getReg()) |reg| self.register_manager.lockRegAssumeUnused(reg) else null;11078 if (src_mcv.getReg()) |reg| self.register_manager.lockRegAssumeUnused(reg) else null;
11043 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);11079 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1104411080
11045 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))11081 const dst_mcv = if (src_mcv.isRegister() and src_mcv.getReg().?.class() == self.regClassForType(dst_ty) and
11082 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
11046 src_mcv11083 src_mcv
11047 else if (dst_abi_size <= 8)11084 else if (dst_abi_size <= 8)
11048 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv)11085 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv)
...@@ -15513,12 +15550,12 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -15513,12 +15550,12 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
15513 const ptr_ty = self.typeOf(ty_op.operand);15550 const ptr_ty = self.typeOf(ty_op.operand);
15514 const elem_size = elem_ty.abiSize(zcu);15551 const elem_size = elem_ty.abiSize(zcu);
1551515552
15516 const elem_rc = self.regSetForType(elem_ty);15553 const elem_rs = self.regSetForType(elem_ty);
15517 const ptr_rc = self.regSetForType(ptr_ty);15554 const ptr_rs = self.regSetForType(ptr_ty);
1551815555
15519 const ptr_mcv = try self.resolveInst(ty_op.operand);15556 const ptr_mcv = try self.resolveInst(ty_op.operand);
15520 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and15557 const dst_mcv = if (elem_size <= 8 and std.math.isPowerOfTwo(elem_size) and
15521 self.reuseOperand(inst, ty_op.operand, 0, ptr_mcv))15558 elem_rs.supersetOf(ptr_rs) and self.reuseOperand(inst, ty_op.operand, 0, ptr_mcv))
15522 // The MCValue that holds the pointer can be re-used as the value.15559 // The MCValue that holds the pointer can be re-used as the value.
15523 ptr_mcv15560 ptr_mcv
15524 else15561 else
...@@ -28295,17 +28332,19 @@ const Temp = struct {...@@ -28295,17 +28332,19 @@ const Temp = struct {
28295 return true;28332 return true;
28296 }28333 }
2829728334
28298 fn load(ptr: *Temp, val_ty: Type, cg: *CodeGen) !Temp {28335 fn load(ptr: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp {
28299 const val = try cg.tempAlloc(val_ty);28336 const val = try cg.tempAlloc(val_ty);
28300 switch (val.tracking(cg).short) {28337 const val_mcv = val.tracking(cg).short;
28338 switch (val_mcv) {
28301 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),28339 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28302 .register => |val_reg| {28340 .register => |val_reg| {
28303 while (try ptr.toLea(cg)) {}28341 while (try ptr.toLea(cg)) {}
28304 try cg.genSetReg(val_reg, val_ty, ptr.tracking(cg).short.deref(), .{});28342 try cg.genSetReg(val_reg, val_ty, ptr.tracking(cg).short.offset(disp).deref(), .{});
28305 },28343 },
28306 .load_frame => |val_frame_addr| {28344 .memory, .indirect, .load_frame, .load_symbol => {
28307 var val_ptr = try cg.tempFromValue(.usize, .{ .lea_frame = val_frame_addr });28345 try ptr.toOffset(disp, cg);
28308 var len = try cg.tempFromValue(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });28346 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
28347 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
28309 try val_ptr.memcpy(ptr, &len, cg);28348 try val_ptr.memcpy(ptr, &len, cg);
28310 try val_ptr.die(cg);28349 try val_ptr.die(cg);
28311 try len.die(cg);28350 try len.die(cg);
...@@ -28314,27 +28353,38 @@ const Temp = struct {...@@ -28314,27 +28353,38 @@ const Temp = struct {
28314 return val;28353 return val;
28315 }28354 }
2831628355
28317 fn store(ptr: *Temp, val: *Temp, cg: *CodeGen) !void {28356 fn store(ptr: *Temp, disp: i32, val: *Temp, cg: *CodeGen) !void {
28318 const val_ty = val.typeOf(cg);28357 const val_ty = val.typeOf(cg);
28319 const val_abi_size: u32 = @intCast(val_ty.abiSize(cg.pt.zcu));
28320 val: switch (val.tracking(cg).short) {28358 val: switch (val.tracking(cg).short) {
28321 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),28359 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28322 .immediate => |imm| if (std.math.cast(i32, imm)) |s| {28360 .immediate => |val_imm| {
28361 const val_op: Immediate = if (std.math.cast(u32, val_imm)) |val_uimm32|
28362 .u(val_uimm32)
28363 else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32|
28364 .s(val_simm32)
28365 else
28366 continue :val .{ .register = undefined };
28323 while (try ptr.toLea(cg)) {}28367 while (try ptr.toLea(cg)) {}
28324 try cg.asmMemoryImmediate(28368 try cg.asmMemoryImmediate(
28325 .{ ._, .mov },28369 .{ ._, .mov },
28326 try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }),28370 try ptr.tracking(cg).short.deref().mem(cg, .{
28327 .s(s),28371 .size = cg.memSize(val_ty),
28372 .disp = disp,
28373 }),
28374 val_op,
28328 );28375 );
28329 } else continue :val .{ .register = undefined },28376 },
28330 .register => {28377 .register => {
28331 while (try ptr.toLea(cg) or try val.toRegClass(true, .general_purpose, cg)) {}28378 while (try ptr.toLea(cg) or try val.toRegClass(true, .general_purpose, cg)) {}
28332 const val_reg = val.tracking(cg).short.register;28379 const val_reg = val.tracking(cg).short.register;
28333 switch (val_reg.class()) {28380 switch (val_reg.class()) {
28334 .general_purpose => try cg.asmMemoryRegister(28381 .general_purpose => try cg.asmMemoryRegister(
28335 .{ ._, .mov },28382 .{ ._, .mov },
28336 try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }),28383 try ptr.tracking(cg).short.deref().mem(cg, .{
28337 registerAlias(val_reg, val_abi_size),28384 .size = cg.memSize(val_ty),
28385 .disp = disp,
28386 }),
28387 registerAlias(val_reg, @intCast(val_ty.abiSize(cg.pt.zcu))),
28338 ),28388 ),
28339 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),28389 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28340 }28390 }
...@@ -28342,6 +28392,111 @@ const Temp = struct {...@@ -28342,6 +28392,111 @@ const Temp = struct {
28342 }28392 }
28343 }28393 }
2834428394
28395 fn read(src: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp {
28396 const val = try cg.tempAlloc(val_ty);
28397 while (try src.toBase(cg)) {}
28398 const val_mcv = val.tracking(cg).short;
28399 switch (val_mcv) {
28400 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28401 .register => |val_reg| try src.readReg(disp, val_ty, registerAlias(
28402 val_reg,
28403 @intCast(val_ty.abiSize(cg.pt.zcu)),
28404 ), cg),
28405 }
28406 return val;
28407 }
28408
28409 fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void {
28410 const strat = try cg.moveStrategy(dst_ty, dst_reg.class(), false);
28411 try strat.read(cg, dst_reg, try src.tracking(cg).short.mem(cg, .{
28412 .size = .fromBitSize(@min(8 * dst_ty.abiSize(cg.pt.zcu), dst_reg.bitSize())),
28413 .disp = disp,
28414 }));
28415 }
28416
28417 fn write(dst: *Temp, disp: i32, val: *Temp, cg: *CodeGen) !void {
28418 const val_ty = val.typeOf(cg);
28419 while (try dst.toBase(cg)) {}
28420 val_to_gpr: while (true) : (while (try val.toRegClass(false, .general_purpose, cg)) {}) {
28421 const val_mcv = val.tracking(cg).short;
28422 switch (val_mcv) {
28423 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28424 .immediate => |val_imm| {
28425 const val_op: Immediate = if (std.math.cast(u32, val_imm)) |val_uimm32|
28426 .u(val_uimm32)
28427 else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32|
28428 .s(val_simm32)
28429 else
28430 continue :val_to_gpr;
28431 try cg.asmMemoryImmediate(
28432 .{ ._, .mov },
28433 try dst.tracking(cg).short.mem(cg, .{
28434 .size = cg.memSize(val_ty),
28435 .disp = disp,
28436 }),
28437 val_op,
28438 );
28439 },
28440 .register => |val_reg| try dst.writeReg(disp, val_ty, registerAlias(
28441 val_reg,
28442 @intCast(val_ty.abiSize(cg.pt.zcu)),
28443 ), cg),
28444 inline .register_pair, .register_triple, .register_quadruple => |val_regs| {
28445 var part_disp = disp;
28446 for (val_regs) |val_reg| {
28447 try dst.writeReg(part_disp, val_ty, val_reg, cg);
28448 part_disp += @divExact(val_reg.bitSize(), 8);
28449 }
28450 },
28451 .register_offset => |val_reg_off| switch (val_reg_off.off) {
28452 0 => try dst.writeReg(disp, val_ty, registerAlias(
28453 val_reg_off.reg,
28454 @intCast(val_ty.abiSize(cg.pt.zcu)),
28455 ), cg),
28456 else => continue :val_to_gpr,
28457 },
28458 .lea_frame, .lea_symbol => continue :val_to_gpr,
28459 .memory, .indirect, .load_frame, .load_symbol => {
28460 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(disp));
28461 var val_ptr = try cg.tempInit(.usize, val_mcv.address());
28462 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
28463 try dst_ptr.memcpy(&val_ptr, &len, cg);
28464 try dst_ptr.die(cg);
28465 try val_ptr.die(cg);
28466 try len.die(cg);
28467 },
28468 }
28469 break;
28470 }
28471 }
28472
28473 fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) !void {
28474 const src_rc = src_reg.class();
28475 const src_abi_size = src_ty.abiSize(cg.pt.zcu);
28476 const strat = try cg.moveStrategy(src_ty, src_rc, false);
28477 if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) {
28478 try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{
28479 .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())),
28480 .disp = disp,
28481 }), src_reg);
28482 } else {
28483 const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu);
28484 const frame_index = try cg.allocFrameIndex(frame_alloc);
28485 const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size);
28486 try strat.write(cg, .{
28487 .base = .{ .frame = frame_index },
28488 .mod = .{ .rm = .{ .size = frame_size } },
28489 }, src_reg);
28490 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address());
28491 var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });
28492 var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size });
28493 try dst_ptr.memcpy(&src_ptr, &len, cg);
28494 try dst_ptr.die(cg);
28495 try src_ptr.die(cg);
28496 try len.die(cg);
28497 }
28498 }
28499
28345 fn memcpy(dst: *Temp, src: *Temp, len: *Temp, cg: *CodeGen) !void {28500 fn memcpy(dst: *Temp, src: *Temp, len: *Temp, cg: *CodeGen) !void {
28346 while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| {28501 while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| {
28347 if (try temp.toReg(reg, cg)) break;28502 if (try temp.toReg(reg, cg)) break;
...@@ -28498,7 +28653,7 @@ fn tempAllocMem(cg: *CodeGen, ty: Type) !Temp {...@@ -28498,7 +28653,7 @@ fn tempAllocMem(cg: *CodeGen, ty: Type) !Temp {
28498 return .{ .index = temp_index.toIndex() };28653 return .{ .index = temp_index.toIndex() };
28499}28654}
2850028655
28501fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp {28656fn tempInit(cg: *CodeGen, ty: Type, value: MCValue) !Temp {
28502 const temp_index = cg.next_temp_index;28657 const temp_index = cg.next_temp_index;
28503 temp_index.tracking(cg).* = .init(value);28658 temp_index.tracking(cg).* = .init(value);
28504 cg.temp_type[@intFromEnum(temp_index)] = ty;28659 cg.temp_type[@intFromEnum(temp_index)] = ty;
...@@ -28507,6 +28662,10 @@ fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp {...@@ -28507,6 +28662,10 @@ fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp {
28507 return .{ .index = temp_index.toIndex() };28662 return .{ .index = temp_index.toIndex() };
28508}28663}
2850928664
28665fn tempFromValue(cg: *CodeGen, value: Value) !Temp {
28666 return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.genTypedValue(value));
28667}
28668
28510fn tempFromOperand(28669fn tempFromOperand(
28511 cg: *CodeGen,28670 cg: *CodeGen,
28512 inst: Air.Inst.Index,28671 inst: Air.Inst.Index,
...@@ -28549,7 +28708,7 @@ fn tempFromOperand(...@@ -28549,7 +28708,7 @@ fn tempFromOperand(
28549 else => break :init const_mcv,28708 else => break :init const_mcv,
28550 }28709 }
28551 });28710 });
28552 return cg.tempFromValue(.fromInterned(ip.typeOf(val)), gop.value_ptr.short);28711 return cg.tempInit(.fromInterned(ip.typeOf(val)), gop.value_ptr.short);
28553 }28712 }
2855428713
28555 const temp_index = cg.next_temp_index;28714 const temp_index = cg.next_temp_index;
...@@ -29023,8 +29182,8 @@ const Select = struct {...@@ -29023,8 +29182,8 @@ const Select = struct {
29023 return switch (spec.kind) {29182 return switch (spec.kind) {
29024 .unused => null,29183 .unused => null,
29025 .any => try cg.tempAlloc(spec.type),29184 .any => try cg.tempAlloc(spec.type),
29026 .cc => |cc| try cg.tempFromValue(spec.type, .{ .eflags = cc }),29185 .cc => |cc| try cg.tempInit(spec.type, .{ .eflags = cc }),
29027 .reg => |reg| try cg.tempFromValue(spec.type, .{ .register = reg }),29186 .reg => |reg| try cg.tempInit(spec.type, .{ .register = reg }),
29028 .rc => |rc| try cg.tempAllocReg(spec.type, regSetForRegClass(rc)),29187 .rc => |rc| try cg.tempAllocReg(spec.type, regSetForRegClass(rc)),
29029 .rc_mask => |rc_mask| try cg.tempAllocReg(spec.type, regSetForRegClass(rc_mask.rc)),29188 .rc_mask => |rc_mask| try cg.tempAllocReg(spec.type, regSetForRegClass(rc_mask.rc)),
29030 .mem => try cg.tempAllocMem(spec.type),29189 .mem => try cg.tempAllocMem(spec.type),
...@@ -29081,18 +29240,14 @@ const Select = struct {...@@ -29081,18 +29240,14 @@ const Select = struct {
29081 break :res_scalar .{ scalar_int_ty, try pt.intValue_big(scalar_int_ty, big_int.toConst()) };29240 break :res_scalar .{ scalar_int_ty, try pt.intValue_big(scalar_int_ty, big_int.toConst()) };
29082 },29241 },
29083 };29242 };
29084 const res_ty, const res_val: Value = if (vector_len) |len| res: {29243 const res_val: Value = if (vector_len) |len| .fromInterned(try pt.intern(.{ .aggregate = .{
29085 const vector_ty = try pt.vectorType(.{29244 .ty = (try pt.vectorType(.{
29086 .len = len,29245 .len = len,
29087 .child = res_scalar_ty.toIntern(),29246 .child = res_scalar_ty.toIntern(),
29088 });29247 })).toIntern(),
29089 const vector_val = try pt.intern(.{ .aggregate = .{29248 .storage = .{ .repeated_elem = res_scalar_val.toIntern() },
29090 .ty = vector_ty.toIntern(),29249 } })) else res_scalar_val;
29091 .storage = .{ .repeated_elem = res_scalar_val.toIntern() },29250 return try cg.tempFromValue(res_val);
29092 } });
29093 break :res .{ vector_ty, .fromInterned(vector_val) };
29094 } else .{ res_scalar_ty, res_scalar_val };
29095 return try cg.tempFromValue(res_ty, try cg.genTypedValue(res_val));
29096 },29251 },
29097 .ref => |ref| ref.deref(s),29252 .ref => |ref| ref.deref(s),
29098 .ref_mask => |ref_mask| ref_mask.ref.deref(s),29253 .ref_mask => |ref_mask| ref_mask.ref.deref(s),
test/behavior/union.zig+1-1
...@@ -2246,12 +2246,12 @@ test "matching captures causes union equivalence" {...@@ -2246,12 +2246,12 @@ test "matching captures causes union equivalence" {
2246}2246}
22472247
2248test "signed enum tag with negative value" {2248test "signed enum tag with negative value" {
2249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2250 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO2249 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
2251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2253 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;2252 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2254 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2253 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2254 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
22552255
2256 const Enum = enum(i8) {2256 const Enum = enum(i8) {
2257 a = -1,2257 a = -1,