diff --git a/src-self-hosted/backend.zig b/src-self-hosted/backend.zig deleted file mode 100644 index 9222a6e3c349ef3e72e67da40a874e62ab842d6f..0000000000000000000000000000000000000000 --- a/src-self-hosted/backend.zig +++ /dev/null @@ -1,2 +0,0 @@ -pub const x86_64 = @import("backend/x86_64.zig"); -pub const x86 = @import("backend/x86.zig"); diff --git a/src-self-hosted/backend/x86.zig b/src-self-hosted/backend/x86.zig deleted file mode 100644 index 60872dedb9cff469ca62b743db9cde5cc1c135cc..0000000000000000000000000000000000000000 --- a/src-self-hosted/backend/x86.zig +++ /dev/null @@ -1,30 +0,0 @@ -// 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, bl, cl, dl, 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)); - } -}; - -// zig fmt: on diff --git a/src-self-hosted/backend/x86_64.zig b/src-self-hosted/backend/x86_64.zig deleted file mode 100644 index 0cc008ae1bbd43585efe5846906b441c400df824..0000000000000000000000000000000000000000 --- a/src-self-hosted/backend/x86_64.zig +++ /dev/null @@ -1,53 +0,0 @@ -// zig fmt: off -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, bl, cl, dl, ah, ch, dh, bh, - r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b, - - /// Returns the bit-width of the register. - pub fn size(self: @This()) 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: @This()) 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: @This()) u4 { - return @truncate(u4, @enumToInt(self)); - } -}; - -// zig fmt: on diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index fab3876d30f5989c2a4da8e85d7e997d0801ca4c..08a7b29ca3499def922a6c02ca4c693b9a582673 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -11,8 +11,6 @@ const ErrorMsg = Module.ErrorMsg; const Target = std.Target; const Allocator = mem.Allocator; -const Backend = @import("backend.zig"); - pub const Result = union(enum) { /// The `code` parameter passed to `generateSymbol` has the value appended. appended: void, @@ -194,14 +192,28 @@ const Function = struct { }, else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), } - return .unreach; + return .none; } fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue { + if (inst.args.func.cast(ir.Inst.Constant)) |func_inst| { + if (inst.args.args.len != 0) { + return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{}); + } + + if (func_inst.val.cast(Value.Payload.Function)) |func_val| { + const func = func_val.func; + return self.fail(inst.base.src, "TODO implement calling function", .{}); + } else { + return self.fail(inst.base.src, "TODO implement calling weird function values", .{}); + } + } else { + return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); + } + switch (self.target.cpu.arch) { else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), } - return .unreach; } fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue { @@ -589,10 +601,13 @@ const Function = struct { } }; +const x86_64 = @import("codegen/x86_64.zig"); +const x86 = @import("codegen/x86.zig"); + fn Reg(comptime arch: Target.Cpu.Arch) type { return switch (arch) { - .i386 => Backend.x86.Register, - .x86_64 => Backend.x86_64.Register, + .i386 => x86.Register, + .x86_64 => x86_64.Register, else => @compileError("TODO add more register enums"), }; } diff --git a/src-self-hosted/codegen/x86.zig b/src-self-hosted/codegen/x86.zig new file mode 100644 index 0000000000000000000000000000000000000000..60872dedb9cff469ca62b743db9cde5cc1c135cc --- /dev/null +++ b/src-self-hosted/codegen/x86.zig @@ -0,0 +1,30 @@ +// 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, bl, cl, dl, 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)); + } +}; + +// zig fmt: on diff --git a/src-self-hosted/codegen/x86_64.zig b/src-self-hosted/codegen/x86_64.zig new file mode 100644 index 0000000000000000000000000000000000000000..0cc008ae1bbd43585efe5846906b441c400df824 --- /dev/null +++ b/src-self-hosted/codegen/x86_64.zig @@ -0,0 +1,53 @@ +// zig fmt: off +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, bl, cl, dl, ah, ch, dh, bh, + r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b, + + /// Returns the bit-width of the register. + pub fn size(self: @This()) 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: @This()) 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: @This()) u4 { + return @truncate(u4, @enumToInt(self)); + } +}; + +// zig fmt: on