diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-09 22:15:58 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-11 20:05:49 +0100 |
| commit | 022b308d6a0a3d3cf178ddc6e887f24369f69deb (patch) | |
| tree | 4d8c893a9dd0176515dcdc7c461b595bb002254d /src | |
| parent | 4af8313f362e393f51af1bcefd0b91c3b1ce5611 (diff) | |
| download | zig-022b308d6a0a3d3cf178ddc6e887f24369f69deb.tar.gz zig-022b308d6a0a3d3cf178ddc6e887f24369f69deb.zip | |
x86_64: start converting MI references
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 251 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 28 |
2 files changed, 106 insertions, 173 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f3f425d549..e9e7e1875b 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -509,6 +509,29 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { }); } +fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate) !void { + const ops: Mir.Inst.Ops = switch (m) { + .sib => if (imm == .signed) .mi_s_sib else .mi_u_sib, + .rip => if (imm == .signed) .mi_s_rip else .mi_u_rip, + else => unreachable, + }; + const payload: u32 = switch (ops) { + .mi_s_sib, .mi_u_sib => try self.addExtra(Mir.MemorySib.encode(m)), + .mi_s_rip, .mi_u_rip => try self.addExtra(Mir.MemoryRip.encode(m)), + else => unreachable, + }; + const data: Mir.Inst.Data = switch (ops) { + .mi_s_sib, .mi_s_rip => .{ .xi_s = .{ .imm = imm.signed, .payload = payload } }, + .mi_u_sib, .mi_u_rip => .{ .xi_u = .{ .imm = @intCast(u32, imm.unsigned), .payload = payload } }, + else => unreachable, + }; + _ = try self.addInst(.{ + .tag = tag, + .ops = ops, + .data = data, + }); +} + fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { const ops: Mir.Inst.Ops = switch (m) { .sib => .rm_sib, @@ -2776,7 +2799,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue } fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { - const abi_size = value_ty.abiSize(self.target.*); + const abi_size = @intCast(u32, value_ty.abiSize(self.target.*)); switch (ptr) { .none => unreachable, .undef => unreachable, @@ -2807,28 +2830,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type try self.genSetReg(value_ty, reg, value); }, .immediate => |imm| { - _ = imm; switch (abi_size) { 1, 2, 4 => { - // TODO this is wasteful! - // introduce new MIR tag specifically for mov [reg + 0], imm - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = 0, - // .operand = @truncate(u32, imm), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = reg.to64(), - // .flags = switch (abi_size) { - // 1 => 0b00, - // 2 => 0b01, - // 4 => 0b10, - // else => unreachable, - // }, - // }), - // .data = .{ .payload = payload }, - // }); + try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ + .base = reg.to64(), + .disp = 0, + }), Immediate.u(@truncate(u32, imm))); }, 8 => { // TODO: optimization: if the imm is only using the lower @@ -2913,19 +2920,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); } - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = 0, - // // TODO check if this logic is correct - // .operand = @intCast(u32, imm), - // }); - const flags: u2 = switch (abi_size) { - 1 => 0b00, - 2 => 0b01, - 4 => 0b10, - 8 => 0b11, - else => unreachable, - }; - if (flags == 0b11) { + if (abi_size == 8) { + // TODO const top_bits: u32 = @intCast(u32, imm >> 32); const can_extend = if (value_ty.isUnsignedInt()) (top_bits == 0) and (imm & 0x8000_0000) == 0 @@ -2936,14 +2932,10 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type return self.fail("TODO imm64 would get incorrectly sign extended", .{}); } } - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = addr_reg.to64(), - // .flags = flags, - // }), - // .data = .{ .payload = payload }, - // }); + try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ + .base = addr_reg.to64(), + .disp = 0, + }), Immediate.u(@intCast(u32, imm))); }, .register => { return self.store(new_ptr, value, ptr_ty, value_ty); @@ -3595,12 +3587,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu ), }, .immediate => |imm| { - _ = imm; - // _ = try self.addInst(.{ - // .tag = mir_tag, - // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), - // .data = .{ .imm = @intCast(u32, imm) }, - // }); + // TODO + try self.asmRegisterImmediate( + mir_tag, + registerAlias(dst_reg, abi_size), + Immediate.u(@intCast(u32, imm)), + ); }, .memory, .linker_load, @@ -3645,36 +3637,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu }), registerAlias(src_reg, abi_size)); }, .immediate => |imm| { - _ = imm; - // const tag: Mir.Inst.Tag = switch (mir_tag) { - // .add => .add_mem_imm, - // .@"or" => .or_mem_imm, - // .@"and" => .and_mem_imm, - // .sub => .sub_mem_imm, - // .xor => .xor_mem_imm, - // .cmp => .cmp_mem_imm, - // else => unreachable, - // }; - const flags: u2 = switch (abi_size) { - 1 => 0b00, - 2 => 0b01, - 4 => 0b10, - 8 => 0b11, - else => unreachable, - }; - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -off, - // .operand = @intCast(u32, imm), - // }); - _ = flags; - // _ = try self.addInst(.{ - // .tag = tag, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = .rbp, - // .flags = flags, - // }), - // .data = .{ .payload = payload }, - // }); + // TODO + try self.asmMemoryImmediate(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ + .base = .rbp, + .disp = -off, + }), Immediate.u(@intCast(u32, imm))); }, .memory, .stack_offset, @@ -5258,33 +5225,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); }, .immediate => |imm| { - _ = imm; switch (abi_size) { - // TODO - // 1, 2, 4 => { - // // We have a positive stack offset value but we want a twos complement negative - // // offset from rbp, which is at the top of the stack frame. - // // mov [rbp+offset], immediate - // const flags: u2 = switch (abi_size) { - // 1 => 0b00, - // 2 => 0b01, - // 4 => 0b10, - // else => unreachable, - // }; - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -stack_offset, - // .operand = @intCast(u32, imm), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = .rsp, - // .flags = flags, - // }), - // .data = .{ .payload = payload }, - // }); - // }, - 1, 2, 4, 8 => { + 1, 2, 4 => { + // TODO + // We have a positive stack offset value but we want a twos complement negative + // offset from rbp, which is at the top of the stack frame. + // mov [rbp+offset], immediate + try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ + .base = .rsp, + .disp = -stack_offset, + }), Immediate.u(@intCast(u32, imm))); + }, + 8 => { const reg = try self.copyToTmpRegister(ty, mcv); return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); }, @@ -5355,7 +5307,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE } fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void { - const abi_size = ty.abiSize(self.target.*); + const abi_size = @intCast(u32, ty.abiSize(self.target.*)); switch (mcv) { .dead => unreachable, .unreach, .none => return, // Nothing to do. @@ -5400,75 +5352,33 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); }, .immediate => |x_big| { - _ = x_big; const base_reg = opts.dest_stack_base orelse .rbp; - _ = base_reg; + // TODO switch (abi_size) { 0 => { assert(ty.isError()); - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -stack_offset, - // .operand = @truncate(u32, x_big), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = base_reg, - // .flags = 0b00, - // }), - // .data = .{ .payload = payload }, - // }); + try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{ + .base = base_reg, + .disp = -stack_offset, + }), Immediate.u(@truncate(u32, x_big))); }, 1, 2, 4 => { - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -stack_offset, - // .operand = @truncate(u32, x_big), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = base_reg, - // .flags = switch (abi_size) { - // 1 => 0b00, - // 2 => 0b01, - // 4 => 0b10, - // else => unreachable, - // }, - // }), - // .data = .{ .payload = payload }, - // }); + try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ + .base = base_reg, + .disp = -stack_offset, + }), Immediate.u(@truncate(u32, x_big))); }, 8 => { // 64 bit write to memory would take two mov's anyways so we // insted just use two 32 bit writes to avoid register allocation - { - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -stack_offset + 4, - // .operand = @truncate(u32, x_big >> 32), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = base_reg, - // .flags = 0b10, - // }), - // .data = .{ .payload = payload }, - // }); - } - { - // const payload = try self.addExtra(Mir.ImmPair{ - // .dest_off = -stack_offset, - // .operand = @truncate(u32, x_big), - // }); - // _ = try self.addInst(.{ - // .tag = .mov_mem_imm, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = base_reg, - // .flags = 0b10, - // }), - // .data = .{ .payload = payload }, - // }); - } + try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ + .base = base_reg, + .disp = -stack_offset + 4, + }), Immediate.u(@truncate(u32, x_big >> 32))); + try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ + .base = base_reg, + .disp = -stack_offset, + }), Immediate.u(@truncate(u32, x_big))); }, else => { return self.fail("TODO implement set abi_size=large stack variable with immediate", .{}); @@ -5647,15 +5557,10 @@ fn genInlineMemcpy( try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); }, .ptr_stack_offset, .stack_offset => |off| { - _ = off; - // _ = try self.addInst(.{ - // .tag = .lea, - // .ops = Mir.Inst.Ops.encode(.{ - // .reg1 = src_addr_reg.to64(), - // .reg2 = opts.source_stack_base orelse .rbp, - // }), - // .data = .{ .disp = -off }, - // }); + try self.asmRegisterMemory(.lea, src_addr_reg.to64(), Memory.sib(.qword, .{ + .base = opts.source_stack_base orelse .rbp, + .disp = -off, + })); }, .register => |reg| { try self.asmRegisterRegister( diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index fc1e345a5a..218e1c6f55 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -221,6 +221,34 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data; operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) }; }, + .mi_u_sib => { + const msib = emit.mir.extraData(Mir.MemorySib, data.xi_u.payload).data; + operands[0..2].* = .{ + .{ .mem = Mir.MemorySib.decode(msib) }, + .{ .imm = Immediate.u(data.xi_u.imm) }, + }; + }, + .mi_s_sib => { + const msib = emit.mir.extraData(Mir.MemorySib, data.xi_s.payload).data; + operands[0..2].* = .{ + .{ .mem = Mir.MemorySib.decode(msib) }, + .{ .imm = Immediate.s(data.xi_s.imm) }, + }; + }, + .mi_u_rip => { + const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_u.payload).data; + operands[0..2].* = .{ + .{ .mem = Mir.MemoryRip.decode(mrip) }, + .{ .imm = Immediate.u(data.xi_u.imm) }, + }; + }, + .mi_s_rip => { + const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_s.payload).data; + operands[0..2].* = .{ + .{ .mem = Mir.MemoryRip.decode(mrip) }, + .{ .imm = Immediate.s(data.xi_s.imm) }, + }; + }, .rm_sib, .mr_sib => { const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data; const op1 = .{ .reg = data.rx.r1 }; |
