aboutsummaryrefslogtreecommitdiff
path: root/src-self-hosted/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src-self-hosted/codegen')
-rw-r--r--src-self-hosted/codegen/arm.zig607
-rw-r--r--src-self-hosted/codegen/c.zig299
-rw-r--r--src-self-hosted/codegen/llvm.zig125
-rw-r--r--src-self-hosted/codegen/riscv64.zig433
-rw-r--r--src-self-hosted/codegen/spu-mk2.zig170
-rw-r--r--src-self-hosted/codegen/spu-mk2/interpreter.zig166
-rw-r--r--src-self-hosted/codegen/wasm.zig142
-rw-r--r--src-self-hosted/codegen/x86.zig123
-rw-r--r--src-self-hosted/codegen/x86_64.zig220
9 files changed, 0 insertions, 2285 deletions
diff --git a/src-self-hosted/codegen/arm.zig b/src-self-hosted/codegen/arm.zig
deleted file mode 100644
index 05178ea7d3..0000000000
--- a/src-self-hosted/codegen/arm.zig
+++ /dev/null
@@ -1,607 +0,0 @@
-const std = @import("std");
-const DW = std.dwarf;
-const testing = std.testing;
-
-/// The condition field specifies the flags neccessary for an
-/// Instruction to be executed
-pub const Condition = enum(u4) {
- /// equal
- eq,
- /// not equal
- ne,
- /// unsigned higher or same
- cs,
- /// unsigned lower
- cc,
- /// negative
- mi,
- /// positive or zero
- pl,
- /// overflow
- vs,
- /// no overflow
- vc,
- /// unsigned higer
- hi,
- /// unsigned lower or same
- ls,
- /// greater or equal
- ge,
- /// less than
- lt,
- /// greater than
- gt,
- /// less than or equal
- le,
- /// always
- al,
-};
-
-/// Represents a register in the ARM instruction set architecture
-pub const Register = enum(u5) {
- r0,
- r1,
- r2,
- r3,
- r4,
- r5,
- r6,
- r7,
- r8,
- r9,
- r10,
- r11,
- r12,
- r13,
- r14,
- r15,
-
- /// Argument / result / scratch register 1
- a1,
- /// Argument / result / scratch register 2
- a2,
- /// Argument / scratch register 3
- a3,
- /// Argument / scratch register 4
- a4,
- /// Variable-register 1
- v1,
- /// Variable-register 2
- v2,
- /// Variable-register 3
- v3,
- /// Variable-register 4
- v4,
- /// Variable-register 5
- v5,
- /// Platform register
- v6,
- /// Variable-register 7
- v7,
- /// Frame pointer or Variable-register 8
- fp,
- /// Intra-Procedure-call scratch register
- ip,
- /// Stack pointer
- sp,
- /// Link register
- lr,
- /// Program counter
- pc,
-
- /// Returns the unique 4-bit ID of this register which is used in
- /// the machine code
- pub fn id(self: Register) u4 {
- return @truncate(u4, @enumToInt(self));
- }
-
- /// Returns the index into `callee_preserved_regs`.
- pub fn allocIndex(self: Register) ?u4 {
- inline for (callee_preserved_regs) |cpreg, i| {
- if (self.id() == cpreg.id()) return i;
- }
- return null;
- }
-
- pub fn dwarfLocOp(self: Register) u8 {
- return @as(u8, self.id()) + DW.OP_reg0;
- }
-};
-
-test "Register.id" {
- testing.expectEqual(@as(u4, 15), Register.r15.id());
- testing.expectEqual(@as(u4, 15), Register.pc.id());
-}
-
-pub const callee_preserved_regs = [_]Register{ .r0, .r1, .r2, .r3, .r4, .r5, .r6, .r7, .r8, .r10 };
-pub const c_abi_int_param_regs = [_]Register{ .r0, .r1, .r2, .r3 };
-pub const c_abi_int_return_regs = [_]Register{ .r0, .r1 };
-
-/// Represents an instruction in the ARM instruction set architecture
-pub const Instruction = union(enum) {
- DataProcessing: packed struct {
- // Note to self: The order of the fields top-to-bottom is
- // right-to-left in the actual 32-bit int representation
- op2: u12,
- rd: u4,
- rn: u4,
- s: u1,
- opcode: u4,
- i: u1,
- fixed: u2 = 0b00,
- cond: u4,
- },
- SingleDataTransfer: packed struct {
- offset: u12,
- rd: u4,
- rn: u4,
- l: u1,
- w: u1,
- b: u1,
- u: u1,
- p: u1,
- i: u1,
- fixed: u2 = 0b01,
- cond: u4,
- },
- Branch: packed struct {
- offset: u24,
- link: u1,
- fixed: u3 = 0b101,
- cond: u4,
- },
- BranchExchange: packed struct {
- rn: u4,
- fixed_1: u1 = 0b1,
- link: u1,
- fixed_2: u22 = 0b0001_0010_1111_1111_1111_00,
- cond: u4,
- },
- SupervisorCall: packed struct {
- comment: u24,
- fixed: u4 = 0b1111,
- cond: u4,
- },
- Breakpoint: packed struct {
- imm4: u4,
- fixed_1: u4 = 0b0111,
- imm12: u12,
- fixed_2_and_cond: u12 = 0b1110_0001_0010,
- },
-
- /// Represents the possible operations which can be performed by a
- /// DataProcessing instruction
- const Opcode = enum(u4) {
- // Rd := Op1 AND Op2
- @"and",
- // Rd := Op1 EOR Op2
- eor,
- // Rd := Op1 - Op2
- sub,
- // Rd := Op2 - Op1
- rsb,
- // Rd := Op1 + Op2
- add,
- // Rd := Op1 + Op2 + C
- adc,
- // Rd := Op1 - Op2 + C - 1
- sbc,
- // Rd := Op2 - Op1 + C - 1
- rsc,
- // set condition codes on Op1 AND Op2
- tst,
- // set condition codes on Op1 EOR Op2
- teq,
- // set condition codes on Op1 - Op2
- cmp,
- // set condition codes on Op1 + Op2
- cmn,
- // Rd := Op1 OR Op2
- orr,
- // Rd := Op2
- mov,
- // Rd := Op1 AND NOT Op2
- bic,
- // Rd := NOT Op2
- mvn,
- };
-
- /// Represents the second operand to a data processing instruction
- /// which can either be content from a register or an immediate
- /// value
- pub const Operand = union(enum) {
- Register: packed struct {
- rm: u4,
- shift: u8,
- },
- Immediate: packed struct {
- imm: u8,
- rotate: u4,
- },
-
- /// Represents multiple ways a register can be shifted. A
- /// register can be shifted by a specific immediate value or
- /// by the contents of another register
- pub const Shift = union(enum) {
- Immediate: packed struct {
- fixed: u1 = 0b0,
- typ: u2,
- amount: u5,
- },
- Register: packed struct {
- fixed_1: u1 = 0b1,
- typ: u2,
- fixed_2: u1 = 0b0,
- rs: u4,
- },
-
- const Type = enum(u2) {
- LogicalLeft,
- LogicalRight,
- ArithmeticRight,
- RotateRight,
- };
-
- const none = Shift{
- .Immediate = .{
- .amount = 0,
- .typ = 0,
- },
- };
-
- pub fn toU8(self: Shift) u8 {
- return switch (self) {
- .Register => |v| @bitCast(u8, v),
- .Immediate => |v| @bitCast(u8, v),
- };
- }
-
- pub fn reg(rs: Register, typ: Type) Shift {
- return Shift{
- .Register = .{
- .rs = rs.id(),
- .typ = @enumToInt(typ),
- },
- };
- }
-
- pub fn imm(amount: u5, typ: Type) Shift {
- return Shift{
- .Immediate = .{
- .amount = amount,
- .typ = @enumToInt(typ),
- },
- };
- }
- };
-
- pub fn toU12(self: Operand) u12 {
- return switch (self) {
- .Register => |v| @bitCast(u12, v),
- .Immediate => |v| @bitCast(u12, v),
- };
- }
-
- pub fn reg(rm: Register, shift: Shift) Operand {
- return Operand{
- .Register = .{
- .rm = rm.id(),
- .shift = shift.toU8(),
- },
- };
- }
-
- pub fn imm(immediate: u8, rotate: u4) Operand {
- return Operand{
- .Immediate = .{
- .imm = immediate,
- .rotate = rotate,
- },
- };
- }
- };
-
- /// Represents the offset operand of a load or store
- /// instruction. Data can be loaded from memory with either an
- /// immediate offset or an offset that is stored in some register.
- pub const Offset = union(enum) {
- Immediate: u12,
- Register: packed struct {
- rm: u4,
- shift: u8,
- },
-
- pub const none = Offset{
- .Immediate = 0,
- };
-
- pub fn toU12(self: Offset) u12 {
- return switch (self) {
- .Register => |v| @bitCast(u12, v),
- .Immediate => |v| v,
- };
- }
-
- pub fn reg(rm: Register, shift: u8) Offset {
- return Offset{
- .Register = .{
- .rm = rm.id(),
- .shift = shift,
- },
- };
- }
-
- pub fn imm(immediate: u8) Offset {
- return Offset{
- .Immediate = immediate,
- };
- }
- };
-
- pub fn toU32(self: Instruction) u32 {
- return switch (self) {
- .DataProcessing => |v| @bitCast(u32, v),
- .SingleDataTransfer => |v| @bitCast(u32, v),
- .Branch => |v| @bitCast(u32, v),
- .BranchExchange => |v| @bitCast(u32, v),
- .SupervisorCall => |v| @bitCast(u32, v),
- .Breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20),
- };
- }
-
- // Helper functions for the "real" functions below
-
- fn dataProcessing(
- cond: Condition,
- opcode: Opcode,
- s: u1,
- rd: Register,
- rn: Register,
- op2: Operand,
- ) Instruction {
- return Instruction{
- .DataProcessing = .{
- .cond = @enumToInt(cond),
- .i = if (op2 == .Immediate) 1 else 0,
- .opcode = @enumToInt(opcode),
- .s = s,
- .rn = rn.id(),
- .rd = rd.id(),
- .op2 = op2.toU12(),
- },
- };
- }
-
- fn singleDataTransfer(
- cond: Condition,
- rd: Register,
- rn: Register,
- offset: Offset,
- pre_post: u1,
- up_down: u1,
- byte_word: u1,
- writeback: u1,
- load_store: u1,
- ) Instruction {
- return Instruction{
- .SingleDataTransfer = .{
- .cond = @enumToInt(cond),
- .rn = rn.id(),
- .rd = rd.id(),
- .offset = offset.toU12(),
- .l = load_store,
- .w = writeback,
- .b = byte_word,
- .u = up_down,
- .p = pre_post,
- .i = if (offset == .Immediate) 0 else 1,
- },
- };
- }
-
- fn branch(cond: Condition, offset: i24, link: u1) Instruction {
- return Instruction{
- .Branch = .{
- .cond = @enumToInt(cond),
- .link = link,
- .offset = @bitCast(u24, offset),
- },
- };
- }
-
- fn branchExchange(cond: Condition, rn: Register, link: u1) Instruction {
- return Instruction{
- .BranchExchange = .{
- .cond = @enumToInt(cond),
- .link = link,
- .rn = rn.id(),
- },
- };
- }
-
- fn supervisorCall(cond: Condition, comment: u24) Instruction {
- return Instruction{
- .SupervisorCall = .{
- .cond = @enumToInt(cond),
- .comment = comment,
- },
- };
- }
-
- fn breakpoint(imm: u16) Instruction {
- return Instruction{
- .Breakpoint = .{
- .imm12 = @truncate(u12, imm >> 4),
- .imm4 = @truncate(u4, imm),
- },
- };
- }
-
- // Public functions replicating assembler syntax as closely as
- // possible
-
- // Data processing
-
- pub fn @"and"(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .@"and", s, rd, rn, op2);
- }
-
- pub fn eor(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .eor, s, rd, rn, op2);
- }
-
- pub fn sub(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .sub, s, rd, rn, op2);
- }
-
- pub fn rsb(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .rsb, s, rd, rn, op2);
- }
-
- pub fn add(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .add, s, rd, rn, op2);
- }
-
- pub fn adc(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .adc, s, rd, rn, op2);
- }
-
- pub fn sbc(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .sbc, s, rd, rn, op2);
- }
-
- pub fn rsc(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .rsc, s, rd, rn, op2);
- }
-
- pub fn tst(cond: Condition, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .tst, 1, .r0, rn, op2);
- }
-
- pub fn teq(cond: Condition, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .teq, 1, .r0, rn, op2);
- }
-
- pub fn cmp(cond: Condition, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .cmp, 1, .r0, rn, op2);
- }
-
- pub fn cmn(cond: Condition, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .cmn, 1, .r0, rn, op2);
- }
-
- pub fn orr(cond: Condition, s: u1, rd: Register, rn: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .orr, s, rd, rn, op2);
- }
-
- pub fn mov(cond: Condition, s: u1, rd: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .mov, s, rd, .r0, op2);
- }
-
- pub fn bic(cond: Condition, s: u1, rd: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .bic, s, rd, rn, op2);
- }
-
- pub fn mvn(cond: Condition, s: u1, rd: Register, op2: Operand) Instruction {
- return dataProcessing(cond, .mvn, s, rd, .r0, op2);
- }
-
- // Single data transfer
-
- pub fn ldr(cond: Condition, rd: Register, rn: Register, offset: Offset) Instruction {
- return singleDataTransfer(cond, rd, rn, offset, 1, 1, 0, 0, 1);
- }
-
- pub fn str(cond: Condition, rd: Register, rn: Register, offset: Offset) Instruction {
- return singleDataTransfer(cond, rd, rn, offset, 1, 1, 0, 0, 0);
- }
-
- // Branch
-
- pub fn b(cond: Condition, offset: i24) Instruction {
- return branch(cond, offset, 0);
- }
-
- pub fn bl(cond: Condition, offset: i24) Instruction {
- return branch(cond, offset, 1);
- }
-
- // Branch and exchange
-
- pub fn bx(cond: Condition, rn: Register) Instruction {
- return branchExchange(cond, rn, 0);
- }
-
- pub fn blx(cond: Condition, rn: Register) Instruction {
- return branchExchange(cond, rn, 1);
- }
-
- // Supervisor Call
-
- pub const swi = svc;
-
- pub fn svc(cond: Condition, comment: u24) Instruction {
- return supervisorCall(cond, comment);
- }
-
- // Breakpoint
-
- pub fn bkpt(imm: u16) Instruction {
- return breakpoint(imm);
- }
-};
-
-test "serialize instructions" {
- const Testcase = struct {
- inst: Instruction,
- expected: u32,
- };
-
- const testcases = [_]Testcase{
- .{ // add r0, r0, r0
- .inst = Instruction.add(.al, 0, .r0, .r0, Instruction.Operand.reg(.r0, Instruction.Operand.Shift.none)),
- .expected = 0b1110_00_0_0100_0_0000_0000_00000000_0000,
- },
- .{ // mov r4, r2
- .inst = Instruction.mov(.al, 0, .r4, Instruction.Operand.reg(.r2, Instruction.Operand.Shift.none)),
- .expected = 0b1110_00_0_1101_0_0000_0100_00000000_0010,
- },
- .{ // mov r0, #42
- .inst = Instruction.mov(.al, 0, .r0, Instruction.Operand.imm(42, 0)),
- .expected = 0b1110_00_1_1101_0_0000_0000_0000_00101010,
- },
- .{ // ldr r0, [r2, #42]
- .inst = Instruction.ldr(.al, .r0, .r2, Instruction.Offset.imm(42)),
- .expected = 0b1110_01_0_1_1_0_0_1_0010_0000_000000101010,
- },
- .{ // str r0, [r3]
- .inst = Instruction.str(.al, .r0, .r3, Instruction.Offset.none),
- .expected = 0b1110_01_0_1_1_0_0_0_0011_0000_000000000000,
- },
- .{ // b #12
- .inst = Instruction.b(.al, 12),
- .expected = 0b1110_101_0_0000_0000_0000_0000_0000_1100,
- },
- .{ // bl #-4
- .inst = Instruction.bl(.al, -4),
- .expected = 0b1110_101_1_1111_1111_1111_1111_1111_1100,
- },
- .{ // bx lr
- .inst = Instruction.bx(.al, .lr),
- .expected = 0b1110_0001_0010_1111_1111_1111_0001_1110,
- },
- .{ // svc #0
- .inst = Instruction.svc(.al, 0),
- .expected = 0b1110_1111_0000_0000_0000_0000_0000_0000,
- },
- .{ // bkpt #42
- .inst = Instruction.bkpt(42),
- .expected = 0b1110_0001_0010_000000000010_0111_1010,
- },
- };
-
- for (testcases) |case| {
- const actual = case.inst.toU32();
- testing.expectEqual(case.expected, actual);
- }
-}
diff --git a/src-self-hosted/codegen/c.zig b/src-self-hosted/codegen/c.zig
deleted file mode 100644
index 34ddcfbb3b..0000000000
--- a/src-self-hosted/codegen/c.zig
+++ /dev/null
@@ -1,299 +0,0 @@
-const std = @import("std");
-
-const link = @import("../link.zig");
-const Module = @import("../Module.zig");
-
-const Inst = @import("../ir.zig").Inst;
-const Value = @import("../value.zig").Value;
-const Type = @import("../type.zig").Type;
-
-const C = link.File.C;
-const Decl = Module.Decl;
-const mem = std.mem;
-
-/// Maps a name from Zig source to C. Currently, this will always give the same
-/// output for any given input, sometimes resulting in broken identifiers.
-fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 {
- return allocator.dupe(u8, name);
-}
-
-fn renderType(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type) !void {
- switch (T.zigTypeTag()) {
- .NoReturn => {
- try writer.writeAll("zig_noreturn void");
- },
- .Void => try writer.writeAll("void"),
- .Int => {
- if (T.tag() == .u8) {
- ctx.file.need_stdint = true;
- try writer.writeAll("uint8_t");
- } else if (T.tag() == .usize) {
- ctx.file.need_stddef = true;
- try writer.writeAll("size_t");
- } else {
- return ctx.file.fail(ctx.decl.src(), "TODO implement int types", .{});
- }
- },
- else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement type {}", .{e}),
- }
-}
-
-fn renderValue(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type, val: Value) !void {
- switch (T.zigTypeTag()) {
- .Int => {
- if (T.isSignedInt())
- return writer.print("{}", .{val.toSignedInt()});
- return writer.print("{}", .{val.toUnsignedInt()});
- },
- else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement value {}", .{e}),
- }
-}
-
-fn renderFunctionSignature(ctx: *Context, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
- const tv = decl.typed_value.most_recent.typed_value;
- try renderType(ctx, writer, tv.ty.fnReturnType());
- const name = try map(ctx.file.base.allocator, mem.spanZ(decl.name));
- defer ctx.file.base.allocator.free(name);
- try writer.print(" {}(", .{name});
- var param_len = tv.ty.fnParamLen();
- if (param_len == 0)
- try writer.writeAll("void")
- else {
- var index: usize = 0;
- while (index < param_len) : (index += 1) {
- if (index > 0) {
- try writer.writeAll(", ");
- }
- try renderType(ctx, writer, tv.ty.fnParamType(index));
- try writer.print(" arg{}", .{index});
- }
- }
- try writer.writeByte(')');
-}
-
-pub fn generate(file: *C, decl: *Decl) !void {
- switch (decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) {
- .Fn => try genFn(file, decl),
- .Array => try genArray(file, decl),
- else => |e| return file.fail(decl.src(), "TODO {}", .{e}),
- }
-}
-
-fn genArray(file: *C, decl: *Decl) !void {
- const tv = decl.typed_value.most_recent.typed_value;
- // TODO: prevent inline asm constants from being emitted
- const name = try map(file.base.allocator, mem.span(decl.name));
- defer file.base.allocator.free(name);
- if (tv.val.cast(Value.Payload.Bytes)) |payload|
- if (tv.ty.sentinel()) |sentinel|
- if (sentinel.toUnsignedInt() == 0)
- try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data })
- else
- return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{})
- else
- return file.fail(decl.src(), "TODO byte arrays without sentinels", .{})
- else
- return file.fail(decl.src(), "TODO non-byte arrays", .{});
-}
-
-const Context = struct {
- file: *C,
- decl: *Decl,
- inst_map: std.AutoHashMap(*Inst, []u8),
- argdex: usize = 0,
- unnamed_index: usize = 0,
-
- fn name(self: *Context) ![]u8 {
- const val = try std.fmt.allocPrint(self.file.base.allocator, "__temp_{}", .{self.unnamed_index});
- self.unnamed_index += 1;
- return val;
- }
-
- fn deinit(self: *Context) void {
- var it = self.inst_map.iterator();
- while (it.next()) |kv| {
- self.file.base.allocator.free(kv.value);
- }
- self.inst_map.deinit();
- self.* = undefined;
- }
-};
-
-fn genFn(file: *C, decl: *Decl) !void {
- const writer = file.main.writer();
- const tv = decl.typed_value.most_recent.typed_value;
-
- var ctx = Context{
- .file = file,
- .decl = decl,
- .inst_map = std.AutoHashMap(*Inst, []u8).init(file.base.allocator),
- };
- defer ctx.deinit();
-
- try renderFunctionSignature(&ctx, writer, decl);
-
- try writer.writeAll(" {");
-
- const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
- const instructions = func.analysis.success.instructions;
- if (instructions.len > 0) {
- try writer.writeAll("\n");
- for (instructions) |inst| {
- if (switch (inst.tag) {
- .assembly => try genAsm(&ctx, inst.castTag(.assembly).?),
- .call => try genCall(&ctx, inst.castTag(.call).?),
- .ret => try genRet(&ctx, inst.castTag(.ret).?),
- .retvoid => try genRetVoid(&ctx),
- .arg => try genArg(&ctx),
- .dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?),
- .breakpoint => try genBreak(&ctx, inst.castTag(.breakpoint).?),
- .unreach => try genUnreach(&ctx, inst.castTag(.unreach).?),
- .intcast => try genIntCast(&ctx, inst.castTag(.intcast).?),
- else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),
- }) |name| {
- try ctx.inst_map.putNoClobber(inst, name);
- }
- }
- }
-
- try writer.writeAll("}\n\n");
-}
-
-fn genArg(ctx: *Context) !?[]u8 {
- const name = try std.fmt.allocPrint(ctx.file.base.allocator, "arg{}", .{ctx.argdex});
- ctx.argdex += 1;
- return name;
-}
-
-fn genRetVoid(ctx: *Context) !?[]u8 {
- try ctx.file.main.writer().print(" return;\n", .{});
- return null;
-}
-
-fn genRet(ctx: *Context, inst: *Inst.UnOp) !?[]u8 {
- return ctx.file.fail(ctx.decl.src(), "TODO return", .{});
-}
-
-fn genIntCast(ctx: *Context, inst: *Inst.UnOp) !?[]u8 {
- if (inst.base.isUnused())
- return null;
- const op = inst.operand;
- const writer = ctx.file.main.writer();
- const name = try ctx.name();
- const from = ctx.inst_map.get(op) orelse
- return ctx.file.fail(ctx.decl.src(), "Internal error in C backend: intCast argument not found in inst_map", .{});
- try writer.writeAll(" const ");
- try renderType(ctx, writer, inst.base.ty);
- try writer.print(" {} = (", .{name});
- try renderType(ctx, writer, inst.base.ty);
- try writer.print("){};\n", .{from});
- return name;
-}
-
-fn genCall(ctx: *Context, inst: *Inst.Call) !?[]u8 {
- const writer = ctx.file.main.writer();
- const header = ctx.file.header.writer();
- try writer.writeAll(" ");
- if (inst.func.castTag(.constant)) |func_inst| {
- if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
- const target = func_val.func.owner_decl;
- const target_ty = target.typed_value.most_recent.typed_value.ty;
- const ret_ty = target_ty.fnReturnType().tag();
- if (target_ty.fnReturnType().hasCodeGenBits() and inst.base.isUnused()) {
- try writer.print("(void)", .{});
- }
- const tname = mem.spanZ(target.name);
- if (ctx.file.called.get(tname) == null) {
- try ctx.file.called.put(tname, void{});
- try renderFunctionSignature(ctx, header, target);
- try header.writeAll(";\n");
- }
- try writer.print("{}(", .{tname});
- if (inst.args.len != 0) {
- for (inst.args) |arg, i| {
- if (i > 0) {
- try writer.writeAll(", ");
- }
- if (arg.cast(Inst.Constant)) |con| {
- try renderValue(ctx, writer, arg.ty, con.val);
- } else {
- return ctx.file.fail(ctx.decl.src(), "TODO call pass arg {}", .{arg});
- }
- }
- }
- try writer.writeAll(");\n");
- } else {
- return ctx.file.fail(ctx.decl.src(), "TODO non-function call target?", .{});
- }
- } else {
- return ctx.file.fail(ctx.decl.src(), "TODO non-constant call inst?", .{});
- }
- return null;
-}
-
-fn genDbgStmt(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {
- // TODO emit #line directive here with line number and filename
- return null;
-}
-
-fn genBreak(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {
- // TODO ??
- return null;
-}
-
-fn genUnreach(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {
- try ctx.file.main.writer().writeAll(" zig_unreachable();\n");
- return null;
-}
-
-fn genAsm(ctx: *Context, as: *Inst.Assembly) !?[]u8 {
- const writer = ctx.file.main.writer();
- try writer.writeAll(" ");
- for (as.inputs) |i, index| {
- if (i[0] == '{' and i[i.len - 1] == '}') {
- const reg = i[1 .. i.len - 1];
- const arg = as.args[index];
- try writer.writeAll("register ");
- try renderType(ctx, writer, arg.ty);
- try writer.print(" {}_constant __asm__(\"{}\") = ", .{ reg, reg });
- // TODO merge constant handling into inst_map as well
- if (arg.castTag(.constant)) |c| {
- try renderValue(ctx, writer, arg.ty, c.val);
- try writer.writeAll(";\n ");
- } else {
- const gop = try ctx.inst_map.getOrPut(arg);
- if (!gop.found_existing) {
- return ctx.file.fail(ctx.decl.src(), "Internal error in C backend: asm argument not found in inst_map", .{});
- }
- try writer.print("{};\n ", .{gop.entry.value});
- }
- } else {
- return ctx.file.fail(ctx.decl.src(), "TODO non-explicit inline asm regs", .{});
- }
- }
- try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source });
- if (as.output) |o| {
- return ctx.file.fail(ctx.decl.src(), "TODO inline asm output", .{});
- }
- if (as.inputs.len > 0) {
- if (as.output == null) {
- try writer.writeAll(" :");
- }
- try writer.writeAll(": ");
- for (as.inputs) |i, index| {
- if (i[0] == '{' and i[i.len - 1] == '}') {
- const reg = i[1 .. i.len - 1];
- const arg = as.args[index];
- if (index > 0) {
- try writer.writeAll(", ");
- }
- try writer.print("\"\"({}_constant)", .{reg});
- } else {
- // This is blocked by the earlier test
- unreachable;
- }
- }
- }
- try writer.writeAll(");\n");
- return null;
-}
diff --git a/src-self-hosted/codegen/llvm.zig b/src-self-hosted/codegen/llvm.zig
deleted file mode 100644
index 01fa0baf02..0000000000
--- a/src-self-hosted/codegen/llvm.zig
+++ /dev/null
@@ -1,125 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-
-pub fn targetTriple(allocator: *Allocator, target: std.Target) ![]u8 {
- const llvm_arch = switch (target.cpu.arch) {
- .arm => "arm",
- .armeb => "armeb",
- .aarch64 => "aarch64",
- .aarch64_be => "aarch64_be",
- .aarch64_32 => "aarch64_32",
- .arc => "arc",
- .avr => "avr",
- .bpfel => "bpfel",
- .bpfeb => "bpfeb",
- .hexagon => "hexagon",
- .mips => "mips",
- .mipsel => "mipsel",
- .mips64 => "mips64",
- .mips64el => "mips64el",
- .msp430 => "msp430",
- .powerpc => "powerpc",
- .powerpc64 => "powerpc64",
- .powerpc64le => "powerpc64le",
- .r600 => "r600",
- .amdgcn => "amdgcn",
- .riscv32 => "riscv32",
- .riscv64 => "riscv64",
- .sparc => "sparc",
- .sparcv9 => "sparcv9",
- .sparcel => "sparcel",
- .s390x => "s390x",
- .tce => "tce",
- .tcele => "tcele",
- .thumb => "thumb",
- .thumbeb => "thumbeb",
- .i386 => "i386",
- .x86_64 => "x86_64",
- .xcore => "xcore",
- .nvptx => "nvptx",
- .nvptx64 => "nvptx64",
- .le32 => "le32",
- .le64 => "le64",
- .amdil => "amdil",
- .amdil64 => "amdil64",
- .hsail => "hsail",
- .hsail64 => "hsail64",
- .spir => "spir",
- .spir64 => "spir64",
- .kalimba => "kalimba",
- .shave => "shave",
- .lanai => "lanai",
- .wasm32 => "wasm32",
- .wasm64 => "wasm64",
- .renderscript32 => "renderscript32",
- .renderscript64 => "renderscript64",
- .ve => "ve",
- .spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
- };
- // TODO Add a sub-arch for some architectures depending on CPU features.
-
- const llvm_os = switch (target.os.tag) {
- .freestanding => "unknown",
- .ananas => "ananas",
- .cloudabi => "cloudabi",
- .dragonfly => "dragonfly",
- .freebsd => "freebsd",
- .fuchsia => "fuchsia",
- .ios => "ios",
- .kfreebsd => "kfreebsd",
- .linux => "linux",
- .lv2 => "lv2",
- .macosx => "macosx",
- .netbsd => "netbsd",
- .openbsd => "openbsd",
- .solaris => "solaris",
- .windows => "windows",
- .haiku => "haiku",
- .minix => "minix",
- .rtems => "rtems",
- .nacl => "nacl",
- .cnk => "cnk",
- .aix => "aix",
- .cuda => "cuda",
- .nvcl => "nvcl",
- .amdhsa => "amdhsa",
- .ps4 => "ps4",
- .elfiamcu => "elfiamcu",
- .tvos => "tvos",
- .watchos => "watchos",
- .mesa3d => "mesa3d",
- .contiki => "contiki",
- .amdpal => "amdpal",
- .hermit => "hermit",
- .hurd => "hurd",
- .wasi => "wasi",
- .emscripten => "emscripten",
- .uefi => "windows",
- .other => "unknown",
- };
-
- const llvm_abi = switch (target.abi) {
- .none => "unknown",
- .gnu => "gnu",
- .gnuabin32 => "gnuabin32",
- .gnuabi64 => "gnuabi64",
- .gnueabi => "gnueabi",
- .gnueabihf => "gnueabihf",
- .gnux32 => "gnux32",
- .code16 => "code16",
- .eabi => "eabi",
- .eabihf => "eabihf",
- .android => "android",
- .musl => "musl",
- .musleabi => "musleabi",
- .musleabihf => "musleabihf",
- .msvc => "msvc",
- .itanium => "itanium",
- .cygnus => "cygnus",
- .coreclr => "coreclr",
- .simulator => "simulator",
- .macabi => "macabi",
- };
-
- return std.fmt.allocPrint(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi });
-}
diff --git a/src-self-hosted/codegen/riscv64.zig b/src-self-hosted/codegen/riscv64.zig
deleted file mode 100644
index 96b9c58f9c..0000000000
--- a/src-self-hosted/codegen/riscv64.zig
+++ /dev/null
@@ -1,433 +0,0 @@
-const std = @import("std");
-const DW = std.dwarf;
-
-// TODO: this is only tagged to facilitate the monstrosity.
-// Once packed structs work make it packed.
-pub const Instruction = union(enum) {
- R: packed struct {
- opcode: u7,
- rd: u5,
- funct3: u3,
- rs1: u5,
- rs2: u5,
- funct7: u7,
- },
- I: packed struct {
- opcode: u7,
- rd: u5,
- funct3: u3,
- rs1: u5,
- imm0_11: u12,
- },
- S: packed struct {
- opcode: u7,
- imm0_4: u5,
- funct3: u3,
- rs1: u5,
- rs2: u5,
- imm5_11: u7,
- },
- B: packed struct {
- opcode: u7,
- imm11: u1,
- imm1_4: u4,
- funct3: u3,
- rs1: u5,
- rs2: u5,
- imm5_10: u6,
- imm12: u1,
- },
- U: packed struct {
- opcode: u7,
- rd: u5,
- imm12_31: u20,
- },
- J: packed struct {
- opcode: u7,
- rd: u5,
- imm12_19: u8,
- imm11: u1,
- imm1_10: u10,
- imm20: u1,
- },
-
- // TODO: once packed structs work we can remove this monstrosity.
- pub fn toU32(self: Instruction) u32 {
- return switch (self) {
- .R => |v| @bitCast(u32, v),
- .I => |v| @bitCast(u32, v),
- .S => |v| @bitCast(u32, v),
- .B => |v| @intCast(u32, v.opcode) + (@intCast(u32, v.imm11) << 7) + (@intCast(u32, v.imm1_4) << 8) + (@intCast(u32, v.funct3) << 12) + (@intCast(u32, v.rs1) << 15) + (@intCast(u32, v.rs2) << 20) + (@intCast(u32, v.imm5_10) << 25) + (@intCast(u32, v.imm12) << 31),
- .U => |v| @bitCast(u32, v),
- .J => |v| @bitCast(u32, v),
- };
- }
-
- fn rType(op: u7, fn3: u3, fn7: u7, rd: Register, r1: Register, r2: Register) Instruction {
- return Instruction{
- .R = .{
- .opcode = op,
- .funct3 = fn3,
- .funct7 = fn7,
- .rd = @enumToInt(rd),
- .rs1 = @enumToInt(r1),
- .rs2 = @enumToInt(r2),
- },
- };
- }
-
- // RISC-V is all signed all the time -- convert immediates to unsigned for processing
- fn iType(op: u7, fn3: u3, rd: Register, r1: Register, imm: i12) Instruction {
- const umm = @bitCast(u12, imm);
-
- return Instruction{
- .I = .{
- .opcode = op,
- .funct3 = fn3,
- .rd = @enumToInt(rd),
- .rs1 = @enumToInt(r1),
- .imm0_11 = umm,
- },
- };
- }
-
- fn sType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i12) Instruction {
- const umm = @bitCast(u12, imm);
-
- return Instruction{
- .S = .{
- .opcode = op,
- .funct3 = fn3,
- .rs1 = @enumToInt(r1),
- .rs2 = @enumToInt(r2),
- .imm0_4 = @truncate(u5, umm),
- .imm5_11 = @truncate(u7, umm >> 5),
- },
- };
- }
-
- // Use significance value rather than bit value, same for J-type
- // -- less burden on callsite, bonus semantic checking
- fn bType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i13) Instruction {
- const umm = @bitCast(u13, imm);
- if (umm % 2 != 0) @panic("Internal error: misaligned branch target");
-
- return Instruction{
- .B = .{
- .opcode = op,
- .funct3 = fn3,
- .rs1 = @enumToInt(r1),
- .rs2 = @enumToInt(r2),
- .imm1_4 = @truncate(u4, umm >> 1),
- .imm5_10 = @truncate(u6, umm >> 5),
- .imm11 = @truncate(u1, umm >> 11),
- .imm12 = @truncate(u1, umm >> 12),
- },
- };
- }
-
- // We have to extract the 20 bits anyway -- let's not make it more painful
- fn uType(op: u7, rd: Register, imm: i20) Instruction {
- const umm = @bitCast(u20, imm);
-
- return Instruction{
- .U = .{
- .opcode = op,
- .rd = @enumToInt(rd),
- .imm12_31 = umm,
- },
- };
- }
-
- fn jType(op: u7, rd: Register, imm: i21) Instruction {
- const umm = @bitcast(u21, imm);
- if (umm % 2 != 0) @panic("Internal error: misaligned jump target");
-
- return Instruction{
- .J = .{
- .opcode = op,
- .rd = @enumToInt(rd),
- .imm1_10 = @truncate(u10, umm >> 1),
- .imm11 = @truncate(u1, umm >> 1),
- .imm12_19 = @truncate(u8, umm >> 12),
- .imm20 = @truncate(u1, umm >> 20),
- },
- };
- }
-
- // The meat and potatoes. Arguments are in the order in which they would appear in assembly code.
-
- // Arithmetic/Logical, Register-Register
-
- pub fn add(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b000, 0b0000000, rd, r1, r2);
- }
-
- pub fn sub(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b000, 0b0100000, rd, r1, r2);
- }
-
- pub fn @"and"(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b111, 0b0000000, rd, r1, r2);
- }
-
- pub fn @"or"(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b110, 0b0000000, rd, r1, r2);
- }
-
- pub fn xor(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b100, 0b0000000, rd, r1, r2);
- }
-
- pub fn sll(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b001, 0b0000000, rd, r1, r2);
- }
-
- pub fn srl(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b101, 0b0000000, rd, r1, r2);
- }
-
- pub fn sra(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b101, 0b0100000, rd, r1, r2);
- }
-
- pub fn slt(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b010, 0b0000000, rd, r1, r2);
- }
-
- pub fn sltu(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0110011, 0b011, 0b0000000, rd, r1, r2);
- }
-
- // Arithmetic/Logical, Register-Register (32-bit)
-
- pub fn addw(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0111011, 0b000, rd, r1, r2);
- }
-
- pub fn subw(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0111011, 0b000, 0b0100000, rd, r1, r2);
- }
-
- pub fn sllw(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0111011, 0b001, 0b0000000, rd, r1, r2);
- }
-
- pub fn srlw(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0111011, 0b101, 0b0000000, rd, r1, r2);
- }
-
- pub fn sraw(rd: Register, r1: Register, r2: Register) Instruction {
- return rType(0b0111011, 0b101, 0b0100000, rd, r1, r2);
- }
-
- // Arithmetic/Logical, Register-Immediate
-
- pub fn addi(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0010011, 0b000, rd, r1, imm);
- }
-
- pub fn andi(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0010011, 0b111, rd, r1, imm);
- }
-
- pub fn ori(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0010011, 0b110, rd, r1, imm);
- }
-
- pub fn xori(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0010011, 0b100, rd, r1, imm);
- }
-
- pub fn slli(rd: Register, r1: Register, shamt: u6) Instruction {
- return iType(0b0010011, 0b001, rd, r1, shamt);
- }
-
- pub fn srli(rd: Register, r1: Register, shamt: u6) Instruction {
- return iType(0b0010011, 0b101, rd, r1, shamt);
- }
-
- pub fn srai(rd: Register, r1: Register, shamt: u6) Instruction {
- return iType(0b0010011, 0b101, rd, r1, (1 << 10) + shamt);
- }
-
- pub fn slti(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0010011, 0b010, rd, r1, imm);
- }
-
- pub fn sltiu(rd: Register, r1: Register, imm: u12) Instruction {
- return iType(0b0010011, 0b011, rd, r1, @bitCast(i12, imm));
- }
-
- // Arithmetic/Logical, Register-Immediate (32-bit)
-
- pub fn addiw(rd: Register, r1: Register, imm: i12) Instruction {
- return iType(0b0011011, 0b000, rd, r1, imm);
- }
-
- pub fn slliw(rd: Register, r1: Register, shamt: u5) Instruction {
- return iType(0b0011011, 0b001, rd, r1, shamt);
- }
-
- pub fn srliw(rd: Register, r1: Register, shamt: u5) Instruction {
- return iType(0b0011011, 0b101, rd, r1, shamt);
- }
-
- pub fn sraiw(rd: Register, r1: Register, shamt: u5) Instruction {
- return iType(0b0011011, 0b101, rd, r1, (1 << 10) + shamt);
- }
-
- // Upper Immediate
-
- pub fn lui(rd: Register, imm: i20) Instruction {
- return uType(0b0110111, rd, imm);
- }
-
- pub fn auipc(rd: Register, imm: i20) Instruction {
- return uType(0b0010111, rd, imm);
- }
-
- // Load
-
- pub fn ld(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b011, rd, base, offset);
- }
-
- pub fn lw(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b010, rd, base, offset);
- }
-
- pub fn lwu(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b110, rd, base, offset);
- }
-
- pub fn lh(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b001, rd, base, offset);
- }
-
- pub fn lhu(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b101, rd, base, offset);
- }
-
- pub fn lb(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b000, rd, base, offset);
- }
-
- pub fn lbu(rd: Register, offset: i12, base: Register) Instruction {
- return iType(0b0000011, 0b100, rd, base, offset);
- }
-
- // Store
-
- pub fn sd(rs: Register, offset: i12, base: Register) Instruction {
- return sType(0b0100011, 0b011, base, rs, offset);
- }
-
- pub fn sw(rs: Register, offset: i12, base: Register) Instruction {
- return sType(0b0100011, 0b010, base, rs, offset);
- }
-
- pub fn sh(rs: Register, offset: i12, base: Register) Instruction {
- return sType(0b0100011, 0b001, base, rs, offset);
- }
-
- pub fn sb(rs: Register, offset: i12, base: Register) Instruction {
- return sType(0b0100011, 0b000, base, rs, offset);
- }
-
- // Fence
- // TODO: implement fence
-
- // Branch
-
- pub fn beq(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b000, r1, r2, offset);
- }
-
- pub fn bne(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b001, r1, r2, offset);
- }
-
- pub fn blt(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b100, r1, r2, offset);
- }
-
- pub fn bge(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b101, r1, r2, offset);
- }
-
- pub fn bltu(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b110, r1, r2, offset);
- }
-
- pub fn bgeu(r1: Register, r2: Register, offset: u13) Instruction {
- return bType(0b1100011, 0b111, r1, r2, offset);
- }
-
- // Jump
-
- pub fn jal(link: Register, offset: i21) Instruction {
- return jType(0b1101111, link, offset);
- }
-
- pub fn jalr(link: Register, offset: i12, base: Register) Instruction {
- return iType(0b1100111, 0b000, link, base, offset);
- }
-
- // System
-
- pub const ecall = iType(0b1110011, 0b000, .zero, .zero, 0x000);
- pub const ebreak = iType(0b1110011, 0b000, .zero, .zero, 0x001);
-};
-
-// zig fmt: off
-pub const RawRegister = enum(u5) {
- x0, x1, x2, x3, x4, x5, x6, x7,
- x8, x9, x10, x11, x12, x13, x14, x15,
- x16, x17, x18, x19, x20, x21, x22, x23,
- x24, x25, x26, x27, x28, x29, x30, x31,
-
- pub fn dwarfLocOp(reg: RawRegister) u8 {
- return @enumToInt(reg) + DW.OP_reg0;
- }
-};
-
-pub const Register = enum(u5) {
- // 64 bit registers
- zero, // zero
- ra, // return address. caller saved
- sp, // stack pointer. callee saved.
- gp, // global pointer
- tp, // thread pointer
- t0, t1, t2, // temporaries. caller saved.
- s0, // s0/fp, callee saved.
- s1, // callee saved.
- a0, a1, // fn args/return values. caller saved.
- a2, a3, a4, a5, a6, a7, // fn args. caller saved.
- s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, // saved registers. callee saved.
- t3, t4, t5, t6, // caller saved
-
- pub fn parseRegName(name: []const u8) ?Register {
- if(std.meta.stringToEnum(Register, name)) |reg| return reg;
- if(std.meta.stringToEnum(RawRegister, name)) |rawreg| return @intToEnum(Register, @enumToInt(rawreg));
- return null;
- }
-
- /// Returns the index into `callee_preserved_regs`.
- pub fn allocIndex(self: Register) ?u4 {
- inline for(callee_preserved_regs) |cpreg, i| {
- if(self == cpreg) return i;
- }
- return null;
- }
-
- pub fn dwarfLocOp(reg: Register) u8 {
- return @as(u8, @enumToInt(reg)) + DW.OP_reg0;
- }
-};
-
-// zig fmt: on
-
-pub const callee_preserved_regs = [_]Register{
- .s0, .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
-};
diff --git a/src-self-hosted/codegen/spu-mk2.zig b/src-self-hosted/codegen/spu-mk2.zig
deleted file mode 100644
index 542862caca..0000000000
--- a/src-self-hosted/codegen/spu-mk2.zig
+++ /dev/null
@@ -1,170 +0,0 @@
-const std = @import("std");
-
-pub const Interpreter = @import("spu-mk2/interpreter.zig").Interpreter;
-
-pub const ExecutionCondition = enum(u3) {
- always = 0,
- when_zero = 1,
- not_zero = 2,
- greater_zero = 3,
- less_than_zero = 4,
- greater_or_equal_zero = 5,
- less_or_equal_zero = 6,
- overflow = 7,
-};
-
-pub const InputBehaviour = enum(u2) {
- zero = 0,
- immediate = 1,
- peek = 2,
- pop = 3,
-};
-
-pub const OutputBehaviour = enum(u2) {
- discard = 0,
- push = 1,
- jump = 2,
- jump_relative = 3,
-};
-
-pub const Command = enum(u5) {
- copy = 0,
- ipget = 1,
- get = 2,
- set = 3,
- store8 = 4,
- store16 = 5,
- load8 = 6,
- load16 = 7,
- undefined0 = 8,
- undefined1 = 9,
- frget = 10,
- frset = 11,
- bpget = 12,
- bpset = 13,
- spget = 14,
- spset = 15,
- add = 16,
- sub = 17,
- mul = 18,
- div = 19,
- mod = 20,
- @"and" = 21,
- @"or" = 22,
- xor = 23,
- not = 24,
- signext = 25,
- rol = 26,
- ror = 27,
- bswap = 28,
- asr = 29,
- lsl = 30,
- lsr = 31,
-};
-
-pub const Instruction = packed struct {
- condition: ExecutionCondition,
- input0: InputBehaviour,
- input1: InputBehaviour,
- modify_flags: bool,
- output: OutputBehaviour,
- command: Command,
- reserved: u1 = 0,
-
- pub fn format(instr: Instruction, comptime fmt: []const u8, options: std.fmt.FormatOptions, out: anytype) !void {
- try std.fmt.format(out, "0x{x:0<4} ", .{@bitCast(u16, instr)});
- try out.writeAll(switch (instr.condition) {
- .always => " ",
- .when_zero => "== 0",
- .not_zero => "!= 0",
- .greater_zero => " > 0",
- .less_than_zero => " < 0",
- .greater_or_equal_zero => ">= 0",
- .less_or_equal_zero => "<= 0",
- .overflow => "ovfl",
- });
- try out.writeAll(" ");
- try out.writeAll(switch (instr.input0) {
- .zero => "zero",
- .immediate => "imm ",
- .peek => "peek",
- .pop => "pop ",
- });
- try out.writeAll(" ");
- try out.writeAll(switch (instr.input1) {
- .zero => "zero",
- .immediate => "imm ",
- .peek => "peek",
- .pop => "pop ",
- });
- try out.writeAll(" ");
- try out.writeAll(switch (instr.command) {
- .copy => "copy ",
- .ipget => "ipget ",
- .get => "get ",
- .set => "set ",
- .store8 => "store8 ",
- .store16 => "store16 ",
- .load8 => "load8 ",
- .load16 => "load16 ",
- .undefined0 => "undefined",
- .undefined1 => "undefined",
- .frget => "frget ",
- .frset => "frset ",
- .bpget => "bpget ",
- .bpset => "bpset ",
- .spget => "spget ",
- .spset => "spset ",
- .add => "add ",
- .sub => "sub ",
- .mul => "mul ",
- .div => "div ",
- .mod => "mod ",
- .@"and" => "and ",
- .@"or" => "or ",
- .xor => "xor ",
- .not => "not ",
- .signext => "signext ",
- .rol => "rol ",
- .ror => "ror ",
- .bswap => "bswap ",
- .asr => "asr ",
- .lsl => "lsl ",
- .lsr => "lsr ",
- });
- try out.writeAll(" ");
- try out.writeAll(switch (instr.output) {
- .discard => "discard",
- .push => "push ",
- .jump => "jmp ",
- .jump_relative => "rjmp ",
- });
- try out.writeAll(" ");
- try out.writeAll(if (instr.modify_flags)
- "+ flags"
- else
- " ");
- }
-};
-
-pub const FlagRegister = packed struct {
- zero: bool,
- negative: bool,
- carry: bool,
- carry_enabled: bool,
- interrupt0_enabled: bool,
- interrupt1_enabled: bool,
- interrupt2_enabled: bool,
- interrupt3_enabled: bool,
- reserved: u8 = 0,
-};
-
-pub const Register = enum {
- dummy,
-
- pub fn allocIndex(self: Register) ?u4 {
- return null;
- }
-};
-
-pub const callee_preserved_regs = [_]Register{};
diff --git a/src-self-hosted/codegen/spu-mk2/interpreter.zig b/src-self-hosted/codegen/spu-mk2/interpreter.zig
deleted file mode 100644
index 1ec99546c6..0000000000
--- a/src-self-hosted/codegen/spu-mk2/interpreter.zig
+++ /dev/null
@@ -1,166 +0,0 @@
-const std = @import("std");
-const log = std.log.scoped(.SPU_2_Interpreter);
-const spu = @import("../spu-mk2.zig");
-const FlagRegister = spu.FlagRegister;
-const Instruction = spu.Instruction;
-const ExecutionCondition = spu.ExecutionCondition;
-
-pub fn Interpreter(comptime Bus: type) type {
- return struct {
- ip: u16 = 0,
- sp: u16 = undefined,
- bp: u16 = undefined,
- fr: FlagRegister = @bitCast(FlagRegister, @as(u16, 0)),
- /// This is set to true when we hit an undefined0 instruction, allowing it to
- /// be used as a trap for testing purposes
- undefined0: bool = false,
- /// This is set to true when we hit an undefined1 instruction, allowing it to
- /// be used as a trap for testing purposes. undefined1 is used as a breakpoint.
- undefined1: bool = false,
- bus: Bus,
-
- pub fn ExecuteBlock(self: *@This(), comptime size: ?u32) !void {
- var count: usize = 0;
- while (size == null or count < size.?) {
- count += 1;
- var instruction = @bitCast(Instruction, self.bus.read16(self.ip));
-
- log.debug("Executing {}\n", .{instruction});
-
- self.ip +%= 2;
-
- const execute = switch (instruction.condition) {
- .always => true,
- .not_zero => !self.fr.zero,
- .when_zero => self.fr.zero,
- .overflow => self.fr.carry,
- ExecutionCondition.greater_or_equal_zero => !self.fr.negative,
- else => return error.Unimplemented,
- };
-
- if (execute) {
- const val0 = switch (instruction.input0) {
- .zero => @as(u16, 0),
- .immediate => i: {
- const val = self.bus.read16(@intCast(u16, self.ip));
- self.ip +%= 2;
- break :i val;
- },
- else => |e| e: {
- // peek or pop; show value at current SP, and if pop, increment sp
- const val = self.bus.read16(self.sp);
- if (e == .pop) {
- self.sp +%= 2;
- }
- break :e val;
- },
- };
- const val1 = switch (instruction.input1) {
- .zero => @as(u16, 0),
- .immediate => i: {
- const val = self.bus.read16(@intCast(u16, self.ip));
- self.ip +%= 2;
- break :i val;
- },
- else => |e| e: {
- // peek or pop; show value at current SP, and if pop, increment sp
- const val = self.bus.read16(self.sp);
- if (e == .pop) {
- self.sp +%= 2;
- }
- break :e val;
- },
- };
-
- const output: u16 = switch (instruction.command) {
- .get => self.bus.read16(self.bp +% (2 *% val0)),
- .set => a: {
- self.bus.write16(self.bp +% 2 *% val0, val1);
- break :a val1;
- },
- .load8 => self.bus.read8(val0),
- .load16 => self.bus.read16(val0),
- .store8 => a: {
- const val = @truncate(u8, val1);
- self.bus.write8(val0, val);
- break :a val;
- },
- .store16 => a: {
- self.bus.write16(val0, val1);
- break :a val1;
- },
- .copy => val0,
- .add => a: {
- var val: u16 = undefined;
- self.fr.carry = @addWithOverflow(u16, val0, val1, &val);
- break :a val;
- },
- .sub => a: {
- var val: u16 = undefined;
- self.fr.carry = @subWithOverflow(u16, val0, val1, &val);
- break :a val;
- },
- .spset => a: {
- self.sp = val0;
- break :a val0;
- },
- .bpset => a: {
- self.bp = val0;
- break :a val0;
- },
- .frset => a: {
- const val = (@bitCast(u16, self.fr) & val1) | (val0 & ~val1);
- self.fr = @bitCast(FlagRegister, val);
- break :a val;
- },
- .bswap => (val0 >> 8) | (val0 << 8),
- .bpget => self.bp,
- .spget => self.sp,
- .ipget => self.ip +% (2 *% val0),
- .lsl => val0 << 1,
- .lsr => val0 >> 1,
- .@"and" => val0 & val1,
- .@"or" => val0 | val1,
- .xor => val0 ^ val1,
- .not => ~val0,
- .undefined0 => {
- self.undefined0 = true;
- // Break out of the loop, and let the caller decide what to do
- return;
- },
- .undefined1 => {
- self.undefined1 = true;
- // Break out of the loop, and let the caller decide what to do
- return;
- },
- .signext => if ((val0 & 0x80) != 0)
- (val0 & 0xFF) | 0xFF00
- else
- (val0 & 0xFF),
- else => return error.Unimplemented,
- };
-
- switch (instruction.output) {
- .discard => {},
- .push => {
- self.sp -%= 2;
- self.bus.write16(self.sp, output);
- },
- .jump => {
- self.ip = output;
- },
- else => return error.Unimplemented,
- }
- if (instruction.modify_flags) {
- self.fr.negative = (output & 0x8000) != 0;
- self.fr.zero = (output == 0x0000);
- }
- } else {
- if (instruction.input0 == .immediate) self.ip +%= 2;
- if (instruction.input1 == .immediate) self.ip +%= 2;
- break;
- }
- }
- }
- };
-}
diff --git a/src-self-hosted/codegen/wasm.zig b/src-self-hosted/codegen/wasm.zig
deleted file mode 100644
index 4ea8838409..0000000000
--- a/src-self-hosted/codegen/wasm.zig
+++ /dev/null
@@ -1,142 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const ArrayList = std.ArrayList;
-const assert = std.debug.assert;
-const leb = std.debug.leb;
-const mem = std.mem;
-
-const Module = @import("../Module.zig");
-const Decl = Module.Decl;
-const Inst = @import("../ir.zig").Inst;
-const Type = @import("../type.zig").Type;
-const Value = @import("../value.zig").Value;
-
-fn genValtype(ty: Type) u8 {
- return switch (ty.tag()) {
- .u32, .i32 => 0x7F,
- .u64, .i64 => 0x7E,
- .f32 => 0x7D,
- .f64 => 0x7C,
- else => @panic("TODO: Implement more types for wasm."),
- };
-}
-
-pub fn genFunctype(buf: *ArrayList(u8), decl: *Decl) !void {
- const ty = decl.typed_value.most_recent.typed_value.ty;
- const writer = buf.writer();
-
- // functype magic
- try writer.writeByte(0x60);
-
- // param types
- try leb.writeULEB128(writer, @intCast(u32, ty.fnParamLen()));
- if (ty.fnParamLen() != 0) {
- const params = try buf.allocator.alloc(Type, ty.fnParamLen());
- defer buf.allocator.free(params);
- ty.fnParamTypes(params);
- for (params) |param_type| try writer.writeByte(genValtype(param_type));
- }
-
- // return type
- const return_type = ty.fnReturnType();
- switch (return_type.tag()) {
- .void, .noreturn => try leb.writeULEB128(writer, @as(u32, 0)),
- else => {
- try leb.writeULEB128(writer, @as(u32, 1));
- try writer.writeByte(genValtype(return_type));
- },
- }
-}
-
-pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
- assert(buf.items.len == 0);
- const writer = buf.writer();
-
- // Reserve space to write the size after generating the code
- try buf.resize(5);
-
- // Write the size of the locals vec
- // TODO: implement locals
- try leb.writeULEB128(writer, @as(u32, 0));
-
- // Write instructions
- // TODO: check for and handle death of instructions
- const tv = decl.typed_value.most_recent.typed_value;
- const mod_fn = tv.val.cast(Value.Payload.Function).?.func;
- for (mod_fn.analysis.success.instructions) |inst| try genInst(buf, decl, inst);
-
- // Write 'end' opcode
- try writer.writeByte(0x0B);
-
- // Fill in the size of the generated code to the reserved space at the
- // beginning of the buffer.
- const size = buf.items.len - 5 + decl.fn_link.wasm.?.idx_refs.items.len * 5;
- leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, size));
-}
-
-fn genInst(buf: *ArrayList(u8), decl: *Decl, inst: *Inst) !void {
- return switch (inst.tag) {
- .call => genCall(buf, decl, inst.castTag(.call).?),
- .constant => genConstant(buf, decl, inst.castTag(.constant).?),
- .dbg_stmt => {},
- .ret => genRet(buf, decl, inst.castTag(.ret).?),
- .retvoid => {},
- else => error.TODOImplementMoreWasmCodegen,
- };
-}
-
-fn genConstant(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Constant) !void {
- const writer = buf.writer();
- switch (inst.base.ty.tag()) {
- .u32 => {
- try writer.writeByte(0x41); // i32.const
- try leb.writeILEB128(writer, inst.val.toUnsignedInt());
- },
- .i32 => {
- try writer.writeByte(0x41); // i32.const
- try leb.writeILEB128(writer, inst.val.toSignedInt());
- },
- .u64 => {
- try writer.writeByte(0x42); // i64.const
- try leb.writeILEB128(writer, inst.val.toUnsignedInt());
- },
- .i64 => {
- try writer.writeByte(0x42); // i64.const
- try leb.writeILEB128(writer, inst.val.toSignedInt());
- },
- .f32 => {
- try writer.writeByte(0x43); // f32.const
- // TODO: enforce LE byte order
- try writer.writeAll(mem.asBytes(&inst.val.toFloat(f32)));
- },
- .f64 => {
- try writer.writeByte(0x44); // f64.const
- // TODO: enforce LE byte order
- try writer.writeAll(mem.asBytes(&inst.val.toFloat(f64)));
- },
- .void => {},
- else => return error.TODOImplementMoreWasmCodegen,
- }
-}
-
-fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void {
- try genInst(buf, decl, inst.operand);
-}
-
-fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void {
- const func_inst = inst.func.castTag(.constant).?;
- const func_val = func_inst.val.cast(Value.Payload.Function).?;
- const target = func_val.func.owner_decl;
- const target_ty = target.typed_value.most_recent.typed_value.ty;
-
- if (inst.args.len != 0) return error.TODOImplementMoreWasmCodegen;
-
- try buf.append(0x10); // call
-
- // The function index immediate argument will be filled in using this data
- // in link.Wasm.flush().
- try decl.fn_link.wasm.?.idx_refs.append(buf.allocator, .{
- .offset = @intCast(u32, buf.items.len),
- .decl = target,
- });
-}
diff --git a/src-self-hosted/codegen/x86.zig b/src-self-hosted/codegen/x86.zig
deleted file mode 100644
index fdad4e56db..0000000000
--- a/src-self-hosted/codegen/x86.zig
+++ /dev/null
@@ -1,123 +0,0 @@
-const std = @import("std");
-const DW = std.dwarf;
-
-// zig fmt: off
-pub const Register = enum(u8) {
- // 0 through 7, 32-bit registers. id is int value
- eax, ecx, edx, ebx, esp, ebp, esi, edi,
-
- // 8-15, 16-bit registers. id is int value - 8.
- ax, cx, dx, bx, sp, bp, si, di,
-
- // 16-23, 8-bit registers. id is int value - 16.
- al, cl, dl, bl, ah, ch, dh, bh,
-
- /// Returns the bit-width of the register.
- pub fn size(self: @This()) u7 {
- return switch (@enumToInt(self)) {
- 0...7 => 32,
- 8...15 => 16,
- 16...23 => 8,
- else => unreachable,
- };
- }
-
- /// Returns the register's id. This is used in practically every opcode the
- /// x86 has. It is embedded in some instructions, such as the `B8 +rd` move
- /// instruction, and is used in the R/M byte.
- pub fn id(self: @This()) u3 {
- return @truncate(u3, @enumToInt(self));
- }
-
- /// Returns the index into `callee_preserved_regs`.
- pub fn allocIndex(self: Register) ?u4 {
- return switch (self) {
- .eax, .ax, .al => 0,
- .ecx, .cx, .cl => 1,
- .edx, .dx, .dl => 2,
- .esi, .si => 3,
- .edi, .di => 4,
- else => null,
- };
- }
-
- /// Convert from any register to its 32 bit alias.
- pub fn to32(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()));
- }
-
- /// Convert from any register to its 16 bit alias.
- pub fn to16(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()) + 8);
- }
-
- /// Convert from any register to its 8 bit alias.
- pub fn to8(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()) + 16);
- }
-
-
- pub fn dwarfLocOp(reg: Register) u8 {
- return switch (reg.to32()) {
- .eax => DW.OP_reg0,
- .ecx => DW.OP_reg1,
- .edx => DW.OP_reg2,
- .ebx => DW.OP_reg3,
- .esp => DW.OP_reg4,
- .ebp => DW.OP_reg5,
- .esi => DW.OP_reg6,
- .edi => DW.OP_reg7,
- else => unreachable,
- };
- }
-};
-
-// zig fmt: on
-
-pub const callee_preserved_regs = [_]Register{ .eax, .ecx, .edx, .esi, .edi };
-
-// TODO add these to Register enum and corresponding dwarfLocOp
-// // Return Address register. This is stored in `0(%esp, "")` and is not a physical register.
-// RA = (8, "RA"),
-//
-// ST0 = (11, "st0"),
-// ST1 = (12, "st1"),
-// ST2 = (13, "st2"),
-// ST3 = (14, "st3"),
-// ST4 = (15, "st4"),
-// ST5 = (16, "st5"),
-// ST6 = (17, "st6"),
-// ST7 = (18, "st7"),
-//
-// XMM0 = (21, "xmm0"),
-// XMM1 = (22, "xmm1"),
-// XMM2 = (23, "xmm2"),
-// XMM3 = (24, "xmm3"),
-// XMM4 = (25, "xmm4"),
-// XMM5 = (26, "xmm5"),
-// XMM6 = (27, "xmm6"),
-// XMM7 = (28, "xmm7"),
-//
-// MM0 = (29, "mm0"),
-// MM1 = (30, "mm1"),
-// MM2 = (31, "mm2"),
-// MM3 = (32, "mm3"),
-// MM4 = (33, "mm4"),
-// MM5 = (34, "mm5"),
-// MM6 = (35, "mm6"),
-// MM7 = (36, "mm7"),
-//
-// MXCSR = (39, "mxcsr"),
-//
-// ES = (40, "es"),
-// CS = (41, "cs"),
-// SS = (42, "ss"),
-// DS = (43, "ds"),
-// FS = (44, "fs"),
-// GS = (45, "gs"),
-//
-// TR = (48, "tr"),
-// LDTR = (49, "ldtr"),
-//
-// FS_BASE = (93, "fs.base"),
-// GS_BASE = (94, "gs.base"),
diff --git a/src-self-hosted/codegen/x86_64.zig b/src-self-hosted/codegen/x86_64.zig
deleted file mode 100644
index dea39f82cd..0000000000
--- a/src-self-hosted/codegen/x86_64.zig
+++ /dev/null
@@ -1,220 +0,0 @@
-const std = @import("std");
-const Type = @import("../Type.zig");
-const DW = std.dwarf;
-
-// zig fmt: off
-
-/// Definitions of all of the x64 registers. The order is semantically meaningful.
-/// The registers are defined such that IDs go in descending order of 64-bit,
-/// 32-bit, 16-bit, and then 8-bit, and each set contains exactly sixteen
-/// registers. This results in some useful properties:
-///
-/// Any 64-bit register can be turned into its 32-bit form by adding 16, and
-/// vice versa. This also works between 32-bit and 16-bit forms. With 8-bit, it
-/// works for all except for sp, bp, si, and di, which do *not* have an 8-bit
-/// form.
-///
-/// If (register & 8) is set, the register is extended.
-///
-/// The ID can be easily determined by figuring out what range the register is
-/// in, and then subtracting the base.
-pub const Register = enum(u8) {
- // 0 through 15, 64-bit registers. 8-15 are extended.
- // id is just the int value.
- rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
- r8, r9, r10, r11, r12, r13, r14, r15,
-
- // 16 through 31, 32-bit registers. 24-31 are extended.
- // id is int value - 16.
- eax, ecx, edx, ebx, esp, ebp, esi, edi,
- r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d,
-
- // 32-47, 16-bit registers. 40-47 are extended.
- // id is int value - 32.
- ax, cx, dx, bx, sp, bp, si, di,
- r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w,
-
- // 48-63, 8-bit registers. 56-63 are extended.
- // id is int value - 48.
- al, cl, dl, bl, ah, ch, dh, bh,
- r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b,
-
- /// Returns the bit-width of the register.
- pub fn size(self: Register) u7 {
- return switch (@enumToInt(self)) {
- 0...15 => 64,
- 16...31 => 32,
- 32...47 => 16,
- 48...64 => 8,
- else => unreachable,
- };
- }
-
- /// Returns whether the register is *extended*. Extended registers are the
- /// new registers added with amd64, r8 through r15. This also includes any
- /// other variant of access to those registers, such as r8b, r15d, and so
- /// on. This is needed because access to these registers requires special
- /// handling via the REX prefix, via the B or R bits, depending on context.
- pub fn isExtended(self: Register) bool {
- return @enumToInt(self) & 0x08 != 0;
- }
-
- /// This returns the 4-bit register ID, which is used in practically every
- /// opcode. Note that bit 3 (the highest bit) is *never* used directly in
- /// an instruction (@see isExtended), and requires special handling. The
- /// lower three bits are often embedded directly in instructions (such as
- /// the B8 variant of moves), or used in R/M bytes.
- pub fn id(self: Register) u4 {
- return @truncate(u4, @enumToInt(self));
- }
-
- /// Returns the index into `callee_preserved_regs`.
- pub fn allocIndex(self: Register) ?u4 {
- return switch (self) {
- .rax, .eax, .ax, .al => 0,
- .rcx, .ecx, .cx, .cl => 1,
- .rdx, .edx, .dx, .dl => 2,
- .rsi, .esi, .si => 3,
- .rdi, .edi, .di => 4,
- .r8, .r8d, .r8w, .r8b => 5,
- .r9, .r9d, .r9w, .r9b => 6,
- .r10, .r10d, .r10w, .r10b => 7,
- .r11, .r11d, .r11w, .r11b => 8,
- else => null,
- };
- }
-
- /// Convert from any register to its 64 bit alias.
- pub fn to64(self: Register) Register {
- return @intToEnum(Register, self.id());
- }
-
- /// Convert from any register to its 32 bit alias.
- pub fn to32(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()) + 16);
- }
-
- /// Convert from any register to its 16 bit alias.
- pub fn to16(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()) + 32);
- }
-
- /// Convert from any register to its 8 bit alias.
- pub fn to8(self: Register) Register {
- return @intToEnum(Register, @as(u8, self.id()) + 48);
- }
-
- pub fn dwarfLocOp(self: Register) u8 {
- return switch (self.to64()) {
- .rax => DW.OP_reg0,
- .rdx => DW.OP_reg1,
- .rcx => DW.OP_reg2,
- .rbx => DW.OP_reg3,
- .rsi => DW.OP_reg4,
- .rdi => DW.OP_reg5,
- .rbp => DW.OP_reg6,
- .rsp => DW.OP_reg7,
-
- .r8 => DW.OP_reg8,
- .r9 => DW.OP_reg9,
- .r10 => DW.OP_reg10,
- .r11 => DW.OP_reg11,
- .r12 => DW.OP_reg12,
- .r13 => DW.OP_reg13,
- .r14 => DW.OP_reg14,
- .r15 => DW.OP_reg15,
-
- else => unreachable,
- };
- }
-};
-
-// zig fmt: on
-
-/// These registers belong to the called function.
-pub const callee_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 };
-pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
-pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };
-
-// TODO add these registers to the enum and populate dwarfLocOp
-// // Return Address register. This is stored in `0(%rsp, "")` and is not a physical register.
-// RA = (16, "RA"),
-//
-// XMM0 = (17, "xmm0"),
-// XMM1 = (18, "xmm1"),
-// XMM2 = (19, "xmm2"),
-// XMM3 = (20, "xmm3"),
-// XMM4 = (21, "xmm4"),
-// XMM5 = (22, "xmm5"),
-// XMM6 = (23, "xmm6"),
-// XMM7 = (24, "xmm7"),
-//
-// XMM8 = (25, "xmm8"),
-// XMM9 = (26, "xmm9"),
-// XMM10 = (27, "xmm10"),
-// XMM11 = (28, "xmm11"),
-// XMM12 = (29, "xmm12"),
-// XMM13 = (30, "xmm13"),
-// XMM14 = (31, "xmm14"),
-// XMM15 = (32, "xmm15"),
-//
-// ST0 = (33, "st0"),
-// ST1 = (34, "st1"),
-// ST2 = (35, "st2"),
-// ST3 = (36, "st3"),
-// ST4 = (37, "st4"),
-// ST5 = (38, "st5"),
-// ST6 = (39, "st6"),
-// ST7 = (40, "st7"),
-//
-// MM0 = (41, "mm0"),
-// MM1 = (42, "mm1"),
-// MM2 = (43, "mm2"),
-// MM3 = (44, "mm3"),
-// MM4 = (45, "mm4"),
-// MM5 = (46, "mm5"),
-// MM6 = (47, "mm6"),
-// MM7 = (48, "mm7"),
-//
-// RFLAGS = (49, "rFLAGS"),
-// ES = (50, "es"),
-// CS = (51, "cs"),
-// SS = (52, "ss"),
-// DS = (53, "ds"),
-// FS = (54, "fs"),
-// GS = (55, "gs"),
-//
-// FS_BASE = (58, "fs.base"),
-// GS_BASE = (59, "gs.base"),
-//
-// TR = (62, "tr"),
-// LDTR = (63, "ldtr"),
-// MXCSR = (64, "mxcsr"),
-// FCW = (65, "fcw"),
-// FSW = (66, "fsw"),
-//
-// XMM16 = (67, "xmm16"),
-// XMM17 = (68, "xmm17"),
-// XMM18 = (69, "xmm18"),
-// XMM19 = (70, "xmm19"),
-// XMM20 = (71, "xmm20"),
-// XMM21 = (72, "xmm21"),
-// XMM22 = (73, "xmm22"),
-// XMM23 = (74, "xmm23"),
-// XMM24 = (75, "xmm24"),
-// XMM25 = (76, "xmm25"),
-// XMM26 = (77, "xmm26"),
-// XMM27 = (78, "xmm27"),
-// XMM28 = (79, "xmm28"),
-// XMM29 = (80, "xmm29"),
-// XMM30 = (81, "xmm30"),
-// XMM31 = (82, "xmm31"),
-//
-// K0 = (118, "k0"),
-// K1 = (119, "k1"),
-// K2 = (120, "k2"),
-// K3 = (121, "k3"),
-// K4 = (122, "k4"),
-// K5 = (123, "k5"),
-// K6 = (124, "k6"),
-// K7 = (125, "k7"),