| ... | @@ -257,6 +257,7 @@ pub const MCValue = union(enum) { | ... | @@ -257,6 +257,7 @@ pub const MCValue = union(enum) { |
| 257 | }; | 257 | }; |
| 258 | } | 258 | } |
| 259 | | 259 | |
| | 260 | // hack around linker relocation bugs |
| 260 | fn isBase(mcv: MCValue) bool { | 261 | fn isBase(mcv: MCValue) bool { |
| 261 | return switch (mcv) { | 262 | return switch (mcv) { |
| 262 | .memory, .indirect, .load_frame => true, | 263 | .memory, .indirect, .load_frame => true, |
| ... | @@ -2398,8 +2399,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -2398,8 +2399,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2398 | .add_wrap, | 2399 | .add_wrap, |
| 2399 | .sub, | 2400 | .sub, |
| 2400 | .sub_wrap, | 2401 | .sub_wrap, |
| 2401 | .bool_and, | | |
| 2402 | .bool_or, | | |
| 2403 | .min, | 2402 | .min, |
| 2404 | .max, | 2403 | .max, |
| 2405 | => |air_tag| try cg.airBinOp(inst, air_tag), | 2404 | => |air_tag| try cg.airBinOp(inst, air_tag), |
| ... | @@ -2454,9 +2453,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -2454,9 +2453,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2454 | .is_null => try cg.airIsNull(inst), | 2453 | .is_null => try cg.airIsNull(inst), |
| 2455 | .is_non_err => try cg.airIsNonErr(inst), | 2454 | .is_non_err => try cg.airIsNonErr(inst), |
| 2456 | .is_err => try cg.airIsErr(inst), | 2455 | .is_err => try cg.airIsErr(inst), |
| 2457 | .load => try cg.airLoad(inst), | | |
| 2458 | .store => try cg.airStore(inst, false), | | |
| 2459 | .store_safe => try cg.airStore(inst, true), | | |
| 2460 | .float_from_int => try cg.airFloatFromInt(inst), | 2456 | .float_from_int => try cg.airFloatFromInt(inst), |
| 2461 | .int_from_float => try cg.airIntFromFloat(inst), | 2457 | .int_from_float => try cg.airIntFromFloat(inst), |
| 2462 | .cmpxchg_strong => try cg.airCmpxchg(inst), | 2458 | .cmpxchg_strong => try cg.airCmpxchg(inst), |
| ... | @@ -2791,14 +2787,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -2791,14 +2787,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2791 | try slot.moveTo(inst, cg); | 2787 | try slot.moveTo(inst, cg); |
| 2792 | }, | 2788 | }, |
| 2793 | .assembly => try cg.airAsm(inst), | 2789 | .assembly => try cg.airAsm(inst), |
| 2794 | .bit_and, .bit_or, .xor => |air_tag| if (use_old) try cg.airBinOp(inst, air_tag) else { | 2790 | .bit_and, .bit_or, .xor, .bool_and, .bool_or => |air_tag| if (use_old) try cg.airBinOp(inst, air_tag) else { |
| 2795 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; | 2791 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 2796 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); | 2792 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2797 | var res: [1]Temp = undefined; | 2793 | var res: [1]Temp = undefined; |
| 2798 | cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, switch (@as(Mir.Inst.Tag, switch (air_tag) { | 2794 | cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, switch (@as(Mir.Inst.Tag, switch (air_tag) { |
| 2799 | else => unreachable, | 2795 | else => unreachable, |
| 2800 | .bit_and => .@"and", | 2796 | .bit_and, .bool_and => .@"and", |
| 2801 | .bit_or => .@"or", | 2797 | .bit_or, .bool_or => .@"or", |
| 2802 | .xor => .xor, | 2798 | .xor => .xor, |
| 2803 | })) { | 2799 | })) { |
| 2804 | else => unreachable, | 2800 | else => unreachable, |
| ... | @@ -9601,6 +9597,25 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9601,6 +9597,25 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9601 | try ops[0].die(cg); | 9597 | try ops[0].die(cg); |
| 9602 | try is_non_err.moveTo(inst, cg); | 9598 | try is_non_err.moveTo(inst, cg); |
| 9603 | }, | 9599 | }, |
| | 9600 | .load => if (use_old) try cg.airLoad(inst) else fallback: { |
| | 9601 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| | 9602 | const val_ty = ty_op.ty.toType(); |
| | 9603 | const ptr_ty = cg.typeOf(ty_op.operand); |
| | 9604 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| | 9605 | if (ptr_info.packed_offset.host_size > 0 and |
| | 9606 | (ptr_info.flags.vector_index == .none or val_ty.toIntern() == .bool_type)) |
| | 9607 | break :fallback try cg.airLoad(inst); |
| | 9608 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| | 9609 | var res = try ops[0].load(val_ty, .{ |
| | 9610 | .disp = switch (ptr_info.flags.vector_index) { |
| | 9611 | .none => 0, |
| | 9612 | .runtime => unreachable, |
| | 9613 | else => |vector_index| @intCast(val_ty.abiSize(zcu) * @intFromEnum(vector_index)), |
| | 9614 | }, |
| | 9615 | }, cg); |
| | 9616 | for (ops) |op| if (op.index != res.index) try op.die(cg); |
| | 9617 | try res.moveTo(inst, cg); |
| | 9618 | }, |
| 9604 | .int_from_ptr => if (use_old) try cg.airIntFromPtr(inst) else { | 9619 | .int_from_ptr => if (use_old) try cg.airIntFromPtr(inst) else { |
| 9605 | const un_op = air_datas[@intFromEnum(inst)].un_op; | 9620 | const un_op = air_datas[@intFromEnum(inst)].un_op; |
| 9606 | var ops = try cg.tempsFromOperands(inst, .{un_op}); | 9621 | var ops = try cg.tempsFromOperands(inst, .{un_op}); |
| ... | @@ -9615,6 +9630,37 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9615,6 +9630,37 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9615 | .ret => try cg.airRet(inst, false), | 9630 | .ret => try cg.airRet(inst, false), |
| 9616 | .ret_safe => try cg.airRet(inst, true), | 9631 | .ret_safe => try cg.airRet(inst, true), |
| 9617 | .ret_load => try cg.airRetLoad(inst), | 9632 | .ret_load => try cg.airRetLoad(inst), |
| | 9633 | .store, .store_safe => |air_tag| if (use_old) try cg.airStore(inst, switch (air_tag) { |
| | 9634 | else => unreachable, |
| | 9635 | .store => false, |
| | 9636 | .store_safe => true, |
| | 9637 | }) else fallback: { |
| | 9638 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| | 9639 | const ptr_ty = cg.typeOf(bin_op.lhs); |
| | 9640 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| | 9641 | const val_ty = cg.typeOf(bin_op.rhs); |
| | 9642 | if (ptr_info.packed_offset.host_size > 0 and |
| | 9643 | (ptr_info.flags.vector_index == .none or val_ty.toIntern() == .bool_type)) |
| | 9644 | break :fallback try cg.airStore(inst, switch (air_tag) { |
| | 9645 | else => unreachable, |
| | 9646 | .store => false, |
| | 9647 | .store_safe => true, |
| | 9648 | }); |
| | 9649 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| | 9650 | try ops[0].store(&ops[1], .{ |
| | 9651 | .disp = switch (ptr_info.flags.vector_index) { |
| | 9652 | .none => 0, |
| | 9653 | .runtime => unreachable, |
| | 9654 | else => |vector_index| @intCast(val_ty.abiSize(zcu) * @intFromEnum(vector_index)), |
| | 9655 | }, |
| | 9656 | .safe = switch (air_tag) { |
| | 9657 | else => unreachable, |
| | 9658 | .store => false, |
| | 9659 | .store_safe => true, |
| | 9660 | }, |
| | 9661 | }, cg); |
| | 9662 | for (ops) |op| try op.die(cg); |
| | 9663 | }, |
| 9618 | .unreach => {}, | 9664 | .unreach => {}, |
| 9619 | .optional_payload_ptr => if (use_old) try cg.airOptionalPayloadPtr(inst) else { | 9665 | .optional_payload_ptr => if (use_old) try cg.airOptionalPayloadPtr(inst) else { |
| 9620 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; | 9666 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| ... | @@ -9630,7 +9676,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9630,7 +9676,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9630 | const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu)); | 9676 | const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu)); |
| 9631 | try ops[0].toOffset(opt_child_abi_size, cg); | 9677 | try ops[0].toOffset(opt_child_abi_size, cg); |
| 9632 | var has_value = try cg.tempInit(.bool, .{ .immediate = 1 }); | 9678 | var has_value = try cg.tempInit(.bool, .{ .immediate = 1 }); |
| 9633 | try ops[0].store(0, &has_value, cg); | 9679 | try ops[0].store(&has_value, .{}, cg); |
| 9634 | try has_value.die(cg); | 9680 | try has_value.die(cg); |
| 9635 | try ops[0].toOffset(-opt_child_abi_size, cg); | 9681 | try ops[0].toOffset(-opt_child_abi_size, cg); |
| 9636 | } | 9682 | } |
| ... | @@ -9652,7 +9698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9652,7 +9698,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9652 | const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu)); | 9698 | const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu)); |
| 9653 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | 9699 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9654 | try ops[0].toOffset(eu_err_off, cg); | 9700 | try ops[0].toOffset(eu_err_off, cg); |
| 9655 | var err = try ops[0].load(0, eu_ty.errorUnionSet(zcu), cg); | 9701 | var err = try ops[0].load(eu_ty.errorUnionSet(zcu), .{}, cg); |
| 9656 | try ops[0].die(cg); | 9702 | try ops[0].die(cg); |
| 9657 | try err.moveTo(inst, cg); | 9703 | try err.moveTo(inst, cg); |
| 9658 | }, | 9704 | }, |
| ... | @@ -9666,7 +9712,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9666,7 +9712,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9666 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | 9712 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9667 | try ops[0].toOffset(eu_err_off, cg); | 9713 | try ops[0].toOffset(eu_err_off, cg); |
| 9668 | var no_err = try cg.tempInit(eu_err_ty, .{ .immediate = 0 }); | 9714 | var no_err = try cg.tempInit(eu_err_ty, .{ .immediate = 0 }); |
| 9669 | try ops[0].store(0, &no_err, cg); | 9715 | try ops[0].store(&no_err, .{}, cg); |
| 9670 | try no_err.die(cg); | 9716 | try no_err.die(cg); |
| 9671 | try ops[0].toOffset(eu_pl_off - eu_err_off, cg); | 9717 | try ops[0].toOffset(eu_pl_off - eu_err_off, cg); |
| 9672 | try ops[0].moveTo(inst, cg); | 9718 | try ops[0].moveTo(inst, cg); |
| ... | @@ -9682,43 +9728,29 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9682,43 +9728,29 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9682 | ), cg); | 9728 | ), cg); |
| 9683 | try ops[0].moveTo(inst, cg); | 9729 | try ops[0].moveTo(inst, cg); |
| 9684 | }, | 9730 | }, |
| 9685 | .struct_field_ptr_index_0 => if (use_old) try cg.airStructFieldPtrIndex(inst, 0) else { | 9731 | .struct_field_ptr_index_0, |
| 9686 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; | 9732 | .struct_field_ptr_index_1, |
| 9687 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | 9733 | .struct_field_ptr_index_2, |
| 9688 | try ops[0].toOffset(cg.fieldOffset( | 9734 | .struct_field_ptr_index_3, |
| 9689 | cg.typeOf(ty_op.operand), | 9735 | => |air_tag| if (use_old) try cg.airStructFieldPtrIndex(inst, switch (air_tag) { |
| 9690 | ty_op.ty.toType(), | 9736 | else => unreachable, |
| 9691 | 0, | 9737 | .struct_field_ptr_index_0 => 0, |
| 9692 | ), cg); | 9738 | .struct_field_ptr_index_1 => 1, |
| 9693 | try ops[0].moveTo(inst, cg); | 9739 | .struct_field_ptr_index_2 => 2, |
| 9694 | }, | 9740 | .struct_field_ptr_index_3 => 3, |
| 9695 | .struct_field_ptr_index_1 => if (use_old) try cg.airStructFieldPtrIndex(inst, 1) else { | 9741 | }) else { |
| 9696 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; | | |
| 9697 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | | |
| 9698 | try ops[0].toOffset(cg.fieldOffset( | | |
| 9699 | cg.typeOf(ty_op.operand), | | |
| 9700 | ty_op.ty.toType(), | | |
| 9701 | 1, | | |
| 9702 | ), cg); | | |
| 9703 | try ops[0].moveTo(inst, cg); | | |
| 9704 | }, | | |
| 9705 | .struct_field_ptr_index_2 => if (use_old) try cg.airStructFieldPtrIndex(inst, 2) else { | | |
| 9706 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; | | |
| 9707 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | | |
| 9708 | try ops[0].toOffset(cg.fieldOffset( | | |
| 9709 | cg.typeOf(ty_op.operand), | | |
| 9710 | ty_op.ty.toType(), | | |
| 9711 | 2, | | |
| 9712 | ), cg); | | |
| 9713 | try ops[0].moveTo(inst, cg); | | |
| 9714 | }, | | |
| 9715 | .struct_field_ptr_index_3 => if (use_old) try cg.airStructFieldPtrIndex(inst, 3) else { | | |
| 9716 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; | 9742 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 9717 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | 9743 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9718 | try ops[0].toOffset(cg.fieldOffset( | 9744 | try ops[0].toOffset(cg.fieldOffset( |
| 9719 | cg.typeOf(ty_op.operand), | 9745 | cg.typeOf(ty_op.operand), |
| 9720 | ty_op.ty.toType(), | 9746 | ty_op.ty.toType(), |
| 9721 | 3, | 9747 | switch (air_tag) { |
| | 9748 | else => unreachable, |
| | 9749 | .struct_field_ptr_index_0 => 0, |
| | 9750 | .struct_field_ptr_index_1 => 1, |
| | 9751 | .struct_field_ptr_index_2 => 2, |
| | 9752 | .struct_field_ptr_index_3 => 3, |
| | 9753 | }, |
| 9722 | ), cg); | 9754 | ), cg); |
| 9723 | try ops[0].moveTo(inst, cg); | 9755 | try ops[0].moveTo(inst, cg); |
| 9724 | }, | 9756 | }, |
| ... | @@ -9733,7 +9765,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9733,7 +9765,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9733 | }; | 9765 | }; |
| 9734 | if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 9766 | if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 9735 | var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand}); | 9767 | var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand}); |
| 9736 | var res = try ops[0].read(field_off, field_ty, cg); | 9768 | var res = try ops[0].read(field_ty, .{ .disp = field_off }, cg); |
| 9737 | for (ops) |op| if (op.index != res.index) try op.die(cg); | 9769 | for (ops) |op| if (op.index != res.index) try op.die(cg); |
| 9738 | try res.moveTo(inst, cg); | 9770 | try res.moveTo(inst, cg); |
| 9739 | } else { | 9771 | } else { |
| ... | @@ -9748,7 +9780,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9748,7 +9780,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9748 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); | 9780 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9749 | const union_layout = union_ty.unionGetLayout(zcu); | 9781 | const union_layout = union_ty.unionGetLayout(zcu); |
| 9750 | // hack around Sema OPV bugs | 9782 | // hack around Sema OPV bugs |
| 9751 | if (union_layout.tag_size > 0) try ops[0].store(@intCast(union_layout.tagOffset()), &ops[1], cg); | 9783 | if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{ |
| | 9784 | .disp = @intCast(union_layout.tagOffset()), |
| | 9785 | }, cg); |
| 9752 | for (ops) |op| try op.die(cg); | 9786 | for (ops) |op| try op.die(cg); |
| 9753 | }, | 9787 | }, |
| 9754 | .get_union_tag => if (use_old) try cg.airGetUnionTag(inst) else { | 9788 | .get_union_tag => if (use_old) try cg.airGetUnionTag(inst) else { |
| ... | @@ -9757,7 +9791,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9757,7 +9791,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9757 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); | 9791 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 9758 | const union_layout = union_ty.unionGetLayout(zcu); | 9792 | const union_layout = union_ty.unionGetLayout(zcu); |
| 9759 | assert(union_layout.tag_size > 0); | 9793 | assert(union_layout.tag_size > 0); |
| 9760 | var res = try ops[0].read(@intCast(union_layout.tagOffset()), ty_op.ty.toType(), cg); | 9794 | var res = try ops[0].read(ty_op.ty.toType(), .{ |
| | 9795 | .disp = @intCast(union_layout.tagOffset()), |
| | 9796 | }, cg); |
| 9761 | for (ops) |op| if (op.index != res.index) try op.die(cg); | 9797 | for (ops) |op| if (op.index != res.index) try op.die(cg); |
| 9762 | try res.moveTo(inst, cg); | 9798 | try res.moveTo(inst, cg); |
| 9763 | }, | 9799 | }, |
| ... | @@ -9916,7 +9952,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9916,7 +9952,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9916 | .scale = .fromFactor(@intCast(elem_size)), | 9952 | .scale = .fromFactor(@intCast(elem_size)), |
| 9917 | } }, | 9953 | } }, |
| 9918 | }); | 9954 | }); |
| 9919 | res[0] = try ops[0].load(0, res_ty, cg); | 9955 | res[0] = try ops[0].load(res_ty, .{}, cg); |
| 9920 | }, | 9956 | }, |
| 9921 | }, | 9957 | }, |
| 9922 | else => |e| return e, | 9958 | else => |e| return e, |
| ... | @@ -10002,10 +10038,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -10002,10 +10038,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 10002 | union_ty.unionTagTypeSafety(zcu).?, | 10038 | union_ty.unionTagTypeSafety(zcu).?, |
| 10003 | extra.field_index, | 10039 | extra.field_index, |
| 10004 | )); | 10040 | )); |
| 10005 | try res.write(@intCast(union_layout.tagOffset()), &tag_temp, cg); | 10041 | try res.write(&tag_temp, .{ |
| | 10042 | .disp = @intCast(union_layout.tagOffset()), |
| | 10043 | }, cg); |
| 10006 | try tag_temp.die(cg); | 10044 | try tag_temp.die(cg); |
| 10007 | } | 10045 | } |
| 10008 | try res.write(@intCast(union_layout.payloadOffset()), &ops[0], cg); | 10046 | try res.write(&ops[0], .{ |
| | 10047 | .disp = @intCast(union_layout.payloadOffset()), |
| | 10048 | }, cg); |
| 10009 | try ops[0].die(cg); | 10049 | try ops[0].die(cg); |
| 10010 | try res.moveTo(inst, cg); | 10050 | try res.moveTo(inst, cg); |
| 10011 | }, | 10051 | }, |
| ... | @@ -28338,6 +28378,7 @@ const Temp = struct { | ... | @@ -28338,6 +28378,7 @@ const Temp = struct { |
| 28338 | return true; | 28378 | return true; |
| 28339 | } | 28379 | } |
| 28340 | | 28380 | |
| | 28381 | // hack around linker relocation bugs |
| 28341 | fn toBase(temp: *Temp, cg: *CodeGen) !bool { | 28382 | fn toBase(temp: *Temp, cg: *CodeGen) !bool { |
| 28342 | const temp_tracking = temp.tracking(cg); | 28383 | const temp_tracking = temp.tracking(cg); |
| 28343 | if (temp_tracking.short.isBase()) return false; | 28384 | if (temp_tracking.short.isBase()) return false; |
| ... | @@ -28354,17 +28395,38 @@ const Temp = struct { | ... | @@ -28354,17 +28395,38 @@ const Temp = struct { |
| 28354 | return true; | 28395 | return true; |
| 28355 | } | 28396 | } |
| 28356 | | 28397 | |
| 28357 | fn load(ptr: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp { | 28398 | const AccessOptions = struct { |
| | 28399 | disp: i32 = 0, |
| | 28400 | safe: bool = false, |
| | 28401 | }; |
| | 28402 | |
| | 28403 | fn load(ptr: *Temp, val_ty: Type, opts: AccessOptions, cg: *CodeGen) !Temp { |
| 28358 | const val = try cg.tempAlloc(val_ty); | 28404 | const val = try cg.tempAlloc(val_ty); |
| | 28405 | try ptr.toOffset(opts.disp, cg); |
| | 28406 | while (try ptr.toLea(cg)) {} |
| 28359 | const val_mcv = val.tracking(cg).short; | 28407 | const val_mcv = val.tracking(cg).short; |
| 28360 | switch (val_mcv) { | 28408 | switch (val_mcv) { |
| 28361 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), | 28409 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28362 | .register => |val_reg| { | 28410 | .register => |val_reg| try ptr.loadReg(val_ty, registerAlias( |
| | 28411 | val_reg, |
| | 28412 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| | 28413 | ), cg), |
| | 28414 | inline .register_pair, |
| | 28415 | .register_triple, |
| | 28416 | .register_quadruple, |
| | 28417 | => |val_regs| for (val_regs) |val_reg| { |
| | 28418 | try ptr.loadReg(val_ty, val_reg, cg); |
| | 28419 | try ptr.toOffset(@divExact(val_reg.bitSize(), 8), cg); |
| 28363 | while (try ptr.toLea(cg)) {} | 28420 | while (try ptr.toLea(cg)) {} |
| 28364 | try cg.genSetReg(val_reg, val_ty, ptr.tracking(cg).short.offset(disp).deref(), .{}); | 28421 | }, |
| | 28422 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| | 28423 | 0 => try ptr.loadReg(val_ty, registerAlias( |
| | 28424 | val_reg_off.reg, |
| | 28425 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| | 28426 | ), cg), |
| | 28427 | else => unreachable, |
| 28365 | }, | 28428 | }, |
| 28366 | .memory, .indirect, .load_frame, .load_symbol => { | 28429 | .memory, .indirect, .load_frame, .load_symbol => { |
| 28367 | try ptr.toOffset(disp, cg); | | |
| 28368 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); | 28430 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); |
| 28369 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); | 28431 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28370 | try val_ptr.memcpy(ptr, &len, cg); | 28432 | try val_ptr.memcpy(ptr, &len, cg); |
| ... | @@ -28375,103 +28437,158 @@ const Temp = struct { | ... | @@ -28375,103 +28437,158 @@ const Temp = struct { |
| 28375 | return val; | 28437 | return val; |
| 28376 | } | 28438 | } |
| 28377 | | 28439 | |
| 28378 | fn store(ptr: *Temp, disp: i32, val: *Temp, cg: *CodeGen) !void { | 28440 | fn store(ptr: *Temp, val: *Temp, opts: AccessOptions, cg: *CodeGen) !void { |
| 28379 | const val_ty = val.typeOf(cg); | 28441 | const val_ty = val.typeOf(cg); |
| 28380 | val: switch (val.tracking(cg).short) { | 28442 | try ptr.toOffset(opts.disp, cg); |
| 28381 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), | 28443 | while (try ptr.toLea(cg)) {} |
| 28382 | .immediate => |val_imm| { | 28444 | val_to_gpr: while (true) : (while (try ptr.toLea(cg) or |
| 28383 | const val_op: Immediate = if (std.math.cast(u32, val_imm)) |val_uimm32| | 28445 | try val.toRegClass(false, .general_purpose, cg)) |
| 28384 | .u(val_uimm32) | 28446 | {}) { |
| 28385 | else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32| | 28447 | const val_mcv = val.tracking(cg).short; |
| 28386 | .s(val_simm32) | 28448 | switch (val_mcv) { |
| 28387 | else | 28449 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28388 | continue :val .{ .register = undefined }; | 28450 | .undef => if (opts.safe) { |
| 28389 | while (try ptr.toLea(cg)) {} | 28451 | var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa }); |
| 28390 | try cg.asmMemoryImmediate( | 28452 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28391 | .{ ._, .mov }, | 28453 | try ptr.memset(&pat, &len, cg); |
| 28392 | try ptr.tracking(cg).short.deref().mem(cg, .{ | 28454 | try pat.die(cg); |
| 28393 | .size = cg.memSize(val_ty), | 28455 | try len.die(cg); |
| 28394 | .disp = disp, | 28456 | }, |
| 28395 | }), | 28457 | .immediate => |val_imm| { |
| 28396 | val_op, | 28458 | const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31| |
| 28397 | ); | 28459 | .u(val_uimm31) |
| 28398 | }, | 28460 | else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32| |
| 28399 | .register => { | 28461 | .s(val_simm32) |
| 28400 | while (try ptr.toLea(cg) or try val.toRegClass(true, .general_purpose, cg)) {} | 28462 | else |
| 28401 | const val_reg = val.tracking(cg).short.register; | 28463 | continue :val_to_gpr; |
| 28402 | switch (val_reg.class()) { | 28464 | // hack around linker relocation bugs |
| 28403 | .general_purpose => try cg.asmMemoryRegister( | 28465 | switch (ptr.tracking(cg).short) { |
| | 28466 | else => {}, |
| | 28467 | .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| | 28468 | } |
| | 28469 | try cg.asmMemoryImmediate( |
| 28404 | .{ ._, .mov }, | 28470 | .{ ._, .mov }, |
| 28405 | try ptr.tracking(cg).short.deref().mem(cg, .{ | 28471 | try ptr.tracking(cg).short.deref().mem(cg, .{ |
| 28406 | .size = cg.memSize(val_ty), | 28472 | .size = cg.memSize(val_ty), |
| 28407 | .disp = disp, | | |
| 28408 | }), | 28473 | }), |
| 28409 | registerAlias(val_reg, @intCast(val_ty.abiSize(cg.pt.zcu))), | 28474 | val_op, |
| 28410 | ), | 28475 | ); |
| 28411 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), | 28476 | }, |
| 28412 | } | 28477 | .eflags => |cc| { |
| 28413 | }, | 28478 | // hack around linker relocation bugs |
| 28414 | } | 28479 | switch (ptr.tracking(cg).short) { |
| 28415 | } | 28480 | else => {}, |
| 28416 | | 28481 | .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| 28417 | fn read(src: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp { | 28482 | } |
| 28418 | var val = try cg.tempAlloc(val_ty); | 28483 | try cg.asmSetccMemory( |
| 28419 | while (try src.toBase(cg)) {} | 28484 | cc, |
| 28420 | val_to_gpr: while (true) : (while (try val.toRegClass(false, .general_purpose, cg)) {}) { | 28485 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }), |
| 28421 | const val_mcv = val.tracking(cg).short; | 28486 | ); |
| 28422 | switch (val_mcv) { | 28487 | }, |
| 28423 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), | 28488 | .register => |val_reg| try ptr.storeReg(val_ty, registerAlias( |
| 28424 | .register => |val_reg| try src.readReg(disp, val_ty, registerAlias( | | |
| 28425 | val_reg, | 28489 | val_reg, |
| 28426 | @intCast(val_ty.abiSize(cg.pt.zcu)), | 28490 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28427 | ), cg), | 28491 | ), cg), |
| 28428 | inline .register_pair, .register_triple, .register_quadruple => |val_regs| { | 28492 | inline .register_pair, |
| 28429 | var part_disp = disp; | 28493 | .register_triple, |
| 28430 | for (val_regs) |val_reg| { | 28494 | .register_quadruple, |
| 28431 | try src.readReg(disp, val_ty, val_reg, cg); | 28495 | => |val_regs| for (val_regs) |val_reg| { |
| 28432 | part_disp += @divExact(val_reg.bitSize(), 8); | 28496 | try ptr.storeReg(val_ty, val_reg, cg); |
| 28433 | } | 28497 | try ptr.toOffset(@divExact(val_reg.bitSize(), 8), cg); |
| | 28498 | while (try ptr.toLea(cg)) {} |
| 28434 | }, | 28499 | }, |
| 28435 | .register_offset => |val_reg_off| switch (val_reg_off.off) { | 28500 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| 28436 | 0 => try src.readReg(disp, val_ty, registerAlias( | 28501 | 0 => try ptr.storeReg(val_ty, registerAlias( |
| 28437 | val_reg_off.reg, | 28502 | val_reg_off.reg, |
| 28438 | @intCast(val_ty.abiSize(cg.pt.zcu)), | 28503 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28439 | ), cg), | 28504 | ), cg), |
| 28440 | else => continue :val_to_gpr, | 28505 | else => continue :val_to_gpr, |
| 28441 | }, | 28506 | }, |
| | 28507 | .register_overflow => |val_reg_ov| { |
| | 28508 | const ip = &cg.pt.zcu.intern_pool; |
| | 28509 | const first_ty: Type = .fromInterned(first_ty: switch (ip.indexToKey(val_ty.toIntern())) { |
| | 28510 | .tuple_type => |tuple_type| { |
| | 28511 | const tuple_field_types = tuple_type.types.get(ip); |
| | 28512 | assert(tuple_field_types.len == 2 and tuple_field_types[1] == .u1_type); |
| | 28513 | break :first_ty tuple_field_types[0]; |
| | 28514 | }, |
| | 28515 | .opt_type => |opt_child| { |
| | 28516 | assert(!val_ty.optionalReprIsPayload(cg.pt.zcu)); |
| | 28517 | break :first_ty opt_child; |
| | 28518 | }, |
| | 28519 | else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }), |
| | 28520 | }); |
| | 28521 | const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu)); |
| | 28522 | try ptr.storeReg(first_ty, registerAlias(val_reg_ov.reg, first_size), cg); |
| | 28523 | try ptr.toOffset(first_size, cg); |
| | 28524 | try cg.asmSetccMemory( |
| | 28525 | val_reg_ov.eflags, |
| | 28526 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }), |
| | 28527 | ); |
| | 28528 | }, |
| 28442 | .lea_frame, .lea_symbol => continue :val_to_gpr, | 28529 | .lea_frame, .lea_symbol => continue :val_to_gpr, |
| 28443 | .memory, .indirect, .load_frame, .load_symbol => { | 28530 | .memory, .indirect, .load_frame, .load_symbol => { |
| 28444 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); | 28531 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); |
| 28445 | var src_ptr = try cg.tempInit(.usize, src.tracking(cg).short.address().offset(disp)); | | |
| 28446 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); | 28532 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28447 | try val_ptr.memcpy(&src_ptr, &len, cg); | 28533 | try ptr.memcpy(&val_ptr, &len, cg); |
| 28448 | try val_ptr.die(cg); | 28534 | try val_ptr.die(cg); |
| 28449 | try src_ptr.die(cg); | | |
| 28450 | try len.die(cg); | 28535 | try len.die(cg); |
| 28451 | }, | 28536 | }, |
| 28452 | } | 28537 | } |
| 28453 | return val; | 28538 | break; |
| 28454 | } | 28539 | } |
| 28455 | } | 28540 | } |
| 28456 | | 28541 | |
| 28457 | fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void { | 28542 | fn read(src: *Temp, val_ty: Type, opts: AccessOptions, cg: *CodeGen) !Temp { |
| 28458 | const strat = try cg.moveStrategy(dst_ty, dst_reg.class(), false); | 28543 | var val = try cg.tempAlloc(val_ty); |
| 28459 | try strat.read(cg, dst_reg, try src.tracking(cg).short.mem(cg, .{ | 28544 | while (try src.toBase(cg)) {} |
| 28460 | .size = .fromBitSize(@min(8 * dst_ty.abiSize(cg.pt.zcu), dst_reg.bitSize())), | 28545 | const val_mcv = val.tracking(cg).short; |
| 28461 | .disp = disp, | 28546 | switch (val_mcv) { |
| 28462 | })); | 28547 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| | 28548 | .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias( |
| | 28549 | val_reg, |
| | 28550 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| | 28551 | ), cg), |
| | 28552 | inline .register_pair, .register_triple, .register_quadruple => |val_regs| { |
| | 28553 | var disp = opts.disp; |
| | 28554 | for (val_regs) |val_reg| { |
| | 28555 | try src.readReg(disp, val_ty, val_reg, cg); |
| | 28556 | disp += @divExact(val_reg.bitSize(), 8); |
| | 28557 | } |
| | 28558 | }, |
| | 28559 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| | 28560 | 0 => try src.readReg(opts.disp, val_ty, registerAlias( |
| | 28561 | val_reg_off.reg, |
| | 28562 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| | 28563 | ), cg), |
| | 28564 | else => unreachable, |
| | 28565 | }, |
| | 28566 | .memory, .indirect, .load_frame, .load_symbol => { |
| | 28567 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); |
| | 28568 | var src_ptr = |
| | 28569 | try cg.tempInit(.usize, src.tracking(cg).short.address().offset(opts.disp)); |
| | 28570 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| | 28571 | try val_ptr.memcpy(&src_ptr, &len, cg); |
| | 28572 | try val_ptr.die(cg); |
| | 28573 | try src_ptr.die(cg); |
| | 28574 | try len.die(cg); |
| | 28575 | }, |
| | 28576 | } |
| | 28577 | return val; |
| 28463 | } | 28578 | } |
| 28464 | | 28579 | |
| 28465 | fn write(dst: *Temp, disp: i32, val: *Temp, cg: *CodeGen) !void { | 28580 | fn write(dst: *Temp, val: *Temp, opts: AccessOptions, cg: *CodeGen) !void { |
| 28466 | const val_ty = val.typeOf(cg); | 28581 | const val_ty = val.typeOf(cg); |
| 28467 | while (try dst.toBase(cg)) {} | 28582 | while (try dst.toBase(cg)) {} |
| 28468 | val_to_gpr: while (true) : (while (try val.toRegClass(false, .general_purpose, cg)) {}) { | 28583 | val_to_gpr: while (true) : (while (try dst.toBase(cg) or |
| | 28584 | try val.toRegClass(false, .general_purpose, cg)) |
| | 28585 | {}) { |
| 28469 | const val_mcv = val.tracking(cg).short; | 28586 | const val_mcv = val.tracking(cg).short; |
| 28470 | switch (val_mcv) { | 28587 | switch (val_mcv) { |
| 28471 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), | 28588 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28472 | .immediate => |val_imm| { | 28589 | .immediate => |val_imm| { |
| 28473 | const val_op: Immediate = if (std.math.cast(u32, val_imm)) |val_uimm32| | 28590 | const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31| |
| 28474 | .u(val_uimm32) | 28591 | .u(val_uimm31) |
| 28475 | else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32| | 28592 | else if (std.math.cast(i32, @as(i64, @bitCast(val_imm)))) |val_simm32| |
| 28476 | .s(val_simm32) | 28593 | .s(val_simm32) |
| 28477 | else | 28594 | else |
| ... | @@ -28480,24 +28597,24 @@ const Temp = struct { | ... | @@ -28480,24 +28597,24 @@ const Temp = struct { |
| 28480 | .{ ._, .mov }, | 28597 | .{ ._, .mov }, |
| 28481 | try dst.tracking(cg).short.mem(cg, .{ | 28598 | try dst.tracking(cg).short.mem(cg, .{ |
| 28482 | .size = cg.memSize(val_ty), | 28599 | .size = cg.memSize(val_ty), |
| 28483 | .disp = disp, | 28600 | .disp = opts.disp, |
| 28484 | }), | 28601 | }), |
| 28485 | val_op, | 28602 | val_op, |
| 28486 | ); | 28603 | ); |
| 28487 | }, | 28604 | }, |
| 28488 | .register => |val_reg| try dst.writeReg(disp, val_ty, registerAlias( | 28605 | .register => |val_reg| try dst.writeReg(opts.disp, val_ty, registerAlias( |
| 28489 | val_reg, | 28606 | val_reg, |
| 28490 | @intCast(val_ty.abiSize(cg.pt.zcu)), | 28607 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28491 | ), cg), | 28608 | ), cg), |
| 28492 | inline .register_pair, .register_triple, .register_quadruple => |val_regs| { | 28609 | inline .register_pair, .register_triple, .register_quadruple => |val_regs| { |
| 28493 | var part_disp = disp; | 28610 | var disp = opts.disp; |
| 28494 | for (val_regs) |val_reg| { | 28611 | for (val_regs) |val_reg| { |
| 28495 | try dst.writeReg(part_disp, val_ty, val_reg, cg); | 28612 | try dst.writeReg(disp, val_ty, val_reg, cg); |
| 28496 | part_disp += @divExact(val_reg.bitSize(), 8); | 28613 | disp += @divExact(val_reg.bitSize(), 8); |
| 28497 | } | 28614 | } |
| 28498 | }, | 28615 | }, |
| 28499 | .register_offset => |val_reg_off| switch (val_reg_off.off) { | 28616 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| 28500 | 0 => try dst.writeReg(disp, val_ty, registerAlias( | 28617 | 0 => try dst.writeReg(opts.disp, val_ty, registerAlias( |
| 28501 | val_reg_off.reg, | 28618 | val_reg_off.reg, |
| 28502 | @intCast(val_ty.abiSize(cg.pt.zcu)), | 28619 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28503 | ), cg), | 28620 | ), cg), |
| ... | @@ -28505,7 +28622,8 @@ const Temp = struct { | ... | @@ -28505,7 +28622,8 @@ const Temp = struct { |
| 28505 | }, | 28622 | }, |
| 28506 | .lea_frame, .lea_symbol => continue :val_to_gpr, | 28623 | .lea_frame, .lea_symbol => continue :val_to_gpr, |
| 28507 | .memory, .indirect, .load_frame, .load_symbol => { | 28624 | .memory, .indirect, .load_frame, .load_symbol => { |
| 28508 | var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(disp)); | 28625 | var dst_ptr = |
| | 28626 | try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp)); |
| 28509 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); | 28627 | var val_ptr = try cg.tempInit(.usize, val_mcv.address()); |
| 28510 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); | 28628 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28511 | try dst_ptr.memcpy(&val_ptr, &len, cg); | 28629 | try dst_ptr.memcpy(&val_ptr, &len, cg); |
| ... | @@ -28514,10 +28632,62 @@ const Temp = struct { | ... | @@ -28514,10 +28632,62 @@ const Temp = struct { |
| 28514 | try len.die(cg); | 28632 | try len.die(cg); |
| 28515 | }, | 28633 | }, |
| 28516 | } | 28634 | } |
| 28517 | return; | 28635 | break; |
| | 28636 | } |
| | 28637 | } |
| | 28638 | |
| | 28639 | fn loadReg(ptr: *Temp, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void { |
| | 28640 | const dst_rc = dst_reg.class(); |
| | 28641 | const strat = try cg.moveStrategy(dst_ty, dst_rc, false); |
| | 28642 | // hack around linker relocation bugs |
| | 28643 | switch (ptr.tracking(cg).short) { |
| | 28644 | else => {}, |
| | 28645 | .lea_symbol => |sym_off| if (dst_rc != .general_purpose or sym_off.off != 0) |
| | 28646 | while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| | 28647 | } |
| | 28648 | try strat.read(cg, dst_reg, try ptr.tracking(cg).short.deref().mem(cg, .{ |
| | 28649 | .size = .fromBitSize(@min(8 * dst_ty.abiSize(cg.pt.zcu), dst_reg.bitSize())), |
| | 28650 | })); |
| | 28651 | } |
| | 28652 | |
| | 28653 | fn storeReg(ptr: *Temp, src_ty: Type, src_reg: Register, cg: *CodeGen) !void { |
| | 28654 | const src_rc = src_reg.class(); |
| | 28655 | const src_abi_size = src_ty.abiSize(cg.pt.zcu); |
| | 28656 | const strat = try cg.moveStrategy(src_ty, src_rc, false); |
| | 28657 | // hack around linker relocation bugs |
| | 28658 | switch (ptr.tracking(cg).short) { |
| | 28659 | else => {}, |
| | 28660 | .lea_symbol => |sym_off| if (src_rc != .general_purpose or sym_off.off != 0) |
| | 28661 | while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| | 28662 | } |
| | 28663 | if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) { |
| | 28664 | try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{ |
| | 28665 | .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())), |
| | 28666 | }), src_reg); |
| | 28667 | } else { |
| | 28668 | const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu); |
| | 28669 | const frame_index = try cg.allocFrameIndex(frame_alloc); |
| | 28670 | const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size); |
| | 28671 | try strat.write(cg, .{ |
| | 28672 | .base = .{ .frame = frame_index }, |
| | 28673 | .mod = .{ .rm = .{ .size = frame_size } }, |
| | 28674 | }, src_reg); |
| | 28675 | var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } }); |
| | 28676 | var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size }); |
| | 28677 | try ptr.memcpy(&src_ptr, &len, cg); |
| | 28678 | try src_ptr.die(cg); |
| | 28679 | try len.die(cg); |
| 28518 | } | 28680 | } |
| 28519 | } | 28681 | } |
| 28520 | | 28682 | |
| | 28683 | fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void { |
| | 28684 | const strat = try cg.moveStrategy(dst_ty, dst_reg.class(), false); |
| | 28685 | try strat.read(cg, dst_reg, try src.tracking(cg).short.mem(cg, .{ |
| | 28686 | .size = .fromBitSize(@min(8 * dst_ty.abiSize(cg.pt.zcu), dst_reg.bitSize())), |
| | 28687 | .disp = disp, |
| | 28688 | })); |
| | 28689 | } |
| | 28690 | |
| 28521 | fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) !void { | 28691 | fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) !void { |
| 28522 | const src_rc = src_reg.class(); | 28692 | const src_rc = src_reg.class(); |
| 28523 | const src_abi_size = src_ty.abiSize(cg.pt.zcu); | 28693 | const src_abi_size = src_ty.abiSize(cg.pt.zcu); |
| ... | @@ -28552,6 +28722,13 @@ const Temp = struct { | ... | @@ -28552,6 +28722,13 @@ const Temp = struct { |
| 28552 | try cg.asmOpOnly(.{ .@"rep _sb", .mov }); | 28722 | try cg.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 28553 | } | 28723 | } |
| 28554 | | 28724 | |
| | 28725 | fn memset(dst: *Temp, val: *Temp, len: *Temp, cg: *CodeGen) !void { |
| | 28726 | while (true) for ([_]*Temp{ dst, val, len }, [_]Register{ .rdi, .rax, .rcx }) |temp, reg| { |
| | 28727 | if (try temp.toReg(reg, cg)) break; |
| | 28728 | } else break; |
| | 28729 | try cg.asmOpOnly(.{ .@"rep _sb", .sto }); |
| | 28730 | } |
| | 28731 | |
| 28555 | fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void { | 28732 | fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void { |
| 28556 | if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) { | 28733 | if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) { |
| 28557 | .ref => { | 28734 | .ref => { |