diff --git a/packages/cjit/src/Runtime.zig b/packages/cjit/src/Runtime.zig index 37f4098..060355d 100644 --- a/packages/cjit/src/Runtime.zig +++ b/packages/cjit/src/Runtime.zig @@ -87,8 +87,6 @@ pub fn deinit(self: *Self) void { } pub fn compile(self: *Self, filename: []const u8, code: []const u8) !void { - std.debug.assert(self.state == .init); - self.tokenizer.setSource(filename, code); while (try self.tokenizer.nextToken(self.arena.allocator())) |token| { _ = token; @@ -97,10 +95,11 @@ pub fn compile(self: *Self, filename: []const u8, code: []const u8) !void { } pub fn setSymbol(self: *Self, comptime T: type, name: []const u8, ptr: *const T) !void { - const symbol = self.symbols.getPtr(name) orelse return error.SymbolNotFound; + const symbol = self.symbols_needed.getPtr(name) orelse return error.SymbolNotFound; if (!types.isCompatible(T, symbol.c_type)) return error.IncompatibleType; - symbol.ptr = @ptrCast(ptr); + // TODO Figure out const-correctness + symbol.ptr = @ptrCast(@constCast(ptr)); } pub fn link(self: *Self) !void { @@ -121,7 +120,7 @@ pub fn link(self: *Self) !void { .global_offset_table => { std.mem.writeInt( usize, - self.sections.rodata.data[relocation.addr .. relocation.addr + @sizeOf(usize)], + self.sections.rodata.data.items[relocation.addr..][0..@sizeOf(usize)], target_addr, builtin.cpu.arch.endian(), ); @@ -129,10 +128,10 @@ pub fn link(self: *Self) !void { .rip_disp32 => { const rip = text_base + relocation.addr + 4; const disp64: isize = @bitCast(rip -% target_addr); - const disp32 = std.math.cast(i32, disp64) orelse error.RelocationError; + const disp32 = std.math.cast(i32, disp64) orelse return error.RelocationError; std.mem.writeInt( i32, - self.sections.text.data[relocation.addr .. relocation.addr + 4], + self.sections.text.data.items[relocation.addr..][0..4], disp32, builtin.cpu.arch.endian(), ); @@ -146,7 +145,7 @@ pub fn link(self: *Self) !void { } pub fn getSymbol(self: *const Self, comptime T: type, name: []const u8) ?*const T { - const symbol = self.symbols.get(name) orelse return null; + const symbol = self.symbols_located.get(name) orelse return null; return @ptrCast(@alignCast(symbol.ptr)); } diff --git a/packages/cjit/src/Sections.zig b/packages/cjit/src/Sections.zig index e83a410..378cb3e 100644 --- a/packages/cjit/src/Sections.zig +++ b/packages/cjit/src/Sections.zig @@ -112,7 +112,7 @@ pub fn relocateSections(self: *Self, allocator: std.mem.Allocator) !void { @memcpy(text_slice[0..self.text.data.items.len], self.text.data.items); @memcpy(data_slice[0..self.data.data.items.len], self.data.data.items); - @memcpy(rodata_slice[0..self.rodata_slice.data.items.len], self.rodata.data.items); + @memcpy(rodata_slice[0..self.rodata.data.items.len], self.rodata.data.items); self.text.data.clearAndFree(allocator); self.data.data.clearAndFree(allocator); @@ -124,7 +124,7 @@ pub fn relocateSections(self: *Self, allocator: std.mem.Allocator) !void { } pub fn protectSections(self: *Self) !void { - const sections: []*Section = .{ &self.text, &self.data, &self.rodata }; + const sections = [_]*Section{ &self.text, &self.data, &self.rodata }; for (sections) |section| { switch (builtin.os.tag) { @@ -157,7 +157,7 @@ pub fn protectSections(self: *Self) !void { .linux => { const linux = std.os.linux; - const protection = switch (section.protection) { + const protection: usize = switch (section.protection) { .executable => linux.PROT.EXEC, .read_only => linux.PROT.READ, .read_write => linux.PROT.READ | linux.PROT.WRITE, diff --git a/packages/cjit/src/tokens/Punctuator.zig b/packages/cjit/src/tokens/Punctuator.zig index 93f8c70..7cc2371 100644 --- a/packages/cjit/src/tokens/Punctuator.zig +++ b/packages/cjit/src/tokens/Punctuator.zig @@ -57,14 +57,14 @@ pub const Punctuator = enum(u32) { pub const line_continuation_crlf = strToInt3("\\\r\n"); }; -fn strToInt1(str: *const u8[1]) u32 { +fn strToInt1(str: *const [1]u8) u32 { return @as(u8, @bitCast(str.*)); } -fn strToInt2(str: *const u8[2]) u32 { +fn strToInt2(str: *const [2]u8) u32 { return @as(u16, @bitCast(str.*)); } -fn strToInt3(str: *const u8[3]) u32 { +fn strToInt3(str: *const [3]u8) u32 { return @as(u24, @bitCast(str.*)); } diff --git a/packages/cjit/src/tokens/Tokenizer.zig b/packages/cjit/src/tokens/Tokenizer.zig index 4c564ef..8a6405e 100644 --- a/packages/cjit/src/tokens/Tokenizer.zig +++ b/packages/cjit/src/tokens/Tokenizer.zig @@ -20,7 +20,7 @@ wide_string: std.ArrayList(u32), pub fn init(arena_allocator: std.mem.Allocator) !Self { const string_buffer = try arena_allocator.alloc(u8, max_string_length); - const wide_string_buffer = try arena_allocator.alloc(u8, max_wide_string_length); + const wide_string_buffer = try arena_allocator.alloc(u32, max_wide_string_length); return .{ .string = .initBuffer(string_buffer), @@ -34,7 +34,7 @@ pub fn setSource(self: *Self, filename: []const u8, code: []const u8) void { } pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token { - self.skipWhitespace(); + try self.skipWhitespace(); // TODO Skip C and C++ style comments // TODO Preprocessor directives @@ -53,7 +53,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token { const state = self.it.save(); self.it.advanceCodepoint(cp); - const cp2 = self.peekCodepointSkipLineContinuation() orelse 0; + const cp2 = try self.peekCodepointSkipLineContinuation() orelse 0; switch (cp2) { // Wide string @@ -83,7 +83,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token { next_cp = try self.peekCodepointSkipLineContinuation(); } - const identifier = self.str[identifier_start..self.it.ptr]; + const identifier = self.it.str[identifier_start..self.it.ptr]; // TODO Preprocessor @@ -92,7 +92,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token { } else if (Builtin.isBuiltin(identifier)) |builtin| { return .{ .builtin = builtin }; } else { - return .{ .identifier = arena_allocator.dupe(u8, identifier) }; + return .{ .identifier = try arena_allocator.dupe(u8, identifier) }; } }, // String @@ -106,6 +106,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token { self.it.advanceCodepoint(cp); // TODO Parse char }, + else => {}, } // Higher code points should've been already handled. The code below may @@ -245,7 +246,7 @@ fn skipWhitespace(self: *Self) !void { 0x000D, // Space (SP) 0x0020, - => try self.it.advanceCodepoint(cp), + => self.it.advanceCodepoint(cp), else => return, } } diff --git a/packages/cjit/src/tokens/Utf8Iterator.zig b/packages/cjit/src/tokens/Utf8Iterator.zig index acf4283..07e6625 100644 --- a/packages/cjit/src/tokens/Utf8Iterator.zig +++ b/packages/cjit/src/tokens/Utf8Iterator.zig @@ -78,10 +78,6 @@ pub fn peekThreeBytes(self: Self) ?u32 { } } -pub fn advanceAsciiBytes(self: *Self, bytes: usize) void { - std.debug.assert(self.str.ptr + bytes <= self.str.len); -} - /// Call with value returned by `peekCodepoint`. pub fn advanceCodepoint(self: *Self, cp: u21) void { std.debug.assert(blk: { diff --git a/packages/cjit/src/x86_64.zig b/packages/cjit/src/x86_64.zig index 0de4f8a..6e64c4b 100644 --- a/packages/cjit/src/x86_64.zig +++ b/packages/cjit/src/x86_64.zig @@ -36,7 +36,7 @@ pub const Gpr = enum(u4) { } pub fn x(self: Gpr) bool { - return @intFromEnum(self & 0b1000) != 0; + return @intFromEnum(self) & 0b1000 != 0; } }; @@ -63,17 +63,17 @@ pub const Xmm = enum(u4) { } pub fn x(self: Xmm) bool { - return @intFromEnum(self & 0b1000) != 0; + return @intFromEnum(self) & 0b1000 != 0; } }; // --- EMIT HELPERS ------------------------------------------------------------ pub const Rex = packed struct(u8) { - b: bool, - x: bool, - r: bool, - w: bool, + b: bool = false, + x: bool = false, + r: bool = false, + w: bool = false, /// MUST always be the default value prefix: u4 = 0b0100, }; @@ -127,19 +127,19 @@ pub fn imm8(rt: *Runtime, value: u8) !void { pub fn imm16(rt: *Runtime, value: u16) !void { var bytes: [2]u8 = undefined; std.mem.writeInt(u16, &bytes, value, .little); - try rt.sections.text.writeBytes(value, rt.allocator); + try rt.sections.text.writeBytes(&bytes, rt.allocator); } pub fn imm32(rt: *Runtime, value: u32) !void { var bytes: [4]u8 = undefined; std.mem.writeInt(u32, &bytes, value, .little); - try rt.sections.text.writeBytes(value, rt.allocator); + try rt.sections.text.writeBytes(&bytes, rt.allocator); } pub fn imm64(rt: *Runtime, value: u64) !void { var bytes: [8]u8 = undefined; std.mem.writeInt(u64, &bytes, value, .little); - try rt.sections.text.writeBytes(value, rt.allocator); + try rt.sections.text.writeBytes(&bytes, rt.allocator); } pub fn disp8(rt: *Runtime, value: i8) !void { @@ -149,7 +149,7 @@ pub fn disp8(rt: *Runtime, value: i8) !void { pub fn disp32(rt: *Runtime, value: i32) !void { var bytes: [4]u8 = undefined; std.mem.writeInt(i32, &bytes, value, .little); - try rt.sections.text.writeBytes(bytes, rt.allocator); + try rt.sections.text.writeBytes(&bytes, rt.allocator); } // ----------------------------------------------------------------------------- @@ -234,7 +234,8 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue) switch (src_value.value) { .register => |src_register| { - if (dst_register == src_register) return; + if (std.meta.eql(dst_register, src_register)) return; + // TODO }, .constant => |constant| switch (dst_register) { .gpr => |dest_gpr| switch (size) { @@ -246,7 +247,7 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue) // otherwise ah, ch, dh and bh would be used. try rex(rt, .{ .r = dest_gpr.x() }); } - try op(rt, 0xB0 | dest_gpr.reg()); + try op(rt, 0xB0 | @as(u8, dest_gpr.reg())); try imm8(rt, @truncate(constant)); }, 2 => { @@ -256,7 +257,7 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue) if (@intFromEnum(dest_gpr) >= 8) { try rex(rt, .{ .r = dest_gpr.x() }); } - try op(rt, 0xB8 | dest_gpr.reg()); + try op(rt, 0xB8 | @as(u8, dest_gpr.reg())); try imm16(rt, @truncate(constant)); }, 4 => { @@ -265,14 +266,14 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue) if (@intFromEnum(dest_gpr) >= 8) { try rex(rt, .{ .r = dest_gpr.x() }); } - try op(rt, 0xB8 | dest_gpr.reg()); + try op(rt, 0xB8 | @as(u8, dest_gpr.reg())); try imm32(rt, @truncate(constant)); }, 8 => { // MOV r64, imm64 // REX.W + B8+ rd io try rex(rt, .{ .r = dest_gpr.x(), .w = true }); - try op(rt, 0xB8 | dest_gpr.reg()); + try op(rt, 0xB8 | @as(u8, dest_gpr.reg())); try imm64(rt, constant); }, else => unreachable, @@ -295,7 +296,7 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue) try op2(rt, 0x0F, 0x6E); // [rip + disp32] try modrm(rt, .{ .mod = 0b00, .reg = dest_xmm.reg(), .rm = Gpr.rbp.reg() }); - try allocRodataDisp32(rt, &data); + try allocRodataDisp32(rt, data); }, }, .symbol => |symbol| {}, diff --git a/packages/cjit/test/root.zig b/packages/cjit/test/root.zig index 5bffa90..288abad 100644 --- a/packages/cjit/test/root.zig +++ b/packages/cjit/test/root.zig @@ -9,7 +9,7 @@ test { var rt: cjit.Runtime = try .init(std.testing.allocator); defer rt.deinit(); - try rt.compile( + try rt.compile("test.c", \\int add(int a, int b); \\ \\int add_one(int x)