| ... | ... | @@ -2467,8 +2467,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2467 | 2467 | .memcpy => try cg.airMemcpy(inst), |
| 2468 | 2468 | .memset => try cg.airMemset(inst, false), |
| 2469 | 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 | 2470 | .ctz => try cg.airCtz(inst), |
| 2473 | 2471 | .popcount => try cg.airPopCount(inst), |
| 2474 | 2472 | .byte_swap => try cg.airByteSwap(inst), |
| ... | ... | @@ -2480,7 +2478,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2480 | 2478 | .shuffle => try cg.airShuffle(inst), |
| 2481 | 2479 | .reduce => try cg.airReduce(inst), |
| 2482 | 2480 | .aggregate_init => try cg.airAggregateInit(inst), |
| 2483 | | .union_init => try cg.airUnionInit(inst), |
| 2484 | 2481 | .prefetch => try cg.airPrefetch(inst), |
| 2485 | 2482 | .mul_add => try cg.airMulAdd(inst), |
| 2486 | 2483 | |
| ... | ... | @@ -2528,7 +2525,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2528 | 2525 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2529 | 2526 | try ops[0].toSlicePtr(cg); |
| 2530 | 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 | 2529 | .patterns = &.{ |
| 2533 | 2530 | .{ .src = .{ .to_gpr, .simm32 } }, |
| 2534 | 2531 | }, |
| ... | ... | @@ -2645,7 +2642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2645 | 2642 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2646 | 2643 | try ops[0].toSlicePtr(cg); |
| 2647 | 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 | 2646 | .patterns = &.{ |
| 2650 | 2647 | .{ .src = .{ .to_gpr, .simm32 } }, |
| 2651 | 2648 | }, |
| ... | ... | @@ -2772,20 +2769,22 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2772 | 2769 | try res[0].moveTo(inst, cg); |
| 2773 | 2770 | }, |
| 2774 | 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 | 2774 | .index = try cg.allocMemPtr(inst), |
| 2777 | 2775 | } }); |
| 2778 | 2776 | try slot.moveTo(inst, cg); |
| 2779 | 2777 | }, |
| 2780 | 2778 | .inferred_alloc, .inferred_alloc_comptime => unreachable, |
| 2781 | 2779 | .ret_ptr => if (use_old) try cg.airRetPtr(inst) else { |
| 2780 | const ty = air_datas[@intFromEnum(inst)].ty; |
| 2782 | 2781 | var slot = switch (cg.ret_mcv.long) { |
| 2783 | 2782 | else => unreachable, |
| 2784 | | .none => try cg.tempFromValue(cg.typeOfIndex(inst), .{ .lea_frame = .{ |
| 2783 | .none => try cg.tempInit(ty, .{ .lea_frame = .{ |
| 2785 | 2784 | .index = try cg.allocMemPtr(inst), |
| 2786 | 2785 | } }), |
| 2787 | 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 | 2788 | try slot.toOffset(cg.ret_mcv.short.indirect.off, cg); |
| 2790 | 2789 | break :slot slot; |
| 2791 | 2790 | }, |
| ... | ... | @@ -2797,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2797 | 2796 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 2798 | 2797 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2799 | 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 | 2800 | else => unreachable, |
| 2802 | 2801 | .bit_and => .@"and", |
| 2803 | 2802 | .bit_or => .@"or", |
| ... | ... | @@ -3156,7 +3155,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3156 | 3155 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 3157 | 3156 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 3158 | 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 | 3159 | .src_constraints = .{ .{ .signed_or_exact_int = .byte }, .any }, |
| 3161 | 3160 | .patterns = &.{ |
| 3162 | 3161 | .{ .src = .{ .mut_mem, .none } }, |
| ... | ... | @@ -4239,14 +4238,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 4239 | 4238 | .trap => try cg.asmOpOnly(.{ ._, .ud2 }), |
| 4240 | 4239 | .breakpoint => try cg.asmOpOnly(.{ ._, .int3 }), |
| 4241 | 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 | 4242 | .index = .ret_addr, |
| 4244 | 4243 | } }); |
| 4245 | 4244 | while (try slot.toRegClass(true, .general_purpose, cg)) {} |
| 4246 | 4245 | try slot.moveTo(inst, cg); |
| 4247 | 4246 | }, |
| 4248 | 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 | 4249 | .index = .base_ptr, |
| 4251 | 4250 | } }); |
| 4252 | 4251 | try slot.moveTo(inst, cg); |
| ... | ... | @@ -4260,7 +4259,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 4260 | 4259 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 4261 | 4260 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 4262 | 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 | 4263 | .required_features = .{ .slow_incdec, null, null, null }, |
| 4265 | 4264 | .src_constraints = .{ .{ .exact_signed_int = 1 }, .any }, |
| 4266 | 4265 | .patterns = &.{ |
| ... | ... | @@ -6997,7 +6996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 6997 | 6996 | switch (extra.compareOperator()) { |
| 6998 | 6997 | .lt => unreachable, |
| 6999 | 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 | 7000 | else => unreachable, |
| 7002 | 7001 | .eq => .e, |
| 7003 | 7002 | .neq => .ne, |
| ... | ... | @@ -8825,7 +8824,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 8825 | 8824 | .unsigned; |
| 8826 | 8825 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 8827 | 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 | 8828 | .signed => switch (air_tag) { |
| 8830 | 8829 | else => unreachable, |
| 8831 | 8830 | .cmp_lt, .cmp_lt_optimized => .l, |
| ... | ... | @@ -9011,7 +9010,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9011 | 9010 | }); |
| 9012 | 9011 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9013 | 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 | 9014 | else => unreachable, |
| 9016 | 9015 | .cmp_eq, .cmp_eq_optimized => .e, |
| 9017 | 9016 | .cmp_neq, .cmp_neq_optimized => .ne, |
| ... | ... | @@ -9540,7 +9539,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9540 | 9539 | .fromSize(opt_child_abi_size) }), |
| 9541 | 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 | 9543 | try ops[0].die(cg); |
| 9545 | 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 | 9562 | .fromSize(opt_child_abi_size) }), |
| 9564 | 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 | 9566 | try ops[0].die(cg); |
| 9568 | 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 | 9580 | try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }), |
| 9582 | 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 | 9584 | try ops[0].die(cg); |
| 9586 | 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 | 9598 | try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }), |
| 9600 | 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 | 9602 | try ops[0].die(cg); |
| 9604 | 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 | 9630 | const opt_child_ty = opt_ty.optionalChild(zcu); |
| 9632 | 9631 | const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu)); |
| 9633 | 9632 | try ops[0].toOffset(opt_child_abi_size, cg); |
| 9634 | | var has_value = try cg.tempFromValue(.bool, .{ .immediate = 1 }); |
| 9635 | | try ops[0].store(&has_value, cg); |
| 9633 | var has_value = try cg.tempInit(.bool, .{ .immediate = 1 }); |
| 9634 | try ops[0].store(0, &has_value, cg); |
| 9636 | 9635 | try has_value.die(cg); |
| 9637 | 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 | 9653 | const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu)); |
| 9655 | 9654 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9656 | 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 | 9657 | try ops[0].die(cg); |
| 9659 | 9658 | try err.moveTo(inst, cg); |
| 9660 | 9659 | }, |
| ... | ... | @@ -9667,8 +9666,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9667 | 9666 | const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu)); |
| 9668 | 9667 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9669 | 9668 | try ops[0].toOffset(eu_err_off, cg); |
| 9670 | | var no_err = try cg.tempFromValue(eu_err_ty, .{ .immediate = 0 }); |
| 9671 | | try ops[0].store(&no_err, cg); |
| 9669 | var no_err = try cg.tempInit(eu_err_ty, .{ .immediate = 0 }); |
| 9670 | try ops[0].store(0, &no_err, cg); |
| 9672 | 9671 | try no_err.die(cg); |
| 9673 | 9672 | try ops[0].toOffset(eu_pl_off - eu_err_off, cg); |
| 9674 | 9673 | try ops[0].moveTo(inst, cg); |
| ... | ... | @@ -9679,7 +9678,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9679 | 9678 | var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand}); |
| 9680 | 9679 | try ops[0].toOffset(cg.fieldOffset( |
| 9681 | 9680 | cg.typeOf(extra.struct_operand), |
| 9682 | | cg.typeOfIndex(inst), |
| 9681 | ty_pl.ty.toType(), |
| 9683 | 9682 | extra.field_index, |
| 9684 | 9683 | ), cg); |
| 9685 | 9684 | try ops[0].moveTo(inst, cg); |
| ... | ... | @@ -9689,7 +9688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9689 | 9688 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9690 | 9689 | try ops[0].toOffset(cg.fieldOffset( |
| 9691 | 9690 | cg.typeOf(ty_op.operand), |
| 9692 | | cg.typeOfIndex(inst), |
| 9691 | ty_op.ty.toType(), |
| 9693 | 9692 | 0, |
| 9694 | 9693 | ), cg); |
| 9695 | 9694 | try ops[0].moveTo(inst, cg); |
| ... | ... | @@ -9699,7 +9698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9699 | 9698 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9700 | 9699 | try ops[0].toOffset(cg.fieldOffset( |
| 9701 | 9700 | cg.typeOf(ty_op.operand), |
| 9702 | | cg.typeOfIndex(inst), |
| 9701 | ty_op.ty.toType(), |
| 9703 | 9702 | 1, |
| 9704 | 9703 | ), cg); |
| 9705 | 9704 | try ops[0].moveTo(inst, cg); |
| ... | ... | @@ -9709,7 +9708,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9709 | 9708 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9710 | 9709 | try ops[0].toOffset(cg.fieldOffset( |
| 9711 | 9710 | cg.typeOf(ty_op.operand), |
| 9712 | | cg.typeOfIndex(inst), |
| 9711 | ty_op.ty.toType(), |
| 9713 | 9712 | 2, |
| 9714 | 9713 | ), cg); |
| 9715 | 9714 | try ops[0].moveTo(inst, cg); |
| ... | ... | @@ -9719,11 +9718,29 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9719 | 9718 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9720 | 9719 | try ops[0].toOffset(cg.fieldOffset( |
| 9721 | 9720 | cg.typeOf(ty_op.operand), |
| 9722 | | cg.typeOfIndex(inst), |
| 9721 | ty_op.ty.toType(), |
| 9723 | 9722 | 3, |
| 9724 | 9723 | ), cg); |
| 9725 | 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 | 9744 | .slice => if (use_old) try cg.airSlice(inst) else { |
| 9728 | 9745 | const ty_pl = air_datas[@intFromEnum(inst)].ty_pl; |
| 9729 | 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 | 9781 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9765 | 9782 | try ops[0].toSlicePtr(cg); |
| 9766 | 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 | 9785 | cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ |
| 9769 | 9786 | .dst_constraints = .{.{ .int = .byte }}, |
| 9770 | 9787 | .patterns = &.{ |
| ... | ... | @@ -9840,7 +9857,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9840 | 9857 | } }, |
| 9841 | 9858 | } }) catch |err| switch (err) { |
| 9842 | 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 | 9861 | else => |elem_size| { |
| 9845 | 9862 | while (true) for (&ops) |*op| { |
| 9846 | 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 | 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 | 9901 | else => |e| return e, |
| ... | ... | @@ -9897,7 +9914,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9897 | 9914 | const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 9898 | 9915 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9899 | 9916 | try ops[0].toSlicePtr(cg); |
| 9900 | | const dst_ty = cg.typeOfIndex(inst); |
| 9917 | const dst_ty = ty_pl.ty.toType(); |
| 9901 | 9918 | if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: { |
| 9902 | 9919 | const elem_size = dst_ty.childType(zcu).abiSize(zcu); |
| 9903 | 9920 | if (elem_size == 0) break :zero_offset; |
| ... | ... | @@ -9944,19 +9961,38 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9944 | 9961 | .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else { |
| 9945 | 9962 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 9946 | 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 | 9965 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), |
| 9949 | 9966 | }); |
| 9950 | 9967 | try ops[0].toPair(&len, cg); |
| 9951 | 9968 | try ops[0].moveTo(inst, cg); |
| 9952 | 9969 | }, |
| 9953 | 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 | 9990 | .field_parent_ptr => if (use_old) try cg.airFieldParentPtr(inst) else { |
| 9955 | 9991 | const ty_pl = air_datas[@intFromEnum(inst)].ty_pl; |
| 9956 | 9992 | const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 9957 | 9993 | var ops = try cg.tempsFromOperands(inst, .{extra.field_ptr}); |
| 9958 | 9994 | try ops[0].toOffset(-cg.fieldOffset( |
| 9959 | | cg.typeOfIndex(inst), |
| 9995 | ty_pl.ty.toType(), |
| 9960 | 9996 | cg.typeOf(extra.field_ptr), |
| 9961 | 9997 | extra.field_index, |
| 9962 | 9998 | ), cg); |
| ... | ... | @@ -10273,7 +10309,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok |
| 10273 | 10309 | }; |
| 10274 | 10310 | |
| 10275 | 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 | 10313 | .float => switch (ty.floatBits(self.target.*)) { |
| 10278 | 10314 | 16, 32, 64, 128 => 16, |
| 10279 | 10315 | 80 => break :need_mem, |
| ... | ... | @@ -11042,7 +11078,8 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 11042 | 11078 | if (src_mcv.getReg()) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; |
| 11043 | 11079 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 11044 | 11080 | |
| 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 | 11083 | src_mcv |
| 11047 | 11084 | else if (dst_abi_size <= 8) |
| 11048 | 11085 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv) |
| ... | ... | @@ -15513,12 +15550,12 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 15513 | 15550 | const ptr_ty = self.typeOf(ty_op.operand); |
| 15514 | 15551 | const elem_size = elem_ty.abiSize(zcu); |
| 15515 | 15552 | |
| 15516 | | const elem_rc = self.regSetForType(elem_ty); |
| 15517 | | const ptr_rc = self.regSetForType(ptr_ty); |
| 15553 | const elem_rs = self.regSetForType(elem_ty); |
| 15554 | const ptr_rs = self.regSetForType(ptr_ty); |
| 15518 | 15555 | |
| 15519 | 15556 | const ptr_mcv = try self.resolveInst(ty_op.operand); |
| 15520 | | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and |
| 15521 | | self.reuseOperand(inst, ty_op.operand, 0, ptr_mcv)) |
| 15557 | const dst_mcv = if (elem_size <= 8 and std.math.isPowerOfTwo(elem_size) and |
| 15558 | elem_rs.supersetOf(ptr_rs) and self.reuseOperand(inst, ty_op.operand, 0, ptr_mcv)) |
| 15522 | 15559 | // The MCValue that holds the pointer can be re-used as the value. |
| 15523 | 15560 | ptr_mcv |
| 15524 | 15561 | else |
| ... | ... | @@ -28295,17 +28332,19 @@ const Temp = struct { |
| 28295 | 28332 | return true; |
| 28296 | 28333 | } |
| 28297 | 28334 | |
| 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 | 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 | 28339 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28302 | 28340 | .register => |val_reg| { |
| 28303 | 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| { |
| 28307 | | var val_ptr = try cg.tempFromValue(.usize, .{ .lea_frame = val_frame_addr }); |
| 28308 | | var len = try cg.tempFromValue(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28344 | .memory, .indirect, .load_frame, .load_symbol => { |
| 28345 | try ptr.toOffset(disp, cg); |
| 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 | 28348 | try val_ptr.memcpy(ptr, &len, cg); |
| 28310 | 28349 | try val_ptr.die(cg); |
| 28311 | 28350 | try len.die(cg); |
| ... | ... | @@ -28314,27 +28353,38 @@ const Temp = struct { |
| 28314 | 28353 | return val; |
| 28315 | 28354 | } |
| 28316 | 28355 | |
| 28317 | | fn store(ptr: *Temp, val: *Temp, cg: *CodeGen) !void { |
| 28356 | fn store(ptr: *Temp, disp: i32, val: *Temp, cg: *CodeGen) !void { |
| 28318 | 28357 | const val_ty = val.typeOf(cg); |
| 28319 | | const val_abi_size: u32 = @intCast(val_ty.abiSize(cg.pt.zcu)); |
| 28320 | 28358 | val: switch (val.tracking(cg).short) { |
| 28321 | 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 | 28367 | while (try ptr.toLea(cg)) {} |
| 28324 | 28368 | try cg.asmMemoryImmediate( |
| 28325 | 28369 | .{ ._, .mov }, |
| 28326 | | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }), |
| 28327 | | .s(s), |
| 28370 | try ptr.tracking(cg).short.deref().mem(cg, .{ |
| 28371 | .size = cg.memSize(val_ty), |
| 28372 | .disp = disp, |
| 28373 | }), |
| 28374 | val_op, |
| 28328 | 28375 | ); |
| 28329 | | } else continue :val .{ .register = undefined }, |
| 28376 | }, |
| 28330 | 28377 | .register => { |
| 28331 | 28378 | while (try ptr.toLea(cg) or try val.toRegClass(true, .general_purpose, cg)) {} |
| 28332 | 28379 | const val_reg = val.tracking(cg).short.register; |
| 28333 | 28380 | switch (val_reg.class()) { |
| 28334 | 28381 | .general_purpose => try cg.asmMemoryRegister( |
| 28335 | 28382 | .{ ._, .mov }, |
| 28336 | | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }), |
| 28337 | | registerAlias(val_reg, val_abi_size), |
| 28383 | try ptr.tracking(cg).short.deref().mem(cg, .{ |
| 28384 | .size = cg.memSize(val_ty), |
| 28385 | .disp = disp, |
| 28386 | }), |
| 28387 | registerAlias(val_reg, @intCast(val_ty.abiSize(cg.pt.zcu))), |
| 28338 | 28388 | ), |
| 28339 | 28389 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28340 | 28390 | } |
| ... | ... | @@ -28342,6 +28392,111 @@ const Temp = struct { |
| 28342 | 28392 | } |
| 28343 | 28393 | } |
| 28344 | 28394 | |
| 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 | 28500 | fn memcpy(dst: *Temp, src: *Temp, len: *Temp, cg: *CodeGen) !void { |
| 28346 | 28501 | while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| { |
| 28347 | 28502 | if (try temp.toReg(reg, cg)) break; |
| ... | ... | @@ -28498,7 +28653,7 @@ fn tempAllocMem(cg: *CodeGen, ty: Type) !Temp { |
| 28498 | 28653 | return .{ .index = temp_index.toIndex() }; |
| 28499 | 28654 | } |
| 28500 | 28655 | |
| 28501 | | fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp { |
| 28656 | fn tempInit(cg: *CodeGen, ty: Type, value: MCValue) !Temp { |
| 28502 | 28657 | const temp_index = cg.next_temp_index; |
| 28503 | 28658 | temp_index.tracking(cg).* = .init(value); |
| 28504 | 28659 | cg.temp_type[@intFromEnum(temp_index)] = ty; |
| ... | ... | @@ -28507,6 +28662,10 @@ fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp { |
| 28507 | 28662 | return .{ .index = temp_index.toIndex() }; |
| 28508 | 28663 | } |
| 28509 | 28664 | |
| 28665 | fn tempFromValue(cg: *CodeGen, value: Value) !Temp { |
| 28666 | return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.genTypedValue(value)); |
| 28667 | } |
| 28668 | |
| 28510 | 28669 | fn tempFromOperand( |
| 28511 | 28670 | cg: *CodeGen, |
| 28512 | 28671 | inst: Air.Inst.Index, |
| ... | ... | @@ -28549,7 +28708,7 @@ fn tempFromOperand( |
| 28549 | 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 | } |
| 28554 | 28713 | |
| 28555 | 28714 | const temp_index = cg.next_temp_index; |
| ... | ... | @@ -29023,8 +29182,8 @@ const Select = struct { |
| 29023 | 29182 | return switch (spec.kind) { |
| 29024 | 29183 | .unused => null, |
| 29025 | 29184 | .any => try cg.tempAlloc(spec.type), |
| 29026 | | .cc => |cc| try cg.tempFromValue(spec.type, .{ .eflags = cc }), |
| 29027 | | .reg => |reg| try cg.tempFromValue(spec.type, .{ .register = reg }), |
| 29185 | .cc => |cc| try cg.tempInit(spec.type, .{ .eflags = cc }), |
| 29186 | .reg => |reg| try cg.tempInit(spec.type, .{ .register = reg }), |
| 29028 | 29187 | .rc => |rc| try cg.tempAllocReg(spec.type, regSetForRegClass(rc)), |
| 29029 | 29188 | .rc_mask => |rc_mask| try cg.tempAllocReg(spec.type, regSetForRegClass(rc_mask.rc)), |
| 29030 | 29189 | .mem => try cg.tempAllocMem(spec.type), |
| ... | ... | @@ -29081,18 +29240,14 @@ const Select = struct { |
| 29081 | 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: { |
| 29085 | | const vector_ty = try pt.vectorType(.{ |
| 29243 | const res_val: Value = if (vector_len) |len| .fromInterned(try pt.intern(.{ .aggregate = .{ |
| 29244 | .ty = (try pt.vectorType(.{ |
| 29086 | 29245 | .len = len, |
| 29087 | 29246 | .child = res_scalar_ty.toIntern(), |
| 29088 | | }); |
| 29089 | | const vector_val = try pt.intern(.{ .aggregate = .{ |
| 29090 | | .ty = vector_ty.toIntern(), |
| 29091 | | .storage = .{ .repeated_elem = res_scalar_val.toIntern() }, |
| 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)); |
| 29247 | })).toIntern(), |
| 29248 | .storage = .{ .repeated_elem = res_scalar_val.toIntern() }, |
| 29249 | } })) else res_scalar_val; |
| 29250 | return try cg.tempFromValue(res_val); |
| 29096 | 29251 | }, |
| 29097 | 29252 | .ref => |ref| ref.deref(s), |
| 29098 | 29253 | .ref_mask => |ref_mask| ref_mask.ref.deref(s), |