| ... | ... | @@ -939,7 +939,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 939 | 939 | /// Copies a value to a register without tracking the register. The register is not considered |
| 940 | 940 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 941 | 941 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 942 | | fn copyToTmpRegister(self: *Self, src: usize, mcv: MCValue) !Register { |
| 942 | fn copyToTmpRegister(self: *Self, src: usize, ty: Type, mcv: MCValue) !Register { |
| 943 | 943 | const reg = self.findUnusedReg() orelse b: { |
| 944 | 944 | // We'll take over the first register. Move the instruction that was previously |
| 945 | 945 | // there to a stack allocation. |
| ... | ... | @@ -956,7 +956,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 956 | 956 | |
| 957 | 957 | break :b reg; |
| 958 | 958 | }; |
| 959 | | try self.genSetReg(src, reg, mcv); |
| 959 | try self.genSetReg(src, ty, reg, mcv); |
| 960 | 960 | return reg; |
| 961 | 961 | } |
| 962 | 962 | |
| ... | ... | @@ -983,7 +983,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 983 | 983 | |
| 984 | 984 | break :b reg; |
| 985 | 985 | }; |
| 986 | | try self.genSetReg(reg_owner.src, reg, mcv); |
| 986 | try self.genSetReg(reg_owner.src, reg_owner.ty, reg, mcv); |
| 987 | 987 | return MCValue{ .register = reg }; |
| 988 | 988 | } |
| 989 | 989 | |
| ... | ... | @@ -1351,13 +1351,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1351 | 1351 | // Load immediate into register if it doesn't fit |
| 1352 | 1352 | // as an operand |
| 1353 | 1353 | break :blk Instruction.Operand.fromU32(@intCast(u32, imm)) orelse |
| 1354 | | Instruction.Operand.reg(try self.copyToTmpRegister(src, op2), Instruction.Operand.Shift.none); |
| 1354 | Instruction.Operand.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), op2), Instruction.Operand.Shift.none); |
| 1355 | 1355 | }, |
| 1356 | 1356 | .register => |reg| Instruction.Operand.reg(reg, Instruction.Operand.Shift.none), |
| 1357 | 1357 | .stack_offset, |
| 1358 | 1358 | .embedded_in_code, |
| 1359 | 1359 | .memory, |
| 1360 | | => Instruction.Operand.reg(try self.copyToTmpRegister(src, op2), Instruction.Operand.Shift.none), |
| 1360 | => Instruction.Operand.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), op2), Instruction.Operand.Shift.none), |
| 1361 | 1361 | }; |
| 1362 | 1362 | |
| 1363 | 1363 | switch (op) { |
| ... | ... | @@ -1443,7 +1443,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1443 | 1443 | switch (src_mcv) { |
| 1444 | 1444 | .immediate => |imm| { |
| 1445 | 1445 | if (imm > math.maxInt(u31)) { |
| 1446 | | src_mcv = MCValue{ .register = try self.copyToTmpRegister(src_inst.src, src_mcv) }; |
| 1446 | src_mcv = MCValue{ .register = try self.copyToTmpRegister(src_inst.src, Type.initTag(.u64), src_mcv) }; |
| 1447 | 1447 | } |
| 1448 | 1448 | }, |
| 1449 | 1449 | else => {}, |
| ... | ... | @@ -1474,7 +1474,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1474 | 1474 | .register => |dst_reg| { |
| 1475 | 1475 | switch (src_mcv) { |
| 1476 | 1476 | .none => unreachable, |
| 1477 | | .undef => try self.genSetReg(src, dst_reg, .undef), |
| 1477 | .undef => try self.genSetReg(src, dst_ty, dst_reg, .undef), |
| 1478 | 1478 | .dead, .unreach => unreachable, |
| 1479 | 1479 | .ptr_stack_offset => unreachable, |
| 1480 | 1480 | .ptr_embedded_in_code => unreachable, |
| ... | ... | @@ -1684,7 +1684,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1684 | 1684 | switch (mc_arg) { |
| 1685 | 1685 | .none => continue, |
| 1686 | 1686 | .register => |reg| { |
| 1687 | | try self.genSetReg(arg.src, reg, arg_mcv); |
| 1687 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 1688 | 1688 | // TODO interact with the register allocator to mark the instruction as moved. |
| 1689 | 1689 | }, |
| 1690 | 1690 | .stack_offset => { |
| ... | ... | @@ -1753,7 +1753,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1753 | 1753 | else |
| 1754 | 1754 | unreachable; |
| 1755 | 1755 | |
| 1756 | | try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr }); |
| 1756 | try self.genSetReg(inst.base.src, Type.initTag(.usize), .ra, .{ .memory = got_addr }); |
| 1757 | 1757 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32()); |
| 1758 | 1758 | } else if (func_value.castTag(.extern_fn)) |_| { |
| 1759 | 1759 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); |
| ... | ... | @@ -1826,7 +1826,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1826 | 1826 | .compare_flags_signed => unreachable, |
| 1827 | 1827 | .compare_flags_unsigned => unreachable, |
| 1828 | 1828 | .register => |reg| { |
| 1829 | | try self.genSetReg(arg.src, reg, arg_mcv); |
| 1829 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 1830 | 1830 | // TODO interact with the register allocator to mark the instruction as moved. |
| 1831 | 1831 | }, |
| 1832 | 1832 | .stack_offset => { |
| ... | ... | @@ -1854,7 +1854,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1854 | 1854 | else |
| 1855 | 1855 | unreachable; |
| 1856 | 1856 | |
| 1857 | | try self.genSetReg(inst.base.src, .lr, .{ .memory = got_addr }); |
| 1857 | try self.genSetReg(inst.base.src, Type.initTag(.usize), .lr, .{ .memory = got_addr }); |
| 1858 | 1858 | |
| 1859 | 1859 | // TODO: add Instruction.supportedOn |
| 1860 | 1860 | // function for ARM |
| ... | ... | @@ -1889,7 +1889,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1889 | 1889 | .compare_flags_signed => unreachable, |
| 1890 | 1890 | .compare_flags_unsigned => unreachable, |
| 1891 | 1891 | .register => |reg| { |
| 1892 | | try self.genSetReg(arg.src, reg, arg_mcv); |
| 1892 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 1893 | 1893 | // TODO interact with the register allocator to mark the instruction as moved. |
| 1894 | 1894 | }, |
| 1895 | 1895 | .stack_offset => { |
| ... | ... | @@ -1917,7 +1917,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1917 | 1917 | else |
| 1918 | 1918 | unreachable; |
| 1919 | 1919 | |
| 1920 | | try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr }); |
| 1920 | try self.genSetReg(inst.base.src, Type.initTag(.usize), .x30, .{ .memory = got_addr }); |
| 1921 | 1921 | |
| 1922 | 1922 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32()); |
| 1923 | 1923 | } else if (func_value.castTag(.extern_fn)) |_| { |
| ... | ... | @@ -1940,7 +1940,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1940 | 1940 | switch (mc_arg) { |
| 1941 | 1941 | .none => continue, |
| 1942 | 1942 | .register => |reg| { |
| 1943 | | try self.genSetReg(arg.src, reg, arg_mcv); |
| 1943 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 1944 | 1944 | // TODO interact with the register allocator to mark the instruction as moved. |
| 1945 | 1945 | }, |
| 1946 | 1946 | .stack_offset => { |
| ... | ... | @@ -1973,12 +1973,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1973 | 1973 | const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64); |
| 1974 | 1974 | switch (arch) { |
| 1975 | 1975 | .x86_64 => { |
| 1976 | | try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr }); |
| 1976 | try self.genSetReg(inst.base.src, Type.initTag(.u32), .rax, .{ .memory = got_addr }); |
| 1977 | 1977 | // callq *%rax |
| 1978 | 1978 | self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 }); |
| 1979 | 1979 | }, |
| 1980 | 1980 | .aarch64 => { |
| 1981 | | try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr }); |
| 1981 | try self.genSetReg(inst.base.src, Type.initTag(.u32), .x30, .{ .memory = got_addr }); |
| 1982 | 1982 | // blr x30 |
| 1983 | 1983 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32()); |
| 1984 | 1984 | }, |
| ... | ... | @@ -2579,7 +2579,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2579 | 2579 | const reg = parseRegName(reg_name) orelse |
| 2580 | 2580 | return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name}); |
| 2581 | 2581 | const arg = try self.resolveInst(inst.args[i]); |
| 2582 | | try self.genSetReg(inst.base.src, reg, arg); |
| 2582 | try self.genSetReg(inst.base.src, inst.args[i].ty, reg, arg); |
| 2583 | 2583 | } |
| 2584 | 2584 | |
| 2585 | 2585 | if (mem.eql(u8, inst.asm_source, "svc #0")) { |
| ... | ... | @@ -2609,7 +2609,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2609 | 2609 | const reg = parseRegName(reg_name) orelse |
| 2610 | 2610 | return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name}); |
| 2611 | 2611 | const arg = try self.resolveInst(inst.args[i]); |
| 2612 | | try self.genSetReg(inst.base.src, reg, arg); |
| 2612 | try self.genSetReg(inst.base.src, inst.args[i].ty, reg, arg); |
| 2613 | 2613 | } |
| 2614 | 2614 | |
| 2615 | 2615 | if (mem.eql(u8, inst.asm_source, "svc #0")) { |
| ... | ... | @@ -2641,7 +2641,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2641 | 2641 | const reg = parseRegName(reg_name) orelse |
| 2642 | 2642 | return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name}); |
| 2643 | 2643 | const arg = try self.resolveInst(inst.args[i]); |
| 2644 | | try self.genSetReg(inst.base.src, reg, arg); |
| 2644 | try self.genSetReg(inst.base.src, inst.args[i].ty, reg, arg); |
| 2645 | 2645 | } |
| 2646 | 2646 | |
| 2647 | 2647 | if (mem.eql(u8, inst.asm_source, "ecall")) { |
| ... | ... | @@ -2671,7 +2671,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2671 | 2671 | const reg = parseRegName(reg_name) orelse |
| 2672 | 2672 | return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name}); |
| 2673 | 2673 | const arg = try self.resolveInst(inst.args[i]); |
| 2674 | | try self.genSetReg(inst.base.src, reg, arg); |
| 2674 | try self.genSetReg(inst.base.src, inst.args[i].ty, reg, arg); |
| 2675 | 2675 | } |
| 2676 | 2676 | |
| 2677 | 2677 | if (mem.eql(u8, inst.asm_source, "syscall")) { |
| ... | ... | @@ -2733,7 +2733,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2733 | 2733 | fn setRegOrMem(self: *Self, src: usize, ty: Type, loc: MCValue, val: MCValue) !void { |
| 2734 | 2734 | switch (loc) { |
| 2735 | 2735 | .none => return, |
| 2736 | | .register => |reg| return self.genSetReg(src, reg, val), |
| 2736 | .register => |reg| return self.genSetReg(src, ty, reg, val), |
| 2737 | 2737 | .stack_offset => |off| return self.genSetStack(src, ty, off, val), |
| 2738 | 2738 | .memory => { |
| 2739 | 2739 | return self.fail(src, "TODO implement setRegOrMem for memory", .{}); |
| ... | ... | @@ -2768,7 +2768,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2768 | 2768 | return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{}); |
| 2769 | 2769 | }, |
| 2770 | 2770 | .immediate => { |
| 2771 | | const reg = try self.copyToTmpRegister(src, mcv); |
| 2771 | const reg = try self.copyToTmpRegister(src, ty, mcv); |
| 2772 | 2772 | return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg }); |
| 2773 | 2773 | }, |
| 2774 | 2774 | .embedded_in_code => |code_offset| { |
| ... | ... | @@ -2782,7 +2782,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2782 | 2782 | 1, 4 => { |
| 2783 | 2783 | const offset = if (math.cast(u12, adj_off)) |imm| blk: { |
| 2784 | 2784 | break :blk Instruction.Offset.imm(imm); |
| 2785 | | } else |_| Instruction.Offset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off }), 0); |
| 2785 | } else |_| Instruction.Offset.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), MCValue{ .immediate = adj_off }), 0); |
| 2786 | 2786 | const str = switch (abi_size) { |
| 2787 | 2787 | 1 => Instruction.strb, |
| 2788 | 2788 | 4 => Instruction.str, |
| ... | ... | @@ -2797,7 +2797,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2797 | 2797 | 2 => { |
| 2798 | 2798 | const offset = if (adj_off <= math.maxInt(u8)) blk: { |
| 2799 | 2799 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); |
| 2800 | | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off })); |
| 2800 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), MCValue{ .immediate = adj_off })); |
| 2801 | 2801 | |
| 2802 | 2802 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.strh(.al, reg, .fp, .{ |
| 2803 | 2803 | .offset = offset, |
| ... | ... | @@ -2814,7 +2814,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2814 | 2814 | if (stack_offset == off) |
| 2815 | 2815 | return; // Copy stack variable to itself; nothing to do. |
| 2816 | 2816 | |
| 2817 | | const reg = try self.copyToTmpRegister(src, mcv); |
| 2817 | const reg = try self.copyToTmpRegister(src, ty, mcv); |
| 2818 | 2818 | return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg }); |
| 2819 | 2819 | }, |
| 2820 | 2820 | }, |
| ... | ... | @@ -2903,7 +2903,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2903 | 2903 | if (stack_offset == off) |
| 2904 | 2904 | return; // Copy stack variable to itself; nothing to do. |
| 2905 | 2905 | |
| 2906 | | const reg = try self.copyToTmpRegister(src, mcv); |
| 2906 | const reg = try self.copyToTmpRegister(src, ty, mcv); |
| 2907 | 2907 | return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg }); |
| 2908 | 2908 | }, |
| 2909 | 2909 | }, |
| ... | ... | @@ -2931,7 +2931,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2931 | 2931 | return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{}); |
| 2932 | 2932 | }, |
| 2933 | 2933 | .immediate => { |
| 2934 | | const reg = try self.copyToTmpRegister(src, mcv); |
| 2934 | const reg = try self.copyToTmpRegister(src, ty, mcv); |
| 2935 | 2935 | return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg }); |
| 2936 | 2936 | }, |
| 2937 | 2937 | .embedded_in_code => |code_offset| { |
| ... | ... | @@ -2946,7 +2946,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2946 | 2946 | const offset = if (math.cast(i9, adj_off)) |imm| |
| 2947 | 2947 | Instruction.LoadStoreOffset.imm_post_index(-imm) |
| 2948 | 2948 | else |_| |
| 2949 | | Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off })); |
| 2949 | Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(src, Type.initTag(.u64), MCValue{ .immediate = adj_off })); |
| 2950 | 2950 | const rn: Register = switch (arch) { |
| 2951 | 2951 | .aarch64, .aarch64_be => .x29, |
| 2952 | 2952 | .aarch64_32 => .w29, |
| ... | ... | @@ -2967,7 +2967,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2967 | 2967 | if (stack_offset == off) |
| 2968 | 2968 | return; // Copy stack variable to itself; nothing to do. |
| 2969 | 2969 | |
| 2970 | | const reg = try self.copyToTmpRegister(src, mcv); |
| 2970 | const reg = try self.copyToTmpRegister(src, ty, mcv); |
| 2971 | 2971 | return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg }); |
| 2972 | 2972 | }, |
| 2973 | 2973 | }, |
| ... | ... | @@ -2975,7 +2975,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2975 | 2975 | } |
| 2976 | 2976 | } |
| 2977 | 2977 | |
| 2978 | | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { |
| 2978 | fn genSetReg(self: *Self, src: usize, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 2979 | 2979 | switch (arch) { |
| 2980 | 2980 | .arm, .armeb => switch (mcv) { |
| 2981 | 2981 | .dead => unreachable, |
| ... | ... | @@ -2986,7 +2986,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2986 | 2986 | if (!self.wantSafety()) |
| 2987 | 2987 | return; // The already existing value will do just fine. |
| 2988 | 2988 | // Write the debug undefined value. |
| 2989 | | return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaa }); |
| 2989 | return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaa }); |
| 2990 | 2990 | }, |
| 2991 | 2991 | .compare_flags_unsigned, |
| 2992 | 2992 | .compare_flags_signed, |
| ... | ... | @@ -3051,21 +3051,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3051 | 3051 | .memory => |addr| { |
| 3052 | 3052 | // The value is in memory at a hard-coded address. |
| 3053 | 3053 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3054 | | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| 3054 | try self.genSetReg(src, ty, reg, .{ .immediate = addr }); |
| 3055 | 3055 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, reg, .{ .offset = Instruction.Offset.none }).toU32()); |
| 3056 | 3056 | }, |
| 3057 | 3057 | .stack_offset => |unadjusted_off| { |
| 3058 | 3058 | // TODO: maybe addressing from sp instead of fp |
| 3059 | | // TODO: supply type information to genSetReg as we do to genSetStack |
| 3060 | | // const abi_size = ty.abiSize(self.target.*); |
| 3061 | | const abi_size = 4; |
| 3059 | const abi_size = ty.abiSize(self.target.*); |
| 3062 | 3060 | const adj_off = unadjusted_off + abi_size; |
| 3063 | 3061 | |
| 3064 | 3062 | switch (abi_size) { |
| 3065 | 3063 | 1, 4 => { |
| 3066 | 3064 | const offset = if (adj_off <= math.maxInt(u12)) blk: { |
| 3067 | 3065 | break :blk Instruction.Offset.imm(@intCast(u12, adj_off)); |
| 3068 | | } else Instruction.Offset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off }), 0); |
| 3066 | } else Instruction.Offset.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), MCValue{ .immediate = adj_off }), 0); |
| 3069 | 3067 | const ldr = switch (abi_size) { |
| 3070 | 3068 | 1 => Instruction.ldrb, |
| 3071 | 3069 | 4 => Instruction.ldr, |
| ... | ... | @@ -3080,7 +3078,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3080 | 3078 | 2 => { |
| 3081 | 3079 | const offset = if (adj_off <= math.maxInt(u8)) blk: { |
| 3082 | 3080 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); |
| 3083 | | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off })); |
| 3081 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(src, Type.initTag(.u32), MCValue{ .immediate = adj_off })); |
| 3084 | 3082 | |
| 3085 | 3083 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldrh(.al, reg, .fp, .{ |
| 3086 | 3084 | .offset = offset, |
| ... | ... | @@ -3102,8 +3100,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3102 | 3100 | return; // The already existing value will do just fine. |
| 3103 | 3101 | // Write the debug undefined value. |
| 3104 | 3102 | switch (reg.size()) { |
| 3105 | | 32 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaa }), |
| 3106 | | 64 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), |
| 3103 | 32 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaa }), |
| 3104 | 64 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), |
| 3107 | 3105 | else => unreachable, // unexpected register size |
| 3108 | 3106 | } |
| 3109 | 3107 | }, |
| ... | ... | @@ -3216,7 +3214,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3216 | 3214 | } else { |
| 3217 | 3215 | // The value is in memory at a hard-coded address. |
| 3218 | 3216 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3219 | | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| 3217 | try self.genSetReg(src, Type.initTag(.usize), reg, .{ .immediate = addr }); |
| 3220 | 3218 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .register = .{ .rn = reg } }).toU32()); |
| 3221 | 3219 | } |
| 3222 | 3220 | }, |
| ... | ... | @@ -3231,7 +3229,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3231 | 3229 | if (!self.wantSafety()) |
| 3232 | 3230 | return; // The already existing value will do just fine. |
| 3233 | 3231 | // Write the debug undefined value. |
| 3234 | | return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }); |
| 3232 | return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }); |
| 3235 | 3233 | }, |
| 3236 | 3234 | .immediate => |unsigned_x| { |
| 3237 | 3235 | const x = @bitCast(i64, unsigned_x); |
| ... | ... | @@ -3256,7 +3254,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3256 | 3254 | .memory => |addr| { |
| 3257 | 3255 | // The value is in memory at a hard-coded address. |
| 3258 | 3256 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3259 | | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| 3257 | try self.genSetReg(src, ty, reg, .{ .immediate = addr }); |
| 3260 | 3258 | |
| 3261 | 3259 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ld(reg, 0, reg).toU32()); |
| 3262 | 3260 | // LOAD imm=[i12 offset = 0], rs1 = |
| ... | ... | @@ -3275,10 +3273,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3275 | 3273 | return; // The already existing value will do just fine. |
| 3276 | 3274 | // Write the debug undefined value. |
| 3277 | 3275 | switch (reg.size()) { |
| 3278 | | 8 => return self.genSetReg(src, reg, .{ .immediate = 0xaa }), |
| 3279 | | 16 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaa }), |
| 3280 | | 32 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaa }), |
| 3281 | | 64 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), |
| 3276 | 8 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaa }), |
| 3277 | 16 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaa }), |
| 3278 | 32 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaa }), |
| 3279 | 64 => return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), |
| 3282 | 3280 | else => unreachable, |
| 3283 | 3281 | } |
| 3284 | 3282 | }, |
| ... | ... | @@ -3492,7 +3490,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3492 | 3490 | assert(id3 != 4 and id3 != 5); |
| 3493 | 3491 | |
| 3494 | 3492 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
| 3495 | | try self.genSetReg(src, reg, MCValue{ .immediate = x }); |
| 3493 | try self.genSetReg(src, ty, reg, MCValue{ .immediate = x }); |
| 3496 | 3494 | |
| 3497 | 3495 | // Now, the register contains the address of the value to load into it |
| 3498 | 3496 | // Currently, we're only allowing 64-bit registers, so we need the `REX.W 8B /r` variant. |
| ... | ... | @@ -3591,7 +3589,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3591 | 3589 | // This immediate is unsigned. |
| 3592 | 3590 | const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed)); |
| 3593 | 3591 | if (imm >= math.maxInt(U)) { |
| 3594 | | return MCValue{ .register = try self.copyToTmpRegister(inst.src, mcv) }; |
| 3592 | return MCValue{ .register = try self.copyToTmpRegister(inst.src, Type.initTag(.usize), mcv) }; |
| 3595 | 3593 | } |
| 3596 | 3594 | }, |
| 3597 | 3595 | else => {}, |