| author | |
| committer | |
| log | dc1f50e505105cabe1ed53951ca612778d6019ee |
| tree | b0d91b810a6643028fc088d0af849b29dfeee632 |
| parent | a933a59ced8175a513ff123c3496b1b563d58453 |
| parent | 0aee40bd13fa72ac4ca41e133440917c0ed94ffb |
| signature |
Bitcast fixes for self-hosted native backends9 files changed, 137 insertions(+), 24 deletions(-)
src/arch/aarch64/CodeGen.zig+19-2| ... | @@ -3958,7 +3958,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3958,7 +3958,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3958 | 3958 | ||
| 3959 | switch (value) { | 3959 | switch (value) { |
| 3960 | .dead => unreachable, | 3960 | .dead => unreachable, |
| 3961 | .undef => unreachable, | 3961 | .undef => { |
| 3962 | try self.genSetReg(value_ty, addr_reg, value); | ||
| 3963 | }, | ||
| 3962 | .register => |value_reg| { | 3964 | .register => |value_reg| { |
| 3963 | log.debug("store: register {} to {}", .{ value_reg, addr_reg }); | 3965 | log.debug("store: register {} to {}", .{ value_reg, addr_reg }); |
| 3964 | try self.genStrRegister(value_reg, addr_reg, value_ty); | 3966 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| ... | @@ -5870,7 +5872,22 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5870,7 +5872,22 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 5870 | 5872 | ||
| 5871 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 5873 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 5872 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5874 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5873 | const result = try self.resolveInst(ty_op.operand); | 5875 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 5876 | const operand = try self.resolveInst(ty_op.operand); | ||
| 5877 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand; | ||
| 5878 | |||
| 5879 | const operand_lock = switch (operand) { | ||
| 5880 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 5881 | .register_with_overflow => |rwo| self.register_manager.lockReg(rwo.reg), | ||
| 5882 | else => null, | ||
| 5883 | }; | ||
| 5884 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 5885 | |||
| 5886 | const dest_ty = self.air.typeOfIndex(inst); | ||
| 5887 | const dest = try self.allocRegOrMem(dest_ty, true, inst); | ||
| 5888 | try self.setRegOrMem(dest_ty, dest, operand); | ||
| 5889 | break :result dest; | ||
| 5890 | }; | ||
| 5874 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 5891 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5875 | } | 5892 | } |
| 5876 | 5893 |
src/arch/arm/CodeGen.zig+21-2| ... | @@ -2765,7 +2765,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2765,7 +2765,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2765 | 2765 | ||
| 2766 | switch (value) { | 2766 | switch (value) { |
| 2767 | .dead => unreachable, | 2767 | .dead => unreachable, |
| 2768 | .undef => unreachable, | 2768 | .undef => { |
| 2769 | try self.genSetReg(value_ty, addr_reg, value); | ||
| 2770 | }, | ||
| 2769 | .register => |value_reg| { | 2771 | .register => |value_reg| { |
| 2770 | try self.genStrRegister(value_reg, addr_reg, value_ty); | 2772 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 2771 | }, | 2773 | }, |
| ... | @@ -5816,7 +5818,24 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5816,7 +5818,24 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 5816 | 5818 | ||
| 5817 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 5819 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 5818 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5820 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5819 | const result = try self.resolveInst(ty_op.operand); | 5821 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 5822 | const operand = try self.resolveInst(ty_op.operand); | ||
| 5823 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand; | ||
| 5824 | |||
| 5825 | const operand_lock = switch (operand) { | ||
| 5826 | .register, | ||
| 5827 | .register_c_flag, | ||
| 5828 | .register_v_flag, | ||
| 5829 | => |reg| self.register_manager.lockReg(reg), | ||
| 5830 | else => null, | ||
| 5831 | }; | ||
| 5832 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 5833 | |||
| 5834 | const dest_ty = self.air.typeOfIndex(inst); | ||
| 5835 | const dest = try self.allocRegOrMem(dest_ty, true, inst); | ||
| 5836 | try self.setRegOrMem(dest_ty, dest, operand); | ||
| 5837 | break :result dest; | ||
| 5838 | }; | ||
| 5820 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 5839 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5821 | } | 5840 | } |
| 5822 | 5841 |
src/arch/riscv64/CodeGen.zig+14-1| ... | @@ -2338,7 +2338,20 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2338,7 +2338,20 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 2338 | 2338 | ||
| 2339 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 2339 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2340 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2340 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2341 | const result = try self.resolveInst(ty_op.operand); | 2341 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2342 | const operand = try self.resolveInst(ty_op.operand); | ||
| 2343 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand; | ||
| 2344 | |||
| 2345 | const operand_lock = switch (operand) { | ||
| 2346 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 2347 | else => null, | ||
| 2348 | }; | ||
| 2349 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2350 | |||
| 2351 | const dest = try self.allocRegOrMem(inst, true); | ||
| 2352 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand); | ||
| 2353 | break :result dest; | ||
| 2354 | }; | ||
| 2342 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2355 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2343 | } | 2356 | } |
| 2344 | 2357 |
src/arch/sparc64/CodeGen.zig+15-1| ... | @@ -1091,7 +1091,21 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void | ... | @@ -1091,7 +1091,21 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void |
| 1091 | 1091 | ||
| 1092 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 1092 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1093 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1093 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1094 | const result = try self.resolveInst(ty_op.operand); | 1094 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1095 | const operand = try self.resolveInst(ty_op.operand); | ||
| 1096 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand; | ||
| 1097 | |||
| 1098 | const operand_lock = switch (operand) { | ||
| 1099 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 1100 | .register_with_overflow => |rwo| self.register_manager.lockReg(rwo.reg), | ||
| 1101 | else => null, | ||
| 1102 | }; | ||
| 1103 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 1104 | |||
| 1105 | const dest = try self.allocRegOrMem(inst, true); | ||
| 1106 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand); | ||
| 1107 | break :result dest; | ||
| 1108 | }; | ||
| 1095 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1109 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1096 | } | 1110 | } |
| 1097 | 1111 |
src/arch/x86_64/CodeGen.zig+57-10| ... | @@ -920,9 +920,6 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | ... | @@ -920,9 +920,6 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 920 | const mod = self.bin_file.options.module.?; | 920 | const mod = self.bin_file.options.module.?; |
| 921 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 921 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 922 | }; | 922 | }; |
| 923 | const abi_align = elem_ty.abiAlignment(self.target.*); | ||
| 924 | if (abi_align > self.stack_align) | ||
| 925 | self.stack_align = abi_align; | ||
| 926 | 923 | ||
| 927 | if (reg_ok) { | 924 | if (reg_ok) { |
| 928 | switch (elem_ty.zigTypeTag()) { | 925 | switch (elem_ty.zigTypeTag()) { |
| ... | @@ -951,6 +948,10 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | ... | @@ -951,6 +948,10 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 951 | }, | 948 | }, |
| 952 | } | 949 | } |
| 953 | } | 950 | } |
| 951 | |||
| 952 | const abi_align = elem_ty.abiAlignment(self.target.*); | ||
| 953 | if (abi_align > self.stack_align) | ||
| 954 | self.stack_align = abi_align; | ||
| 954 | const stack_offset = try self.allocMem(inst, abi_size, abi_align); | 955 | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| 955 | return MCValue{ .stack_offset = @intCast(i32, stack_offset) }; | 956 | return MCValue{ .stack_offset = @intCast(i32, stack_offset) }; |
| 956 | } | 957 | } |
| ... | @@ -990,7 +991,7 @@ fn revertState(self: *Self, state: State) void { | ... | @@ -990,7 +991,7 @@ fn revertState(self: *Self, state: State) void { |
| 990 | 991 | ||
| 991 | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { | 992 | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { |
| 992 | const stack_mcv = try self.allocRegOrMem(inst, false); | 993 | const stack_mcv = try self.allocRegOrMem(inst, false); |
| 993 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); | 994 | log.debug("spilling %{d} to stack mcv {any}", .{ inst, stack_mcv }); |
| 994 | const reg_mcv = self.getResolvedInstValue(inst); | 995 | const reg_mcv = self.getResolvedInstValue(inst); |
| 995 | switch (reg_mcv) { | 996 | switch (reg_mcv) { |
| 996 | .register => |other| { | 997 | .register => |other| { |
| ... | @@ -1016,7 +1017,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { | ... | @@ -1016,7 +1017,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 1016 | }; | 1017 | }; |
| 1017 | 1018 | ||
| 1018 | try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv); | 1019 | try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv); |
| 1019 | log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv }); | 1020 | log.debug("spilling %{d} to mcv {any}", .{ inst_to_save, new_mcv }); |
| 1020 | 1021 | ||
| 1021 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 1022 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 1022 | try branch.inst_table.put(self.gpa, inst_to_save, new_mcv); | 1023 | try branch.inst_table.put(self.gpa, inst_to_save, new_mcv); |
| ... | @@ -2114,6 +2115,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2114,6 +2115,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 2114 | }; | 2115 | }; |
| 2115 | break :result dst_mcv; | 2116 | break :result dst_mcv; |
| 2116 | }; | 2117 | }; |
| 2118 | log.debug("airSliceLen(%{d}): {}", .{ inst, result }); | ||
| 2117 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2119 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2118 | } | 2120 | } |
| 2119 | 2121 | ||
| ... | @@ -2641,6 +2643,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2641,6 +2643,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2641 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 2643 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2642 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2644 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2643 | const elem_ty = self.air.typeOfIndex(inst); | 2645 | const elem_ty = self.air.typeOfIndex(inst); |
| 2646 | const elem_size = elem_ty.abiSize(self.target.*); | ||
| 2644 | const result: MCValue = result: { | 2647 | const result: MCValue = result: { |
| 2645 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) | 2648 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) |
| 2646 | break :result MCValue.none; | 2649 | break :result MCValue.none; |
| ... | @@ -2651,13 +2654,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2651,13 +2654,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2651 | break :result MCValue.dead; | 2654 | break :result MCValue.dead; |
| 2652 | 2655 | ||
| 2653 | const dst_mcv: MCValue = blk: { | 2656 | const dst_mcv: MCValue = blk: { |
| 2654 | if (self.reuseOperand(inst, ty_op.operand, 0, ptr)) { | 2657 | if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 2655 | // The MCValue that holds the pointer can be re-used as the value. | 2658 | // The MCValue that holds the pointer can be re-used as the value. |
| 2656 | break :blk ptr; | 2659 | break :blk ptr; |
| 2657 | } else { | 2660 | } else { |
| 2658 | break :blk try self.allocRegOrMem(inst, true); | 2661 | break :blk try self.allocRegOrMem(inst, true); |
| 2659 | } | 2662 | } |
| 2660 | }; | 2663 | }; |
| 2664 | log.debug("airLoad(%{d}): {} <- {}", .{ inst, dst_mcv, ptr }); | ||
| 2661 | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); | 2665 | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); |
| 2662 | break :result dst_mcv; | 2666 | break :result dst_mcv; |
| 2663 | }; | 2667 | }; |
| ... | @@ -2728,10 +2732,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2728,10 +2732,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2728 | 2732 | ||
| 2729 | switch (value) { | 2733 | switch (value) { |
| 2730 | .none => unreachable, | 2734 | .none => unreachable, |
| 2731 | .undef => unreachable, | ||
| 2732 | .dead => unreachable, | 2735 | .dead => unreachable, |
| 2733 | .unreach => unreachable, | 2736 | .unreach => unreachable, |
| 2734 | .eflags => unreachable, | 2737 | .eflags => unreachable, |
| 2738 | .undef => { | ||
| 2739 | try self.genSetReg(value_ty, reg, value); | ||
| 2740 | }, | ||
| 2735 | .immediate => |imm| { | 2741 | .immediate => |imm| { |
| 2736 | switch (abi_size) { | 2742 | switch (abi_size) { |
| 2737 | 1, 2, 4 => { | 2743 | 1, 2, 4 => { |
| ... | @@ -2773,6 +2779,30 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2773,6 +2779,30 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2773 | .register => |src_reg| { | 2779 | .register => |src_reg| { |
| 2774 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); | 2780 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); |
| 2775 | }, | 2781 | }, |
| 2782 | .register_overflow => |ro| { | ||
| 2783 | const ro_reg_lock = self.register_manager.lockReg(ro.reg); | ||
| 2784 | defer if (ro_reg_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2785 | |||
| 2786 | const wrapped_ty = value_ty.structFieldType(0); | ||
| 2787 | try self.genInlineMemcpyRegisterRegister(wrapped_ty, reg, ro.reg, 0); | ||
| 2788 | |||
| 2789 | const overflow_bit_ty = value_ty.structFieldType(1); | ||
| 2790 | const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*); | ||
| 2791 | const tmp_reg = try self.register_manager.allocReg(null, gp); | ||
| 2792 | _ = try self.addInst(.{ | ||
| 2793 | .tag = .cond_set_byte, | ||
| 2794 | .ops = Mir.Inst.Ops.encode(.{ | ||
| 2795 | .reg1 = tmp_reg.to8(), | ||
| 2796 | }), | ||
| 2797 | .data = .{ .cc = ro.eflags }, | ||
| 2798 | }); | ||
| 2799 | try self.genInlineMemcpyRegisterRegister( | ||
| 2800 | overflow_bit_ty, | ||
| 2801 | reg, | ||
| 2802 | tmp_reg, | ||
| 2803 | -@intCast(i32, overflow_bit_offset), | ||
| 2804 | ); | ||
| 2805 | }, | ||
| 2776 | .linker_load, | 2806 | .linker_load, |
| 2777 | .memory, | 2807 | .memory, |
| 2778 | .stack_offset, | 2808 | .stack_offset, |
| ... | @@ -2787,8 +2817,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2787,8 +2817,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2787 | .dest_stack_base = reg.to64(), | 2817 | .dest_stack_base = reg.to64(), |
| 2788 | }); | 2818 | }); |
| 2789 | }, | 2819 | }, |
| 2790 | else => |other| { | 2820 | .ptr_stack_offset => { |
| 2791 | return self.fail("TODO implement set pointee with {}", .{other}); | 2821 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 2822 | return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | ||
| 2792 | }, | 2823 | }, |
| 2793 | } | 2824 | } |
| 2794 | }, | 2825 | }, |
| ... | @@ -2902,6 +2933,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2902,6 +2933,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void { |
| 2902 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 2933 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2903 | const value = try self.resolveInst(bin_op.rhs); | 2934 | const value = try self.resolveInst(bin_op.rhs); |
| 2904 | const value_ty = self.air.typeOf(bin_op.rhs); | 2935 | const value_ty = self.air.typeOf(bin_op.rhs); |
| 2936 | log.debug("airStore(%{d}): {} <- {}", .{ inst, ptr, value }); | ||
| 2905 | try self.store(ptr, value, ptr_ty, value_ty); | 2937 | try self.store(ptr, value, ptr_ty, value_ty); |
| 2906 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 2938 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2907 | } | 2939 | } |
| ... | @@ -6321,7 +6353,22 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6321,7 +6353,22 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 6321 | 6353 | ||
| 6322 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 6354 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 6323 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6355 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6324 | const result = try self.resolveInst(ty_op.operand); | 6356 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 6357 | const operand = try self.resolveInst(ty_op.operand); | ||
| 6358 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand; | ||
| 6359 | |||
| 6360 | const operand_lock = switch (operand) { | ||
| 6361 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 6362 | .register_overflow => |ro| self.register_manager.lockReg(ro.reg), | ||
| 6363 | else => null, | ||
| 6364 | }; | ||
| 6365 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 6366 | |||
| 6367 | const dest = try self.allocRegOrMem(inst, true); | ||
| 6368 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand); | ||
| 6369 | break :result dest; | ||
| 6370 | }; | ||
| 6371 | log.debug("airBitCast(%{d}): {}", .{ inst, result }); | ||
| 6325 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 6372 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6326 | } | 6373 | } |
| 6327 | 6374 |
test/behavior/basic.zig+1| ... | @@ -387,6 +387,7 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { | ... | @@ -387,6 +387,7 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | test "take address of parameter" { | 389 | test "take address of parameter" { |
| 390 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 390 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 391 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 391 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 392 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 392 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 393 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/const_slice_child.zig+1| ... | @@ -9,6 +9,7 @@ var argv: [*]const [*]const u8 = undefined; | ... | @@ -9,6 +9,7 @@ var argv: [*]const [*]const u8 = undefined; |
| 9 | test "const slice child" { | 9 | test "const slice child" { |
| 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 13 | 14 | ||
| 14 | const strs = [_][*]const u8{ "one", "two", "three" }; | 15 | const strs = [_][*]const u8{ "one", "two", "three" }; |
test/behavior/eval.zig+1| ... | @@ -1338,6 +1338,7 @@ test "lazy sizeof is resolved in division" { | ... | @@ -1338,6 +1338,7 @@ test "lazy sizeof is resolved in division" { |
| 1338 | 1338 | ||
| 1339 | test "lazy value is resolved as slice operand" { | 1339 | test "lazy value is resolved as slice operand" { |
| 1340 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1340 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1341 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1341 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1342 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1342 | 1343 | ||
| 1343 | const A = struct { a: u32 }; | 1344 | const A = struct { a: u32 }; |
test/tests.zig+8-8| ... | @@ -58,14 +58,14 @@ const test_targets = blk: { | ... | @@ -58,14 +58,14 @@ const test_targets = blk: { |
| 58 | .link_libc = true, | 58 | .link_libc = true, |
| 59 | .backend = .stage2_c, | 59 | .backend = .stage2_c, |
| 60 | }, | 60 | }, |
| 61 | //.{ | 61 | .{ |
| 62 | // .target = .{ | 62 | .target = .{ |
| 63 | // .cpu_arch = .x86_64, | 63 | .cpu_arch = .x86_64, |
| 64 | // .os_tag = .linux, | 64 | .os_tag = .linux, |
| 65 | // .abi = .none, | 65 | .abi = .none, |
| 66 | // }, | 66 | }, |
| 67 | // .backend = .stage2_x86_64, | 67 | .backend = .stage2_x86_64, |
| 68 | //}, | 68 | }, |
| 69 | .{ | 69 | .{ |
| 70 | .target = .{ | 70 | .target = .{ |
| 71 | .cpu_arch = .aarch64, | 71 | .cpu_arch = .aarch64, |