authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-02-05 21:05:14+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-21 12:23:36+02:00
log9712e892656ace8ee26c2b2decfde0f2d116ec54
tree111c2000eaa80b4dbcd6d1b1ca97aefa585cb5bd
parentef6aa3d027f781acd577134ffab4b235cff91582

stage2 codegen: Add Type argument to genSetReg


1 files changed, 46 insertions(+), 48 deletions(-)

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