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 {
939939 /// Copies a value to a register without tracking the register. The register is not considered
940940 /// allocated. A second call to `copyToTmpRegister` may return the same register.
941941 /// 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 {
943943 const reg = self.findUnusedReg() orelse b: {
944944 // We'll take over the first register. Move the instruction that was previously
945945 // there to a stack allocation.
......@@ -956,7 +956,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
956956
957957 break :b reg;
958958 };
959 try self.genSetReg(src, reg, mcv);
959 try self.genSetReg(src, ty, reg, mcv);
960960 return reg;
961961 }
962962
......@@ -983,7 +983,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
983983
984984 break :b reg;
985985 };
986 try self.genSetReg(reg_owner.src, reg, mcv);
986 try self.genSetReg(reg_owner.src, reg_owner.ty, reg, mcv);
987987 return MCValue{ .register = reg };
988988 }
989989
......@@ -1351,13 +1351,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
13511351 // Load immediate into register if it doesn't fit
13521352 // as an operand
13531353 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);
13551355 },
13561356 .register => |reg| Instruction.Operand.reg(reg, Instruction.Operand.Shift.none),
13571357 .stack_offset,
13581358 .embedded_in_code,
13591359 .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),
13611361 };
13621362
13631363 switch (op) {
......@@ -1443,7 +1443,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
14431443 switch (src_mcv) {
14441444 .immediate => |imm| {
14451445 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) };
14471447 }
14481448 },
14491449 else => {},
......@@ -1474,7 +1474,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
14741474 .register => |dst_reg| {
14751475 switch (src_mcv) {
14761476 .none => unreachable,
1477 .undef => try self.genSetReg(src, dst_reg, .undef),
1477 .undef => try self.genSetReg(src, dst_ty, dst_reg, .undef),
14781478 .dead, .unreach => unreachable,
14791479 .ptr_stack_offset => unreachable,
14801480 .ptr_embedded_in_code => unreachable,
......@@ -1684,7 +1684,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16841684 switch (mc_arg) {
16851685 .none => continue,
16861686 .register => |reg| {
1687 try self.genSetReg(arg.src, reg, arg_mcv);
1687 try self.genSetReg(arg.src, arg.ty, reg, arg_mcv);
16881688 // TODO interact with the register allocator to mark the instruction as moved.
16891689 },
16901690 .stack_offset => {
......@@ -1753,7 +1753,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
17531753 else
17541754 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 });
17571757 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32());
17581758 } else if (func_value.castTag(.extern_fn)) |_| {
17591759 return self.fail(inst.base.src, "TODO implement calling extern functions", .{});
......@@ -1826,7 +1826,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
18261826 .compare_flags_signed => unreachable,
18271827 .compare_flags_unsigned => unreachable,
18281828 .register => |reg| {
1829 try self.genSetReg(arg.src, reg, arg_mcv);
1829 try self.genSetReg(arg.src, arg.ty, reg, arg_mcv);
18301830 // TODO interact with the register allocator to mark the instruction as moved.
18311831 },
18321832 .stack_offset => {
......@@ -1854,7 +1854,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
18541854 else
18551855 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
18591859 // TODO: add Instruction.supportedOn
18601860 // function for ARM
......@@ -1889,7 +1889,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
18891889 .compare_flags_signed => unreachable,
18901890 .compare_flags_unsigned => unreachable,
18911891 .register => |reg| {
1892 try self.genSetReg(arg.src, reg, arg_mcv);
1892 try self.genSetReg(arg.src, arg.ty, reg, arg_mcv);
18931893 // TODO interact with the register allocator to mark the instruction as moved.
18941894 },
18951895 .stack_offset => {
......@@ -1917,7 +1917,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
19171917 else
19181918 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
19221922 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
19231923 } else if (func_value.castTag(.extern_fn)) |_| {
......@@ -1940,7 +1940,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
19401940 switch (mc_arg) {
19411941 .none => continue,
19421942 .register => |reg| {
1943 try self.genSetReg(arg.src, reg, arg_mcv);
1943 try self.genSetReg(arg.src, arg.ty, reg, arg_mcv);
19441944 // TODO interact with the register allocator to mark the instruction as moved.
19451945 },
19461946 .stack_offset => {
......@@ -1973,12 +1973,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
19731973 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
19741974 switch (arch) {
19751975 .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 });
19771977 // callq *%rax
19781978 self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
19791979 },
19801980 .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 });
19821982 // blr x30
19831983 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
19841984 },
......@@ -2579,7 +2579,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
25792579 const reg = parseRegName(reg_name) orelse
25802580 return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name});
25812581 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);
25832583 }
25842584
25852585 if (mem.eql(u8, inst.asm_source, "svc #0")) {
......@@ -2609,7 +2609,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
26092609 const reg = parseRegName(reg_name) orelse
26102610 return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name});
26112611 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);
26132613 }
26142614
26152615 if (mem.eql(u8, inst.asm_source, "svc #0")) {
......@@ -2641,7 +2641,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
26412641 const reg = parseRegName(reg_name) orelse
26422642 return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name});
26432643 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);
26452645 }
26462646
26472647 if (mem.eql(u8, inst.asm_source, "ecall")) {
......@@ -2671,7 +2671,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
26712671 const reg = parseRegName(reg_name) orelse
26722672 return self.fail(inst.base.src, "unrecognized register: '{s}'", .{reg_name});
26732673 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);
26752675 }
26762676
26772677 if (mem.eql(u8, inst.asm_source, "syscall")) {
......@@ -2733,7 +2733,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27332733 fn setRegOrMem(self: *Self, src: usize, ty: Type, loc: MCValue, val: MCValue) !void {
27342734 switch (loc) {
27352735 .none => return,
2736 .register => |reg| return self.genSetReg(src, reg, val),
2736 .register => |reg| return self.genSetReg(src, ty, reg, val),
27372737 .stack_offset => |off| return self.genSetStack(src, ty, off, val),
27382738 .memory => {
27392739 return self.fail(src, "TODO implement setRegOrMem for memory", .{});
......@@ -2768,7 +2768,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27682768 return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{});
27692769 },
27702770 .immediate => {
2771 const reg = try self.copyToTmpRegister(src, mcv);
2771 const reg = try self.copyToTmpRegister(src, ty, mcv);
27722772 return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg });
27732773 },
27742774 .embedded_in_code => |code_offset| {
......@@ -2782,7 +2782,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27822782 1, 4 => {
27832783 const offset = if (math.cast(u12, adj_off)) |imm| blk: {
27842784 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);
27862786 const str = switch (abi_size) {
27872787 1 => Instruction.strb,
27882788 4 => Instruction.str,
......@@ -2797,7 +2797,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27972797 2 => {
27982798 const offset = if (adj_off <= math.maxInt(u8)) blk: {
27992799 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
28022802 writeInt(u32, try self.code.addManyAsArray(4), Instruction.strh(.al, reg, .fp, .{
28032803 .offset = offset,
......@@ -2814,7 +2814,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
28142814 if (stack_offset == off)
28152815 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);
28182818 return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg });
28192819 },
28202820 },
......@@ -2903,7 +2903,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29032903 if (stack_offset == off)
29042904 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);
29072907 return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg });
29082908 },
29092909 },
......@@ -2931,7 +2931,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29312931 return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{});
29322932 },
29332933 .immediate => {
2934 const reg = try self.copyToTmpRegister(src, mcv);
2934 const reg = try self.copyToTmpRegister(src, ty, mcv);
29352935 return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg });
29362936 },
29372937 .embedded_in_code => |code_offset| {
......@@ -2946,7 +2946,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29462946 const offset = if (math.cast(i9, adj_off)) |imm|
29472947 Instruction.LoadStoreOffset.imm_post_index(-imm)
29482948 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 }));
29502950 const rn: Register = switch (arch) {
29512951 .aarch64, .aarch64_be => .x29,
29522952 .aarch64_32 => .w29,
......@@ -2967,7 +2967,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29672967 if (stack_offset == off)
29682968 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);
29712971 return self.genSetStack(src, ty, stack_offset, MCValue{ .register = reg });
29722972 },
29732973 },
......@@ -2975,7 +2975,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29752975 }
29762976 }
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 {
29792979 switch (arch) {
29802980 .arm, .armeb => switch (mcv) {
29812981 .dead => unreachable,
......@@ -2986,7 +2986,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
29862986 if (!self.wantSafety())
29872987 return; // The already existing value will do just fine.
29882988 // Write the debug undefined value.
2989 return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaa });
2989 return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaa });
29902990 },
29912991 .compare_flags_unsigned,
29922992 .compare_flags_signed,
......@@ -3051,21 +3051,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
30513051 .memory => |addr| {
30523052 // The value is in memory at a hard-coded address.
30533053 // 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 });
30553055 writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, reg, .{ .offset = Instruction.Offset.none }).toU32());
30563056 },
30573057 .stack_offset => |unadjusted_off| {
30583058 // 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.*);
30623060 const adj_off = unadjusted_off + abi_size;
30633061
30643062 switch (abi_size) {
30653063 1, 4 => {
30663064 const offset = if (adj_off <= math.maxInt(u12)) blk: {
30673065 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);
30693067 const ldr = switch (abi_size) {
30703068 1 => Instruction.ldrb,
30713069 4 => Instruction.ldr,
......@@ -3080,7 +3078,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
30803078 2 => {
30813079 const offset = if (adj_off <= math.maxInt(u8)) blk: {
30823080 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
30853083 writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldrh(.al, reg, .fp, .{
30863084 .offset = offset,
......@@ -3102,8 +3100,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
31023100 return; // The already existing value will do just fine.
31033101 // Write the debug undefined value.
31043102 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 }),
31073105 else => unreachable, // unexpected register size
31083106 }
31093107 },
......@@ -3216,7 +3214,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32163214 } else {
32173215 // The value is in memory at a hard-coded address.
32183216 // 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 });
32203218 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .register = .{ .rn = reg } }).toU32());
32213219 }
32223220 },
......@@ -3231,7 +3229,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32313229 if (!self.wantSafety())
32323230 return; // The already existing value will do just fine.
32333231 // Write the debug undefined value.
3234 return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
3232 return self.genSetReg(src, ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
32353233 },
32363234 .immediate => |unsigned_x| {
32373235 const x = @bitCast(i64, unsigned_x);
......@@ -3256,7 +3254,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32563254 .memory => |addr| {
32573255 // The value is in memory at a hard-coded address.
32583256 // 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
32613259 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ld(reg, 0, reg).toU32());
32623260 // LOAD imm=[i12 offset = 0], rs1 =
......@@ -3275,10 +3273,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32753273 return; // The already existing value will do just fine.
32763274 // Write the debug undefined value.
32773275 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 }),
32823280 else => unreachable,
32833281 }
32843282 },
......@@ -3492,7 +3490,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
34923490 assert(id3 != 4 and id3 != 5);
34933491
34943492 // 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
34973495 // Now, the register contains the address of the value to load into it
34983496 // 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 {
35913589 // This immediate is unsigned.
35923590 const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
35933591 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) };
35953593 }
35963594 },
35973595 else => {},