Commit 6315bcb32a
Changed files (3)
src
arch
x86_64
src/arch/x86_64/CodeGen.zig
@@ -17,7 +17,7 @@ const DW = std.dwarf;
const ErrorMsg = Module.ErrorMsg;
const FnResult = @import("../../codegen.zig").FnResult;
const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
-const Isel = @import("Isel.zig");
+const Emit = @import("Emit.zig");
const Liveness = @import("../../Liveness.zig");
const Mir = @import("Mir.zig");
const Module = @import("../../Module.zig");
@@ -309,7 +309,7 @@ pub fn generate(
};
defer mir.deinit(bin_file.allocator);
- var isel = Isel{
+ var emit = Emit{
.mir = mir,
.bin_file = bin_file,
.debug_output = debug_output,
@@ -320,9 +320,9 @@ pub fn generate(
.prev_di_line = module_fn.lbrace_line,
.prev_di_column = module_fn.lbrace_column,
};
- defer isel.deinit();
- isel.lowerMir() catch |err| switch (err) {
- error.IselFail => return FnResult{ .fail = isel.err_msg.? },
+ defer emit.deinit();
+ emit.lowerMir() catch |err| switch (err) {
+ error.EmitFail => return FnResult{ .fail = emit.err_msg.? },
else => |e| return e,
};
src/arch/x86_64/Isel.zig → src/arch/x86_64/Emit.zig
@@ -1,7 +1,7 @@
//! This file contains the functionality for lowering x86_64 MIR into
//! machine code
-const Isel = @This();
+const Emit = @This();
const std = @import("std");
const assert = std.debug.assert;
@@ -44,185 +44,183 @@ relocs: std.ArrayListUnmanaged(Reloc) = .{},
const InnerError = error{
OutOfMemory,
- Overflow,
- IselFail,
+ EmitFail,
};
const Reloc = struct {
/// Offset of the instruction.
- source: u64,
+ source: usize,
/// Target of the relocation.
target: Mir.Inst.Index,
/// Offset of the relocation within the instruction.
- offset: u64,
+ offset: usize,
/// Length of the instruction.
length: u5,
};
-pub fn lowerMir(isel: *Isel) InnerError!void {
- const mir_tags = isel.mir.instructions.items(.tag);
+pub fn lowerMir(emit: *Emit) InnerError!void {
+ const mir_tags = emit.mir.instructions.items(.tag);
for (mir_tags) |tag, index| {
const inst = @intCast(u32, index);
- try isel.code_offset_mapping.putNoClobber(isel.bin_file.allocator, inst, isel.code.items.len);
+ try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len);
switch (tag) {
- .adc => try isel.mirArith(.adc, inst),
- .add => try isel.mirArith(.add, inst),
- .sub => try isel.mirArith(.sub, inst),
- .xor => try isel.mirArith(.xor, inst),
- .@"and" => try isel.mirArith(.@"and", inst),
- .@"or" => try isel.mirArith(.@"or", inst),
- .sbb => try isel.mirArith(.sbb, inst),
- .cmp => try isel.mirArith(.cmp, inst),
- .mov => try isel.mirArith(.mov, inst),
-
- .adc_mem_imm => try isel.mirArithMemImm(.adc, inst),
- .add_mem_imm => try isel.mirArithMemImm(.add, inst),
- .sub_mem_imm => try isel.mirArithMemImm(.sub, inst),
- .xor_mem_imm => try isel.mirArithMemImm(.xor, inst),
- .and_mem_imm => try isel.mirArithMemImm(.@"and", inst),
- .or_mem_imm => try isel.mirArithMemImm(.@"or", inst),
- .sbb_mem_imm => try isel.mirArithMemImm(.sbb, inst),
- .cmp_mem_imm => try isel.mirArithMemImm(.cmp, inst),
- .mov_mem_imm => try isel.mirArithMemImm(.mov, inst),
-
- .adc_scale_src => try isel.mirArithScaleSrc(.adc, inst),
- .add_scale_src => try isel.mirArithScaleSrc(.add, inst),
- .sub_scale_src => try isel.mirArithScaleSrc(.sub, inst),
- .xor_scale_src => try isel.mirArithScaleSrc(.xor, inst),
- .and_scale_src => try isel.mirArithScaleSrc(.@"and", inst),
- .or_scale_src => try isel.mirArithScaleSrc(.@"or", inst),
- .sbb_scale_src => try isel.mirArithScaleSrc(.sbb, inst),
- .cmp_scale_src => try isel.mirArithScaleSrc(.cmp, inst),
- .mov_scale_src => try isel.mirArithScaleSrc(.mov, inst),
-
- .adc_scale_dst => try isel.mirArithScaleDst(.adc, inst),
- .add_scale_dst => try isel.mirArithScaleDst(.add, inst),
- .sub_scale_dst => try isel.mirArithScaleDst(.sub, inst),
- .xor_scale_dst => try isel.mirArithScaleDst(.xor, inst),
- .and_scale_dst => try isel.mirArithScaleDst(.@"and", inst),
- .or_scale_dst => try isel.mirArithScaleDst(.@"or", inst),
- .sbb_scale_dst => try isel.mirArithScaleDst(.sbb, inst),
- .cmp_scale_dst => try isel.mirArithScaleDst(.cmp, inst),
- .mov_scale_dst => try isel.mirArithScaleDst(.mov, inst),
-
- .adc_scale_imm => try isel.mirArithScaleImm(.adc, inst),
- .add_scale_imm => try isel.mirArithScaleImm(.add, inst),
- .sub_scale_imm => try isel.mirArithScaleImm(.sub, inst),
- .xor_scale_imm => try isel.mirArithScaleImm(.xor, inst),
- .and_scale_imm => try isel.mirArithScaleImm(.@"and", inst),
- .or_scale_imm => try isel.mirArithScaleImm(.@"or", inst),
- .sbb_scale_imm => try isel.mirArithScaleImm(.sbb, inst),
- .cmp_scale_imm => try isel.mirArithScaleImm(.cmp, inst),
- .mov_scale_imm => try isel.mirArithScaleImm(.mov, inst),
-
- .movabs => try isel.mirMovabs(inst),
-
- .lea => try isel.mirLea(inst),
-
- .imul_complex => try isel.mirIMulComplex(inst),
-
- .push => try isel.mirPushPop(.push, inst),
- .pop => try isel.mirPushPop(.pop, inst),
-
- .jmp => try isel.mirJmpCall(.jmp_near, inst),
- .call => try isel.mirJmpCall(.call_near, inst),
+ .adc => try emit.mirArith(.adc, inst),
+ .add => try emit.mirArith(.add, inst),
+ .sub => try emit.mirArith(.sub, inst),
+ .xor => try emit.mirArith(.xor, inst),
+ .@"and" => try emit.mirArith(.@"and", inst),
+ .@"or" => try emit.mirArith(.@"or", inst),
+ .sbb => try emit.mirArith(.sbb, inst),
+ .cmp => try emit.mirArith(.cmp, inst),
+ .mov => try emit.mirArith(.mov, inst),
+
+ .adc_mem_imm => try emit.mirArithMemImm(.adc, inst),
+ .add_mem_imm => try emit.mirArithMemImm(.add, inst),
+ .sub_mem_imm => try emit.mirArithMemImm(.sub, inst),
+ .xor_mem_imm => try emit.mirArithMemImm(.xor, inst),
+ .and_mem_imm => try emit.mirArithMemImm(.@"and", inst),
+ .or_mem_imm => try emit.mirArithMemImm(.@"or", inst),
+ .sbb_mem_imm => try emit.mirArithMemImm(.sbb, inst),
+ .cmp_mem_imm => try emit.mirArithMemImm(.cmp, inst),
+ .mov_mem_imm => try emit.mirArithMemImm(.mov, inst),
+
+ .adc_scale_src => try emit.mirArithScaleSrc(.adc, inst),
+ .add_scale_src => try emit.mirArithScaleSrc(.add, inst),
+ .sub_scale_src => try emit.mirArithScaleSrc(.sub, inst),
+ .xor_scale_src => try emit.mirArithScaleSrc(.xor, inst),
+ .and_scale_src => try emit.mirArithScaleSrc(.@"and", inst),
+ .or_scale_src => try emit.mirArithScaleSrc(.@"or", inst),
+ .sbb_scale_src => try emit.mirArithScaleSrc(.sbb, inst),
+ .cmp_scale_src => try emit.mirArithScaleSrc(.cmp, inst),
+ .mov_scale_src => try emit.mirArithScaleSrc(.mov, inst),
+
+ .adc_scale_dst => try emit.mirArithScaleDst(.adc, inst),
+ .add_scale_dst => try emit.mirArithScaleDst(.add, inst),
+ .sub_scale_dst => try emit.mirArithScaleDst(.sub, inst),
+ .xor_scale_dst => try emit.mirArithScaleDst(.xor, inst),
+ .and_scale_dst => try emit.mirArithScaleDst(.@"and", inst),
+ .or_scale_dst => try emit.mirArithScaleDst(.@"or", inst),
+ .sbb_scale_dst => try emit.mirArithScaleDst(.sbb, inst),
+ .cmp_scale_dst => try emit.mirArithScaleDst(.cmp, inst),
+ .mov_scale_dst => try emit.mirArithScaleDst(.mov, inst),
+
+ .adc_scale_imm => try emit.mirArithScaleImm(.adc, inst),
+ .add_scale_imm => try emit.mirArithScaleImm(.add, inst),
+ .sub_scale_imm => try emit.mirArithScaleImm(.sub, inst),
+ .xor_scale_imm => try emit.mirArithScaleImm(.xor, inst),
+ .and_scale_imm => try emit.mirArithScaleImm(.@"and", inst),
+ .or_scale_imm => try emit.mirArithScaleImm(.@"or", inst),
+ .sbb_scale_imm => try emit.mirArithScaleImm(.sbb, inst),
+ .cmp_scale_imm => try emit.mirArithScaleImm(.cmp, inst),
+ .mov_scale_imm => try emit.mirArithScaleImm(.mov, inst),
+
+ .movabs => try emit.mirMovabs(inst),
+
+ .lea => try emit.mirLea(inst),
+
+ .imul_complex => try emit.mirIMulComplex(inst),
+
+ .push => try emit.mirPushPop(.push, inst),
+ .pop => try emit.mirPushPop(.pop, inst),
+
+ .jmp => try emit.mirJmpCall(.jmp_near, inst),
+ .call => try emit.mirJmpCall(.call_near, inst),
.cond_jmp_greater_less,
.cond_jmp_above_below,
.cond_jmp_eq_ne,
- => try isel.mirCondJmp(tag, inst),
+ => try emit.mirCondJmp(tag, inst),
.cond_set_byte_greater_less,
.cond_set_byte_above_below,
.cond_set_byte_eq_ne,
- => try isel.mirCondSetByte(tag, inst),
+ => try emit.mirCondSetByte(tag, inst),
- .ret => try isel.mirRet(inst),
+ .ret => try emit.mirRet(inst),
- .syscall => try isel.mirSyscall(),
+ .syscall => try emit.mirSyscall(),
- .@"test" => try isel.mirTest(inst),
+ .@"test" => try emit.mirTest(inst),
- .brk => try isel.mirBrk(),
- .nop => try isel.mirNop(),
+ .brk => try emit.mirBrk(),
+ .nop => try emit.mirNop(),
- .call_extern => try isel.mirCallExtern(inst),
+ .call_extern => try emit.mirCallExtern(inst),
- .dbg_line => try isel.mirDbgLine(inst),
- .dbg_prologue_end => try isel.mirDbgPrologueEnd(inst),
- .dbg_epilogue_begin => try isel.mirDbgEpilogueBegin(inst),
- .arg_dbg_info => try isel.mirArgDbgInfo(inst),
+ .dbg_line => try emit.mirDbgLine(inst),
+ .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst),
+ .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst),
+ .arg_dbg_info => try emit.mirArgDbgInfo(inst),
- .push_regs_from_callee_preserved_regs => try isel.mirPushPopRegsFromCalleePreservedRegs(.push, inst),
- .pop_regs_from_callee_preserved_regs => try isel.mirPushPopRegsFromCalleePreservedRegs(.pop, inst),
+ .push_regs_from_callee_preserved_regs => try emit.mirPushPopRegsFromCalleePreservedRegs(.push, inst),
+ .pop_regs_from_callee_preserved_regs => try emit.mirPushPopRegsFromCalleePreservedRegs(.pop, inst),
else => {
- return isel.fail("Implement MIR->Isel lowering for x86_64 for pseudo-inst: {s}", .{tag});
+ return emit.fail("Implement MIR->Emit lowering for x86_64 for pseudo-inst: {s}", .{tag});
},
}
}
- try isel.fixupRelocs();
+ try emit.fixupRelocs();
}
-pub fn deinit(isel: *Isel) void {
- isel.relocs.deinit(isel.bin_file.allocator);
- isel.code_offset_mapping.deinit(isel.bin_file.allocator);
- isel.* = undefined;
+pub fn deinit(emit: *Emit) void {
+ emit.relocs.deinit(emit.bin_file.allocator);
+ emit.code_offset_mapping.deinit(emit.bin_file.allocator);
+ emit.* = undefined;
}
-fn fail(isel: *Isel, comptime format: []const u8, args: anytype) InnerError {
+fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
@setCold(true);
- assert(isel.err_msg == null);
- isel.err_msg = try ErrorMsg.create(isel.bin_file.allocator, isel.src_loc, format, args);
- return error.IselFail;
+ assert(emit.err_msg == null);
+ emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args);
+ return error.EmitFail;
}
-fn failWithLoweringError(isel: *Isel, err: LoweringError) InnerError {
+fn failWithLoweringError(emit: *Emit, err: LoweringError) InnerError {
return switch (err) {
- error.RaxOperandExpected => isel.fail("Register.rax expected as destination operand", .{}),
- error.OperandSizeMismatch => isel.fail("operand size mismatch", .{}),
+ error.RaxOperandExpected => emit.fail("Register.rax expected as destination operand", .{}),
+ error.OperandSizeMismatch => emit.fail("operand size mismatch", .{}),
else => |e| e,
};
}
-fn fixupRelocs(isel: *Isel) InnerError!void {
+fn fixupRelocs(emit: *Emit) InnerError!void {
// TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.
// This should be reversed like it is done in aarch64 MIR emit code: start with the smallest
// possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution
// until the entire decl is correctly emitted with all JMP/CALL instructions within range.
- for (isel.relocs.items) |reloc| {
- const offset = try math.cast(usize, reloc.offset);
- const target = isel.code_offset_mapping.get(reloc.target) orelse
- return isel.fail("JMP/CALL relocation target not found!", .{});
+ for (emit.relocs.items) |reloc| {
+ const target = emit.code_offset_mapping.get(reloc.target) orelse
+ return emit.fail("JMP/CALL relocation target not found!", .{});
const disp = @intCast(i32, @intCast(i64, target) - @intCast(i64, reloc.source + reloc.length));
- mem.writeIntLittle(i32, isel.code.items[offset..][0..4], disp);
+ mem.writeIntLittle(i32, emit.code.items[reloc.offset..][0..4], disp);
}
}
-fn mirBrk(isel: *Isel) InnerError!void {
- return lowerToZoEnc(.brk, isel.code) catch |err| isel.failWithLoweringError(err);
+fn mirBrk(emit: *Emit) InnerError!void {
+ return lowerToZoEnc(.brk, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirNop(isel: *Isel) InnerError!void {
- return lowerToZoEnc(.nop, isel.code) catch |err| isel.failWithLoweringError(err);
+fn mirNop(emit: *Emit) InnerError!void {
+ return lowerToZoEnc(.nop, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirSyscall(isel: *Isel) InnerError!void {
- return lowerToZoEnc(.syscall, isel.code) catch |err| isel.failWithLoweringError(err);
+fn mirSyscall(emit: *Emit) InnerError!void {
+ return lowerToZoEnc(.syscall, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirPushPop(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirPushPop(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
// PUSH/POP reg
- return lowerToOEnc(tag, ops.reg1, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToOEnc(tag, ops.reg1, emit.code) catch |err| emit.failWithLoweringError(err);
},
0b01 => {
// PUSH/POP r/m64
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const ptr_size: Memory.PtrSize = switch (immOpSize(imm)) {
16 => .word_ptr,
else => .qword_ptr,
@@ -230,26 +228,26 @@ fn mirPushPop(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
return lowerToMEnc(tag, RegisterOrMemory.mem(ptr_size, .{
.disp = imm,
.base = ops.reg1,
- }), isel.code) catch |err| isel.failWithLoweringError(err);
+ }), emit.code) catch |err| emit.failWithLoweringError(err);
},
0b10 => {
// PUSH imm32
assert(tag == .push);
- const imm = isel.mir.instructions.items(.data)[inst].imm;
- return lowerToIEnc(.push, imm, isel.code) catch |err|
- isel.failWithLoweringError(err);
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
+ return lowerToIEnc(.push, imm, emit.code) catch |err|
+ emit.failWithLoweringError(err);
},
0b11 => unreachable,
}
}
-fn mirPushPopRegsFromCalleePreservedRegs(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+fn mirPushPopRegsFromCalleePreservedRegs(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
const callee_preserved_regs = bits.callee_preserved_regs;
- const regs = isel.mir.instructions.items(.data)[inst].regs_to_push_or_pop;
+ const regs = emit.mir.instructions.items(.data)[inst].regs_to_push_or_pop;
if (tag == .push) {
for (callee_preserved_regs) |reg, i| {
if ((regs >> @intCast(u5, i)) & 1 == 0) continue;
- lowerToOEnc(.push, reg, isel.code) catch |err|
- return isel.failWithLoweringError(err);
+ lowerToOEnc(.push, reg, emit.code) catch |err|
+ return emit.failWithLoweringError(err);
}
} else {
// pop in the reverse direction
@@ -257,56 +255,56 @@ fn mirPushPopRegsFromCalleePreservedRegs(isel: *Isel, tag: Tag, inst: Mir.Inst.I
while (i > 0) : (i -= 1) {
const reg = callee_preserved_regs[i - 1];
if ((regs >> @intCast(u5, i - 1)) & 1 == 0) continue;
- lowerToOEnc(.pop, reg, isel.code) catch |err|
- return isel.failWithLoweringError(err);
+ lowerToOEnc(.pop, reg, emit.code) catch |err|
+ return emit.failWithLoweringError(err);
}
}
}
-fn mirJmpCall(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirJmpCall(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
- const target = isel.mir.instructions.items(.data)[inst].inst;
- const source = isel.code.items.len;
- lowerToDEnc(tag, 0, isel.code) catch |err|
- return isel.failWithLoweringError(err);
- try isel.relocs.append(isel.bin_file.allocator, .{
+ const target = emit.mir.instructions.items(.data)[inst].inst;
+ const source = emit.code.items.len;
+ lowerToDEnc(tag, 0, emit.code) catch |err|
+ return emit.failWithLoweringError(err);
+ try emit.relocs.append(emit.bin_file.allocator, .{
.source = source,
.target = target,
- .offset = isel.code.items.len - 4,
+ .offset = emit.code.items.len - 4,
.length = 5,
});
},
0b01 => {
if (ops.reg1 == .none) {
// JMP/CALL [imm]
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const ptr_size: Memory.PtrSize = switch (immOpSize(imm)) {
16 => .word_ptr,
else => .qword_ptr,
};
- return lowerToMEnc(tag, RegisterOrMemory.mem(ptr_size, .{ .disp = imm }), isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToMEnc(tag, RegisterOrMemory.mem(ptr_size, .{ .disp = imm }), emit.code) catch |err|
+ emit.failWithLoweringError(err);
}
// JMP/CALL reg
- return lowerToMEnc(tag, RegisterOrMemory.reg(ops.reg1), isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToMEnc(tag, RegisterOrMemory.reg(ops.reg1), emit.code) catch |err| emit.failWithLoweringError(err);
},
0b10 => {
// JMP/CALL r/m64
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
return lowerToMEnc(tag, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg1.size()), .{
.disp = imm,
.base = ops.reg1,
- }), isel.code) catch |err| isel.failWithLoweringError(err);
+ }), emit.code) catch |err| emit.failWithLoweringError(err);
},
- 0b11 => return isel.fail("TODO unused JMP/CALL variant 0b11", .{}),
+ 0b11 => return emit.fail("TODO unused JMP/CALL variant 0b11", .{}),
}
}
-fn mirCondJmp(isel: *Isel, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
- const target = isel.mir.instructions.items(.data)[inst].inst;
+fn mirCondJmp(emit: *Emit, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
+ const target = emit.mir.instructions.items(.data)[inst].inst;
const tag = switch (mir_tag) {
.cond_jmp_greater_less => switch (ops.flags) {
0b00 => Tag.jge,
@@ -326,19 +324,19 @@ fn mirCondJmp(isel: *Isel, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerErr
},
else => unreachable,
};
- const source = isel.code.items.len;
- lowerToDEnc(tag, 0, isel.code) catch |err|
- return isel.failWithLoweringError(err);
- try isel.relocs.append(isel.bin_file.allocator, .{
+ const source = emit.code.items.len;
+ lowerToDEnc(tag, 0, emit.code) catch |err|
+ return emit.failWithLoweringError(err);
+ try emit.relocs.append(emit.bin_file.allocator, .{
.source = source,
.target = target,
- .offset = isel.code.items.len - 4,
+ .offset = emit.code.items.len - 4,
.length = 6,
});
}
-fn mirCondSetByte(isel: *Isel, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirCondSetByte(emit: *Emit, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
const tag = switch (mir_tag) {
.cond_set_byte_greater_less => switch (ops.flags) {
0b00 => Tag.setge,
@@ -358,111 +356,111 @@ fn mirCondSetByte(isel: *Isel, mir_tag: Mir.Inst.Tag, inst: Mir.Inst.Index) Inne
},
else => unreachable,
};
- return lowerToMEnc(tag, RegisterOrMemory.reg(ops.reg1.to8()), isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToMEnc(tag, RegisterOrMemory.reg(ops.reg1.to8()), emit.code) catch |err|
+ emit.failWithLoweringError(err);
}
-fn mirTest(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirTest(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .@"test");
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
if (ops.reg2 == .none) {
// TEST r/m64, imm32
// MI
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
if (ops.reg1.to64() == .rax) {
// TEST rax, imm32
// I
- return lowerToIEnc(.@"test", imm, isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToIEnc(.@"test", imm, emit.code) catch |err|
+ emit.failWithLoweringError(err);
}
- return lowerToMiEnc(.@"test", RegisterOrMemory.reg(ops.reg1), imm, isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToMiEnc(.@"test", RegisterOrMemory.reg(ops.reg1), imm, emit.code) catch |err|
+ emit.failWithLoweringError(err);
}
// TEST r/m64, r64
- return isel.fail("TODO TEST r/m64, r64", .{});
+ return emit.fail("TODO TEST r/m64, r64", .{});
},
- else => return isel.fail("TODO more TEST alternatives", .{}),
+ else => return emit.fail("TODO more TEST alternatives", .{}),
}
}
-fn mirRet(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirRet(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .ret);
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
// RETF imm16
// I
- const imm = isel.mir.instructions.items(.data)[inst].imm;
- return lowerToIEnc(.ret_far, imm, isel.code) catch |err| isel.failWithLoweringError(err);
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
+ return lowerToIEnc(.ret_far, imm, emit.code) catch |err| emit.failWithLoweringError(err);
},
0b01 => {
- return lowerToZoEnc(.ret_far, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToZoEnc(.ret_far, emit.code) catch |err| emit.failWithLoweringError(err);
},
0b10 => {
// RET imm16
// I
- const imm = isel.mir.instructions.items(.data)[inst].imm;
- return lowerToIEnc(.ret_near, imm, isel.code) catch |err| isel.failWithLoweringError(err);
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
+ return lowerToIEnc(.ret_near, imm, emit.code) catch |err| emit.failWithLoweringError(err);
},
0b11 => {
- return lowerToZoEnc(.ret_near, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToZoEnc(.ret_near, emit.code) catch |err| emit.failWithLoweringError(err);
},
}
}
-fn mirArith(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirArith(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
if (ops.reg2 == .none) {
// mov reg1, imm32
// MI
- const imm = isel.mir.instructions.items(.data)[inst].imm;
- return lowerToMiEnc(tag, RegisterOrMemory.reg(ops.reg1), imm, isel.code) catch |err|
- isel.failWithLoweringError(err);
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
+ return lowerToMiEnc(tag, RegisterOrMemory.reg(ops.reg1), imm, emit.code) catch |err|
+ emit.failWithLoweringError(err);
}
// mov reg1, reg2
// RM
- return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.reg(ops.reg2), isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.reg(ops.reg2), emit.code) catch |err|
+ emit.failWithLoweringError(err);
},
0b01 => {
// mov reg1, [reg2 + imm32]
// RM
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const src_reg: ?Register = if (ops.reg2 == .none) null else ops.reg2;
return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg1.size()), .{
.disp = imm,
.base = src_reg,
- }), isel.code) catch |err| isel.failWithLoweringError(err);
+ }), emit.code) catch |err| emit.failWithLoweringError(err);
},
0b10 => {
if (ops.reg2 == .none) {
- return isel.fail("TODO unused variant: mov reg1, none, 0b10", .{});
+ return emit.fail("TODO unused variant: mov reg1, none, 0b10", .{});
}
// mov [reg1 + imm32], reg2
// MR
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
return lowerToMrEnc(tag, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg2.size()), .{
.disp = imm,
.base = ops.reg1,
- }), ops.reg2, isel.code) catch |err| isel.failWithLoweringError(err);
+ }), ops.reg2, emit.code) catch |err| emit.failWithLoweringError(err);
},
0b11 => {
- return isel.fail("TODO unused variant: mov reg1, reg2, 0b11", .{});
+ return emit.fail("TODO unused variant: mov reg1, reg2, 0b11", .{});
},
}
}
-fn mirArithMemImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirArithMemImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
assert(ops.reg2 == .none);
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const imm_pair = isel.mir.extraData(Mir.ImmPair, payload).data;
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const imm_pair = emit.mir.extraData(Mir.ImmPair, payload).data;
const ptr_size: Memory.PtrSize = switch (ops.flags) {
0b00 => .byte_ptr,
0b01 => .word_ptr,
@@ -472,7 +470,7 @@ fn mirArithMemImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
return lowerToMiEnc(tag, RegisterOrMemory.mem(ptr_size, .{
.disp = imm_pair.dest_off,
.base = ops.reg1,
- }), imm_pair.operand, isel.code) catch |err| isel.failWithLoweringError(err);
+ }), imm_pair.operand, emit.code) catch |err| emit.failWithLoweringError(err);
}
inline fn setRexWRegister(reg: Register) bool {
@@ -508,10 +506,10 @@ inline fn imm64OpSize(u_imm: u64) u8 {
return 64;
}
-fn mirArithScaleSrc(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirArithScaleSrc(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
const scale = ops.flags;
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
// OP reg1, [reg2 + scale*rcx + imm32]
const scale_index = ScaleIndex{
.scale = scale,
@@ -521,13 +519,13 @@ fn mirArithScaleSrc(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
.disp = imm,
.base = ops.reg2,
.scale_index = scale_index,
- }), isel.code) catch |err| isel.failWithLoweringError(err);
+ }), emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirArithScaleDst(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirArithScaleDst(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
const scale = ops.flags;
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const scale_index = ScaleIndex{
.scale = scale,
.index = .rax,
@@ -538,21 +536,21 @@ fn mirArithScaleDst(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
.disp = 0,
.base = ops.reg1,
.scale_index = scale_index,
- }), imm, isel.code) catch |err| isel.failWithLoweringError(err);
+ }), imm, emit.code) catch |err| emit.failWithLoweringError(err);
}
// OP [reg1 + scale*rax + imm32], reg2
return lowerToMrEnc(tag, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg2.size()), .{
.disp = imm,
.base = ops.reg1,
.scale_index = scale_index,
- }), ops.reg2, isel.code) catch |err| isel.failWithLoweringError(err);
+ }), ops.reg2, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirArithScaleImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+fn mirArithScaleImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
const scale = ops.flags;
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const imm_pair = isel.mir.extraData(Mir.ImmPair, payload).data;
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const imm_pair = emit.mir.extraData(Mir.ImmPair, payload).data;
const scale_index = ScaleIndex{
.scale = scale,
.index = .rax,
@@ -562,60 +560,60 @@ fn mirArithScaleImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
.disp = imm_pair.dest_off,
.base = ops.reg1,
.scale_index = scale_index,
- }), imm_pair.operand, isel.code) catch |err| isel.failWithLoweringError(err);
+ }), imm_pair.operand, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirMovabs(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirMovabs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .movabs);
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
const imm: u64 = if (ops.reg1.size() == 64) blk: {
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const imm = isel.mir.extraData(Mir.Imm64, payload).data;
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const imm = emit.mir.extraData(Mir.Imm64, payload).data;
break :blk imm.decode();
- } else isel.mir.instructions.items(.data)[inst].imm;
+ } else emit.mir.instructions.items(.data)[inst].imm;
if (ops.flags == 0b00) {
// movabs reg, imm64
// OI
- return lowerToOiEnc(.mov, ops.reg1, imm, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToOiEnc(.mov, ops.reg1, imm, emit.code) catch |err| emit.failWithLoweringError(err);
}
if (ops.reg1 == .none) {
// movabs moffs64, rax
// TD
- return lowerToTdEnc(.mov, imm, ops.reg2, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToTdEnc(.mov, imm, ops.reg2, emit.code) catch |err| emit.failWithLoweringError(err);
}
// movabs rax, moffs64
// FD
- return lowerToFdEnc(.mov, ops.reg1, imm, isel.code) catch |err| isel.failWithLoweringError(err);
+ return lowerToFdEnc(.mov, ops.reg1, imm, emit.code) catch |err| emit.failWithLoweringError(err);
}
-fn mirIMulComplex(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirIMulComplex(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .imul_complex);
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
- return lowerToRmEnc(.imul, ops.reg1, RegisterOrMemory.reg(ops.reg2), isel.code) catch |err|
- isel.failWithLoweringError(err);
+ return lowerToRmEnc(.imul, ops.reg1, RegisterOrMemory.reg(ops.reg2), emit.code) catch |err|
+ emit.failWithLoweringError(err);
},
0b10 => {
- const imm = isel.mir.instructions.items(.data)[inst].imm;
- return lowerToRmiEnc(.imul, ops.reg1, RegisterOrMemory.reg(ops.reg2), imm, isel.code) catch |err|
- isel.failWithLoweringError(err);
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
+ return lowerToRmiEnc(.imul, ops.reg1, RegisterOrMemory.reg(ops.reg2), imm, emit.code) catch |err|
+ emit.failWithLoweringError(err);
},
- else => return isel.fail("TODO implement imul", .{}),
+ else => return emit.fail("TODO implement imul", .{}),
}
}
-fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .lea);
- const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
+ const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
switch (ops.flags) {
0b00 => {
// lea reg1, [reg2 + imm32]
// RM
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const src_reg: ?Register = if (ops.reg2 == .none) null else ops.reg2;
return lowerToRmEnc(
.lea,
@@ -624,25 +622,25 @@ fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
.disp = imm,
.base = src_reg,
}),
- isel.code,
- ) catch |err| isel.failWithLoweringError(err);
+ emit.code,
+ ) catch |err| emit.failWithLoweringError(err);
},
0b01 => {
// lea reg1, [rip + imm32]
// RM
- const start_offset = isel.code.items.len;
+ const start_offset = emit.code.items.len;
lowerToRmEnc(
.lea,
ops.reg1,
RegisterOrMemory.rip(Memory.PtrSize.fromBits(ops.reg1.size()), 0),
- isel.code,
- ) catch |err| return isel.failWithLoweringError(err);
- const end_offset = isel.code.items.len;
+ emit.code,
+ ) catch |err| return emit.failWithLoweringError(err);
+ const end_offset = emit.code.items.len;
// Backpatch the displacement
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const imm = isel.mir.extraData(Mir.Imm64, payload).data.decode();
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const imm = emit.mir.extraData(Mir.Imm64, payload).data.decode();
const disp = @intCast(i32, @intCast(i64, imm) - @intCast(i64, end_offset - start_offset));
- mem.writeIntLittle(i32, isel.code.items[end_offset - 4 ..][0..4], disp);
+ mem.writeIntLittle(i32, emit.code.items[end_offset - 4 ..][0..4], disp);
},
0b10 => {
// lea reg1, [rip + reloc]
@@ -651,14 +649,14 @@ fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
.lea,
ops.reg1,
RegisterOrMemory.rip(Memory.PtrSize.fromBits(ops.reg1.size()), 0),
- isel.code,
- ) catch |err| return isel.failWithLoweringError(err);
- const end_offset = isel.code.items.len;
- const got_entry = isel.mir.instructions.items(.data)[inst].got_entry;
- if (isel.bin_file.cast(link.File.MachO)) |macho_file| {
+ emit.code,
+ ) catch |err| return emit.failWithLoweringError(err);
+ const end_offset = emit.code.items.len;
+ const got_entry = emit.mir.instructions.items(.data)[inst].got_entry;
+ if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
// TODO I think the reloc might be in the wrong place.
const decl = macho_file.active_decl.?;
- try decl.link.macho.relocs.append(isel.bin_file.allocator, .{
+ try decl.link.macho.relocs.append(emit.bin_file.allocator, .{
.offset = @intCast(u32, end_offset - 4),
.target = .{ .local = got_entry },
.addend = 0,
@@ -668,7 +666,7 @@ fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
.@"type" = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
});
} else {
- return isel.fail(
+ return emit.fail(
"TODO implement lea reg, [rip + reloc] for linking backends different than MachO",
.{},
);
@@ -676,7 +674,7 @@ fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
},
0b11 => {
// lea reg, [rbp + rcx + imm32]
- const imm = isel.mir.instructions.items(.data)[inst].imm;
+ const imm = emit.mir.instructions.items(.data)[inst].imm;
const src_reg: ?Register = if (ops.reg2 == .none) null else ops.reg2;
const scale_index = ScaleIndex{
.scale = 0,
@@ -690,25 +688,25 @@ fn mirLea(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
.base = src_reg,
.scale_index = scale_index,
}),
- isel.code,
- ) catch |err| isel.failWithLoweringError(err);
+ emit.code,
+ ) catch |err| emit.failWithLoweringError(err);
},
}
}
-fn mirCallExtern(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .call_extern);
- const n_strx = isel.mir.instructions.items(.data)[inst].extern_fn;
+ const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn;
const offset = blk: {
// callq
- lowerToDEnc(.call_near, 0, isel.code) catch |err|
- return isel.failWithLoweringError(err);
- break :blk @intCast(u32, isel.code.items.len) - 4;
+ lowerToDEnc(.call_near, 0, emit.code) catch |err|
+ return emit.failWithLoweringError(err);
+ break :blk @intCast(u32, emit.code.items.len) - 4;
};
- if (isel.bin_file.cast(link.File.MachO)) |macho_file| {
+ if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
// Add relocation to the decl.
- try macho_file.active_decl.?.link.macho.relocs.append(isel.bin_file.allocator, .{
+ try macho_file.active_decl.?.link.macho.relocs.append(emit.bin_file.allocator, .{
.offset = offset,
.target = .{ .global = n_strx },
.addend = 0,
@@ -718,22 +716,22 @@ fn mirCallExtern(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
.@"type" = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
});
} else {
- return isel.fail("TODO implement call_extern for linking backends different than MachO", .{});
+ return emit.fail("TODO implement call_extern for linking backends different than MachO", .{});
}
}
-fn mirDbgLine(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .dbg_line);
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const dbg_line_column = isel.mir.extraData(Mir.DbgLineColumn, payload).data;
- try isel.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const dbg_line_column = emit.mir.extraData(Mir.DbgLineColumn, payload).data;
+ try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
}
-fn dbgAdvancePCAndLine(isel: *Isel, line: u32, column: u32) InnerError!void {
- const delta_line = @intCast(i32, line) - @intCast(i32, isel.prev_di_line);
- const delta_pc: usize = isel.code.items.len - isel.prev_di_pc;
- switch (isel.debug_output) {
+fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
+ const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line);
+ const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
+ switch (emit.debug_output) {
.dwarf => |dbg_out| {
// TODO Look into using the DWARF special opcodes to compress this data.
// It lets you emit single-byte opcodes that add different numbers to
@@ -746,15 +744,15 @@ fn dbgAdvancePCAndLine(isel: *Isel, line: u32, column: u32) InnerError!void {
leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
}
dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
- isel.prev_di_pc = isel.code.items.len;
- isel.prev_di_line = line;
- isel.prev_di_column = column;
- isel.prev_di_pc = isel.code.items.len;
+ emit.prev_di_pc = emit.code.items.len;
+ emit.prev_di_line = line;
+ emit.prev_di_column = column;
+ emit.prev_di_pc = emit.code.items.len;
},
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// we have already checked the target in the linker to make sure it is compatable
- const quant = @import("../../link/Plan9/aout.zig").getPCQuant(isel.target.cpu.arch) catch unreachable;
+ const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.target.cpu.arch) catch unreachable;
// increasing the line number
try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
@@ -779,62 +777,62 @@ fn dbgAdvancePCAndLine(isel: *Isel, line: u32, column: u32) InnerError!void {
// we don't need to do anything, because adding the quant does it for us
} else unreachable;
if (dbg_out.start_line.* == null)
- dbg_out.start_line.* = isel.prev_di_line;
+ dbg_out.start_line.* = emit.prev_di_line;
dbg_out.end_line.* = line;
// only do this if the pc changed
- isel.prev_di_line = line;
- isel.prev_di_column = column;
- isel.prev_di_pc = isel.code.items.len;
+ emit.prev_di_line = line;
+ emit.prev_di_column = column;
+ emit.prev_di_pc = emit.code.items.len;
},
.none => {},
}
}
-fn mirDbgPrologueEnd(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .dbg_prologue_end);
- switch (isel.debug_output) {
+ switch (emit.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
- try isel.dbgAdvancePCAndLine(isel.prev_di_line, isel.prev_di_column);
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
.plan9 => {},
.none => {},
}
}
-fn mirDbgEpilogueBegin(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .dbg_epilogue_begin);
- switch (isel.debug_output) {
+ switch (emit.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
- try isel.dbgAdvancePCAndLine(isel.prev_di_line, isel.prev_di_column);
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
},
.plan9 => {},
.none => {},
}
}
-fn mirArgDbgInfo(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
- const tag = isel.mir.instructions.items(.tag)[inst];
+fn mirArgDbgInfo(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
assert(tag == .arg_dbg_info);
- const payload = isel.mir.instructions.items(.data)[inst].payload;
- const arg_dbg_info = isel.mir.extraData(Mir.ArgDbgInfo, payload).data;
- const mcv = isel.mir.function.args[arg_dbg_info.arg_index];
- try isel.genArgDbgInfo(arg_dbg_info.air_inst, mcv);
+ const payload = emit.mir.instructions.items(.data)[inst].payload;
+ const arg_dbg_info = emit.mir.extraData(Mir.ArgDbgInfo, payload).data;
+ const mcv = emit.mir.function.args[arg_dbg_info.arg_index];
+ try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv);
}
-fn genArgDbgInfo(isel: *Isel, inst: Air.Inst.Index, mcv: MCValue) !void {
- const ty_str = isel.mir.function.air.instructions.items(.data)[inst].ty_str;
- const zir = &isel.mir.function.mod_fn.owner_decl.getFileScope().zir;
+fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue) !void {
+ const ty_str = emit.mir.function.air.instructions.items(.data)[inst].ty_str;
+ const zir = &emit.mir.function.mod_fn.owner_decl.getFileScope().zir;
const name = zir.nullTerminatedString(ty_str.str);
const name_with_null = name.ptr[0 .. name.len + 1];
- const ty = isel.mir.function.air.getRefType(ty_str.ty);
+ const ty = emit.mir.function.air.getRefType(ty_str.ty);
switch (mcv) {
.register => |reg| {
- switch (isel.debug_output) {
+ switch (emit.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_info.ensureUnusedCapacity(3);
dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
@@ -843,7 +841,7 @@ fn genArgDbgInfo(isel: *Isel, inst: Air.Inst.Index, mcv: MCValue) !void {
reg.dwarfLocOp(),
});
try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
- try isel.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
+ try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
},
.plan9 => {},
@@ -851,7 +849,7 @@ fn genArgDbgInfo(isel: *Isel, inst: Air.Inst.Index, mcv: MCValue) !void {
}
},
.stack_offset => {
- switch (isel.debug_output) {
+ switch (emit.debug_output) {
.dwarf => {},
.plan9 => {},
.none => {},
@@ -863,21 +861,21 @@ fn genArgDbgInfo(isel: *Isel, inst: Air.Inst.Index, mcv: MCValue) !void {
/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
/// after codegen for this symbol is done.
-fn addDbgInfoTypeReloc(isel: *Isel, ty: Type) !void {
- switch (isel.debug_output) {
+fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
+ switch (emit.debug_output) {
.dwarf => |dbg_out| {
assert(ty.hasCodeGenBits());
const index = dbg_out.dbg_info.items.len;
try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
- const gop = try dbg_out.dbg_info_type_relocs.getOrPut(isel.bin_file.allocator, ty);
+ const gop = try dbg_out.dbg_info_type_relocs.getOrPut(emit.bin_file.allocator, ty);
if (!gop.found_existing) {
gop.value_ptr.* = .{
.off = undefined,
.relocs = .{},
};
}
- try gop.value_ptr.relocs.append(isel.bin_file.allocator, @intCast(u32, index));
+ try gop.value_ptr.relocs.append(emit.bin_file.allocator, @intCast(u32, index));
},
.plan9 => {},
.none => {},
@@ -1375,7 +1373,6 @@ const RegisterOrMemory = union(enum) {
const LoweringError = error{
OutOfMemory,
- Overflow,
OperandSizeMismatch,
RaxOperandExpected,
};
@@ -1759,150 +1756,150 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []co
return error.TestFailed;
}
-const TestIsel = struct {
+const TestEmit = struct {
code_buffer: std.ArrayList(u8),
next: usize = 0,
- fn init() TestIsel {
+ fn init() TestEmit {
return .{
.code_buffer = std.ArrayList(u8).init(testing.allocator),
};
}
- fn deinit(isel: *TestIsel) void {
- isel.code_buffer.deinit();
- isel.next = undefined;
+ fn deinit(emit: *TestEmit) void {
+ emit.code_buffer.deinit();
+ emit.next = undefined;
}
- fn code(isel: *TestIsel) *std.ArrayList(u8) {
- isel.next = isel.code_buffer.items.len;
- return &isel.code_buffer;
+ fn code(emit: *TestEmit) *std.ArrayList(u8) {
+ emit.next = emit.code_buffer.items.len;
+ return &emit.code_buffer;
}
- fn lowered(isel: TestIsel) []const u8 {
- return isel.code_buffer.items[isel.next..];
+ fn lowered(emit: TestEmit) []const u8 {
+ return emit.code_buffer.items[emit.next..];
}
};
test "lower MI encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToMiEnc(.mov, RegisterOrMemory.reg(.rax), 0x10, isel.code());
- try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", isel.lowered(), "mov rax, 0x10");
- try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, isel.code());
- try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", isel.lowered(), "mov dword ptr [r11 + 0], 0x10");
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToMiEnc(.mov, RegisterOrMemory.reg(.rax), 0x10, emit.code());
+ try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", emit.lowered(), "mov rax, 0x10");
+ try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, emit.code());
+ try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", emit.lowered(), "mov dword ptr [r11 + 0], 0x10");
try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{
.disp = @bitCast(u32, @as(i32, -8)),
.base = .rdx,
- }), 0x10, isel.code());
- try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", isel.lowered(), "add dword ptr [rdx - 8], 0x10");
+ }), 0x10, emit.code());
+ try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", emit.lowered(), "add dword ptr [rdx - 8], 0x10");
try lowerToMiEnc(.sub, RegisterOrMemory.mem(.dword_ptr, .{
.disp = 0x10000000,
.base = .r11,
- }), 0x10, isel.code());
+ }), 0x10, emit.code());
try expectEqualHexStrings(
"\x41\x81\xab\x00\x00\x00\x10\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"sub dword ptr [r11 + 0x10000000], 0x10",
);
- try lowerToMiEnc(.@"and", RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0x10000000 }), 0x10, isel.code());
+ try lowerToMiEnc(.@"and", RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0x10000000 }), 0x10, emit.code());
try expectEqualHexStrings(
"\x81\x24\x25\x00\x00\x00\x10\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"and dword ptr [ds:0x10000000], 0x10",
);
try lowerToMiEnc(.@"and", RegisterOrMemory.mem(.dword_ptr, .{
.disp = 0x10000000,
.base = .r12,
- }), 0x10, isel.code());
+ }), 0x10, emit.code());
try expectEqualHexStrings(
"\x41\x81\xA4\x24\x00\x00\x00\x10\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"and dword ptr [r12 + 0x10000000], 0x10",
);
- try lowerToMiEnc(.mov, RegisterOrMemory.rip(.qword_ptr, 0x10), 0x10, isel.code());
+ try lowerToMiEnc(.mov, RegisterOrMemory.rip(.qword_ptr, 0x10), 0x10, emit.code());
try expectEqualHexStrings(
"\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"mov qword ptr [rip + 0x10], 0x10",
);
try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -8)),
.base = .rbp,
- }), 0x10, isel.code());
+ }), 0x10, emit.code());
try expectEqualHexStrings(
"\x48\xc7\x45\xf8\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"mov qword ptr [rbp - 8], 0x10",
);
try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{
.disp = @bitCast(u32, @as(i32, -2)),
.base = .rbp,
- }), 0x10, isel.code());
- try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", isel.lowered(), "mov word ptr [rbp - 2], 0x10");
+ }), 0x10, emit.code());
+ try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", emit.lowered(), "mov word ptr [rbp - 2], 0x10");
try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{
.disp = @bitCast(u32, @as(i32, -1)),
.base = .rbp,
- }), 0x10, isel.code());
- try expectEqualHexStrings("\xC6\x45\xFF\x10", isel.lowered(), "mov byte ptr [rbp - 1], 0x10");
+ }), 0x10, emit.code());
+ try expectEqualHexStrings("\xC6\x45\xFF\x10", emit.lowered(), "mov byte ptr [rbp - 1], 0x10");
try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0x10000000,
.scale_index = .{
.scale = 1,
.index = .rcx,
},
- }), 0x10, isel.code());
+ }), 0x10, emit.code());
try expectEqualHexStrings(
"\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"mov qword ptr [rcx*2 + 0x10000000], 0x10",
);
}
test "lower RM encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToRmEnc(.mov, .rax, RegisterOrMemory.reg(.rbx), isel.code());
- try expectEqualHexStrings("\x48\x8b\xc3", isel.lowered(), "mov rax, rbx");
- try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0, .base = .r11 }), isel.code());
- try expectEqualHexStrings("\x49\x8b\x03", isel.lowered(), "mov rax, qword ptr [r11 + 0]");
- try lowerToRmEnc(.add, .r11, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10000000 }), isel.code());
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToRmEnc(.mov, .rax, RegisterOrMemory.reg(.rbx), emit.code());
+ try expectEqualHexStrings("\x48\x8b\xc3", emit.lowered(), "mov rax, rbx");
+ try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0, .base = .r11 }), emit.code());
+ try expectEqualHexStrings("\x49\x8b\x03", emit.lowered(), "mov rax, qword ptr [r11 + 0]");
+ try lowerToRmEnc(.add, .r11, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10000000 }), emit.code());
try expectEqualHexStrings(
"\x4C\x03\x1C\x25\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"add r11, qword ptr [ds:0x10000000]",
);
- try lowerToRmEnc(.add, .r12b, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), isel.code());
+ try lowerToRmEnc(.add, .r12b, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), emit.code());
try expectEqualHexStrings(
"\x44\x02\x24\x25\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"add r11b, byte ptr [ds:0x10000000]",
);
try lowerToRmEnc(.sub, .r11, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0x10000000,
.base = .r13,
- }), isel.code());
+ }), emit.code());
try expectEqualHexStrings(
"\x4D\x2B\x9D\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"sub r11, qword ptr [r13 + 0x10000000]",
);
try lowerToRmEnc(.sub, .r11, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0x10000000,
.base = .r12,
- }), isel.code());
+ }), emit.code());
try expectEqualHexStrings(
"\x4D\x2B\x9C\x24\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"sub r11, qword ptr [r12 + 0x10000000]",
);
try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -4)),
.base = .rbp,
- }), isel.code());
- try expectEqualHexStrings("\x48\x8B\x45\xFC", isel.lowered(), "mov rax, qword ptr [rbp - 4]");
- try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code());
- try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", isel.lowered(), "lea rax, [rip + 0x10]");
+ }), emit.code());
+ try expectEqualHexStrings("\x48\x8B\x45\xFC", emit.lowered(), "mov rax, qword ptr [rbp - 4]");
+ try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), emit.code());
+ try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", emit.lowered(), "lea rax, [rip + 0x10]");
try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -8)),
.base = .rbp,
@@ -1910,8 +1907,8 @@ test "lower RM encoding" {
.scale = 0,
.index = .rcx,
},
- }), isel.code());
- try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]");
+ }), emit.code());
+ try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", emit.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]");
try lowerToRmEnc(.mov, .eax, RegisterOrMemory.mem(.dword_ptr, .{
.disp = @bitCast(u32, @as(i32, -4)),
.base = .rbp,
@@ -1919,8 +1916,8 @@ test "lower RM encoding" {
.scale = 2,
.index = .rdx,
},
- }), isel.code());
- try expectEqualHexStrings("\x8B\x44\x95\xFC", isel.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
+ }), emit.code());
+ try expectEqualHexStrings("\x8B\x44\x95\xFC", emit.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -8)),
.base = .rbp,
@@ -1928,8 +1925,8 @@ test "lower RM encoding" {
.scale = 3,
.index = .rcx,
},
- }), isel.code());
- try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");
+ }), emit.code());
+ try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", emit.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");
try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{
.disp = @bitCast(u32, @as(i32, -24)),
.base = .rsi,
@@ -1937,8 +1934,8 @@ test "lower RM encoding" {
.scale = 0,
.index = .rcx,
},
- }), isel.code());
- try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", isel.lowered(), "mov r8b, byte ptr [rsi + rcx*1 - 24]");
+ }), emit.code());
+ try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", emit.lowered(), "mov r8b, byte ptr [rsi + rcx*1 - 24]");
try lowerToRmEnc(.lea, .rsi, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0,
.base = .rbp,
@@ -1946,148 +1943,148 @@ test "lower RM encoding" {
.scale = 0,
.index = .rcx,
},
- }), isel.code());
- try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", isel.lowered(), "lea rsi, qword ptr [rbp + rcx*1 + 0]");
+ }), emit.code());
+ try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", emit.lowered(), "lea rsi, qword ptr [rbp + rcx*1 + 0]");
}
test "lower MR encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, isel.code());
- try expectEqualHexStrings("\x48\x89\xd8", isel.lowered(), "mov rax, rbx");
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, emit.code());
+ try expectEqualHexStrings("\x48\x89\xd8", emit.lowered(), "mov rax, rbx");
try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -4)),
.base = .rbp,
- }), .r11, isel.code());
- try expectEqualHexStrings("\x4c\x89\x5d\xfc", isel.lowered(), "mov qword ptr [rbp - 4], r11");
- try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, isel.code());
+ }), .r11, emit.code());
+ try expectEqualHexStrings("\x4c\x89\x5d\xfc", emit.lowered(), "mov qword ptr [rbp - 4], r11");
+ try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, emit.code());
try expectEqualHexStrings(
"\x44\x00\x24\x25\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"add byte ptr [ds:0x10000000], r12b",
);
- try lowerToMrEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0x10000000 }), .r12d, isel.code());
+ try lowerToMrEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0x10000000 }), .r12d, emit.code());
try expectEqualHexStrings(
"\x44\x01\x24\x25\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"add dword ptr [ds:0x10000000], r12d",
);
try lowerToMrEnc(.sub, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0x10000000,
.base = .r11,
- }), .r12, isel.code());
+ }), .r12, emit.code());
try expectEqualHexStrings(
"\x4D\x29\xA3\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"sub qword ptr [r11 + 0x10000000], r12",
);
- try lowerToMrEnc(.mov, RegisterOrMemory.rip(.qword_ptr, 0x10), .r12, isel.code());
- try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", isel.lowered(), "mov qword ptr [rip + 0x10], r12");
+ try lowerToMrEnc(.mov, RegisterOrMemory.rip(.qword_ptr, 0x10), .r12, emit.code());
+ try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", emit.lowered(), "mov qword ptr [rip + 0x10], r12");
}
test "lower OI encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToOiEnc(.mov, .rax, 0x1000000000000000, isel.code());
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToOiEnc(.mov, .rax, 0x1000000000000000, emit.code());
try expectEqualHexStrings(
"\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"movabs rax, 0x1000000000000000",
);
- try lowerToOiEnc(.mov, .r11, 0x1000000000000000, isel.code());
+ try lowerToOiEnc(.mov, .r11, 0x1000000000000000, emit.code());
try expectEqualHexStrings(
"\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"movabs r11, 0x1000000000000000",
);
- try lowerToOiEnc(.mov, .r11d, 0x10000000, isel.code());
- try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", isel.lowered(), "mov r11d, 0x10000000");
- try lowerToOiEnc(.mov, .r11w, 0x1000, isel.code());
- try expectEqualHexStrings("\x66\x41\xBB\x00\x10", isel.lowered(), "mov r11w, 0x1000");
- try lowerToOiEnc(.mov, .r11b, 0x10, isel.code());
- try expectEqualHexStrings("\x41\xB3\x10", isel.lowered(), "mov r11b, 0x10");
+ try lowerToOiEnc(.mov, .r11d, 0x10000000, emit.code());
+ try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", emit.lowered(), "mov r11d, 0x10000000");
+ try lowerToOiEnc(.mov, .r11w, 0x1000, emit.code());
+ try expectEqualHexStrings("\x66\x41\xBB\x00\x10", emit.lowered(), "mov r11w, 0x1000");
+ try lowerToOiEnc(.mov, .r11b, 0x10, emit.code());
+ try expectEqualHexStrings("\x41\xB3\x10", emit.lowered(), "mov r11b, 0x10");
}
test "lower FD/TD encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToFdEnc(.mov, .rax, 0x1000000000000000, isel.code());
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToFdEnc(.mov, .rax, 0x1000000000000000, emit.code());
try expectEqualHexStrings(
"\x48\xa1\x00\x00\x00\x00\x00\x00\x00\x10",
- isel.lowered(),
+ emit.lowered(),
"mov rax, ds:0x1000000000000000",
);
- try lowerToFdEnc(.mov, .eax, 0x10000000, isel.code());
- try expectEqualHexStrings("\xa1\x00\x00\x00\x10", isel.lowered(), "mov eax, ds:0x10000000");
- try lowerToFdEnc(.mov, .ax, 0x1000, isel.code());
- try expectEqualHexStrings("\x66\xa1\x00\x10", isel.lowered(), "mov ax, ds:0x1000");
- try lowerToFdEnc(.mov, .al, 0x10, isel.code());
- try expectEqualHexStrings("\xa0\x10", isel.lowered(), "mov al, ds:0x10");
+ try lowerToFdEnc(.mov, .eax, 0x10000000, emit.code());
+ try expectEqualHexStrings("\xa1\x00\x00\x00\x10", emit.lowered(), "mov eax, ds:0x10000000");
+ try lowerToFdEnc(.mov, .ax, 0x1000, emit.code());
+ try expectEqualHexStrings("\x66\xa1\x00\x10", emit.lowered(), "mov ax, ds:0x1000");
+ try lowerToFdEnc(.mov, .al, 0x10, emit.code());
+ try expectEqualHexStrings("\xa0\x10", emit.lowered(), "mov al, ds:0x10");
}
test "lower M encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToMEnc(.jmp_near, RegisterOrMemory.reg(.r12), isel.code());
- try expectEqualHexStrings("\x41\xFF\xE4", isel.lowered(), "jmp r12");
- try lowerToMEnc(.jmp_near, RegisterOrMemory.reg(.r12w), isel.code());
- try expectEqualHexStrings("\x66\x41\xFF\xE4", isel.lowered(), "jmp r12w");
- try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0, .base = .r12 }), isel.code());
- try expectEqualHexStrings("\x41\xFF\x24\x24", isel.lowered(), "jmp qword ptr [r12]");
- try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.word_ptr, .{ .disp = 0, .base = .r12 }), isel.code());
- try expectEqualHexStrings("\x66\x41\xFF\x24\x24", isel.lowered(), "jmp word ptr [r12]");
- try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10, .base = .r12 }), isel.code());
- try expectEqualHexStrings("\x41\xFF\x64\x24\x10", isel.lowered(), "jmp qword ptr [r12 + 0x10]");
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.reg(.r12), emit.code());
+ try expectEqualHexStrings("\x41\xFF\xE4", emit.lowered(), "jmp r12");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.reg(.r12w), emit.code());
+ try expectEqualHexStrings("\x66\x41\xFF\xE4", emit.lowered(), "jmp r12w");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0, .base = .r12 }), emit.code());
+ try expectEqualHexStrings("\x41\xFF\x24\x24", emit.lowered(), "jmp qword ptr [r12]");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.word_ptr, .{ .disp = 0, .base = .r12 }), emit.code());
+ try expectEqualHexStrings("\x66\x41\xFF\x24\x24", emit.lowered(), "jmp word ptr [r12]");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10, .base = .r12 }), emit.code());
+ try expectEqualHexStrings("\x41\xFF\x64\x24\x10", emit.lowered(), "jmp qword ptr [r12 + 0x10]");
try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{
.disp = 0x1000,
.base = .r12,
- }), isel.code());
+ }), emit.code());
try expectEqualHexStrings(
"\x41\xFF\xA4\x24\x00\x10\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"jmp qword ptr [r12 + 0x1000]",
);
- try lowerToMEnc(.jmp_near, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code());
- try expectEqualHexStrings("\xFF\x25\x10\x00\x00\x00", isel.lowered(), "jmp qword ptr [rip + 0x10]");
- try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10 }), isel.code());
- try expectEqualHexStrings("\xFF\x24\x25\x10\x00\x00\x00", isel.lowered(), "jmp qword ptr [ds:0x10]");
- try lowerToMEnc(.seta, RegisterOrMemory.reg(.r11b), isel.code());
- try expectEqualHexStrings("\x41\x0F\x97\xC3", isel.lowered(), "seta r11b");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.rip(.qword_ptr, 0x10), emit.code());
+ try expectEqualHexStrings("\xFF\x25\x10\x00\x00\x00", emit.lowered(), "jmp qword ptr [rip + 0x10]");
+ try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10 }), emit.code());
+ try expectEqualHexStrings("\xFF\x24\x25\x10\x00\x00\x00", emit.lowered(), "jmp qword ptr [ds:0x10]");
+ try lowerToMEnc(.seta, RegisterOrMemory.reg(.r11b), emit.code());
+ try expectEqualHexStrings("\x41\x0F\x97\xC3", emit.lowered(), "seta r11b");
}
test "lower O encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
- try lowerToOEnc(.pop, .r12, isel.code());
- try expectEqualHexStrings("\x41\x5c", isel.lowered(), "pop r12");
- try lowerToOEnc(.push, .r12w, isel.code());
- try expectEqualHexStrings("\x66\x41\x54", isel.lowered(), "push r12w");
+ var emit = TestEmit.init();
+ defer emit.deinit();
+ try lowerToOEnc(.pop, .r12, emit.code());
+ try expectEqualHexStrings("\x41\x5c", emit.lowered(), "pop r12");
+ try lowerToOEnc(.push, .r12w, emit.code());
+ try expectEqualHexStrings("\x66\x41\x54", emit.lowered(), "push r12w");
}
test "lower RMI encoding" {
- var isel = TestIsel.init();
- defer isel.deinit();
+ var emit = TestEmit.init();
+ defer emit.deinit();
try lowerToRmiEnc(.imul, .rax, RegisterOrMemory.mem(.qword_ptr, .{
.disp = @bitCast(u32, @as(i32, -8)),
.base = .rbp,
- }), 0x10, isel.code());
+ }), 0x10, emit.code());
try expectEqualHexStrings(
"\x48\x69\x45\xF8\x10\x00\x00\x00",
- isel.lowered(),
+ emit.lowered(),
"imul rax, qword ptr [rbp - 8], 0x10",
);
try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.dword_ptr, .{
.disp = @bitCast(u32, @as(i32, -4)),
.base = .rbp,
- }), 0x10, isel.code());
- try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", isel.lowered(), "imul eax, dword ptr [rbp - 4], 0x10");
+ }), 0x10, emit.code());
+ try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", emit.lowered(), "imul eax, dword ptr [rbp - 4], 0x10");
try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.word_ptr, .{
.disp = @bitCast(u32, @as(i32, -2)),
.base = .rbp,
- }), 0x10, isel.code());
- try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", isel.lowered(), "imul ax, word ptr [rbp - 2], 0x10");
- try lowerToRmiEnc(.imul, .r12, RegisterOrMemory.reg(.r12), 0x10, isel.code());
- try expectEqualHexStrings("\x4D\x69\xE4\x10\x00\x00\x00", isel.lowered(), "imul r12, r12, 0x10");
- try lowerToRmiEnc(.imul, .r12w, RegisterOrMemory.reg(.r12w), 0x10, isel.code());
- try expectEqualHexStrings("\x66\x45\x69\xE4\x10\x00", isel.lowered(), "imul r12w, r12w, 0x10");
+ }), 0x10, emit.code());
+ try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", emit.lowered(), "imul ax, word ptr [rbp - 2], 0x10");
+ try lowerToRmiEnc(.imul, .r12, RegisterOrMemory.reg(.r12), 0x10, emit.code());
+ try expectEqualHexStrings("\x4D\x69\xE4\x10\x00\x00\x00", emit.lowered(), "imul r12, r12, 0x10");
+ try lowerToRmiEnc(.imul, .r12w, RegisterOrMemory.reg(.r12w), 0x10, emit.code());
+ try expectEqualHexStrings("\x66\x45\x69\xE4\x10\x00", emit.lowered(), "imul r12w, r12w, 0x10");
}
CMakeLists.txt
@@ -578,7 +578,7 @@ set(ZIG_STAGE2_SOURCES
"${CMAKE_SOURCE_DIR}/src/arch/wasm/Emit.zig"
"${CMAKE_SOURCE_DIR}/src/arch/wasm/Mir.zig"
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/CodeGen.zig"
- "${CMAKE_SOURCE_DIR}/src/arch/x86_64/Isel.zig"
+ "${CMAKE_SOURCE_DIR}/src/arch/x86_64/Emit.zig"
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/Mir.zig"
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/bits.zig"
"${CMAKE_SOURCE_DIR}/src/clang.zig"