cjit: Fix some compilation errors
This commit is contained in:
@@ -87,8 +87,6 @@ pub fn deinit(self: *Self) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(self: *Self, filename: []const u8, code: []const u8) !void {
|
pub fn compile(self: *Self, filename: []const u8, code: []const u8) !void {
|
||||||
std.debug.assert(self.state == .init);
|
|
||||||
|
|
||||||
self.tokenizer.setSource(filename, code);
|
self.tokenizer.setSource(filename, code);
|
||||||
while (try self.tokenizer.nextToken(self.arena.allocator())) |token| {
|
while (try self.tokenizer.nextToken(self.arena.allocator())) |token| {
|
||||||
_ = 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 {
|
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;
|
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 {
|
pub fn link(self: *Self) !void {
|
||||||
@@ -121,7 +120,7 @@ pub fn link(self: *Self) !void {
|
|||||||
.global_offset_table => {
|
.global_offset_table => {
|
||||||
std.mem.writeInt(
|
std.mem.writeInt(
|
||||||
usize,
|
usize,
|
||||||
self.sections.rodata.data[relocation.addr .. relocation.addr + @sizeOf(usize)],
|
self.sections.rodata.data.items[relocation.addr..][0..@sizeOf(usize)],
|
||||||
target_addr,
|
target_addr,
|
||||||
builtin.cpu.arch.endian(),
|
builtin.cpu.arch.endian(),
|
||||||
);
|
);
|
||||||
@@ -129,10 +128,10 @@ pub fn link(self: *Self) !void {
|
|||||||
.rip_disp32 => {
|
.rip_disp32 => {
|
||||||
const rip = text_base + relocation.addr + 4;
|
const rip = text_base + relocation.addr + 4;
|
||||||
const disp64: isize = @bitCast(rip -% target_addr);
|
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(
|
std.mem.writeInt(
|
||||||
i32,
|
i32,
|
||||||
self.sections.text.data[relocation.addr .. relocation.addr + 4],
|
self.sections.text.data.items[relocation.addr..][0..4],
|
||||||
disp32,
|
disp32,
|
||||||
builtin.cpu.arch.endian(),
|
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 {
|
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));
|
return @ptrCast(@alignCast(symbol.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(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(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.text.data.clearAndFree(allocator);
|
||||||
self.data.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 {
|
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| {
|
for (sections) |section| {
|
||||||
switch (builtin.os.tag) {
|
switch (builtin.os.tag) {
|
||||||
@@ -157,7 +157,7 @@ pub fn protectSections(self: *Self) !void {
|
|||||||
.linux => {
|
.linux => {
|
||||||
const linux = std.os.linux;
|
const linux = std.os.linux;
|
||||||
|
|
||||||
const protection = switch (section.protection) {
|
const protection: usize = switch (section.protection) {
|
||||||
.executable => linux.PROT.EXEC,
|
.executable => linux.PROT.EXEC,
|
||||||
.read_only => linux.PROT.READ,
|
.read_only => linux.PROT.READ,
|
||||||
.read_write => linux.PROT.READ | linux.PROT.WRITE,
|
.read_write => linux.PROT.READ | linux.PROT.WRITE,
|
||||||
|
|||||||
@@ -57,14 +57,14 @@ pub const Punctuator = enum(u32) {
|
|||||||
pub const line_continuation_crlf = strToInt3("\\\r\n");
|
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.*));
|
return @as(u8, @bitCast(str.*));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strToInt2(str: *const u8[2]) u32 {
|
fn strToInt2(str: *const [2]u8) u32 {
|
||||||
return @as(u16, @bitCast(str.*));
|
return @as(u16, @bitCast(str.*));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strToInt3(str: *const u8[3]) u32 {
|
fn strToInt3(str: *const [3]u8) u32 {
|
||||||
return @as(u24, @bitCast(str.*));
|
return @as(u24, @bitCast(str.*));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ wide_string: std.ArrayList(u32),
|
|||||||
|
|
||||||
pub fn init(arena_allocator: std.mem.Allocator) !Self {
|
pub fn init(arena_allocator: std.mem.Allocator) !Self {
|
||||||
const string_buffer = try arena_allocator.alloc(u8, max_string_length);
|
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 .{
|
return .{
|
||||||
.string = .initBuffer(string_buffer),
|
.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 {
|
pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token {
|
||||||
self.skipWhitespace();
|
try self.skipWhitespace();
|
||||||
|
|
||||||
// TODO Skip C and C++ style comments
|
// TODO Skip C and C++ style comments
|
||||||
// TODO Preprocessor directives
|
// TODO Preprocessor directives
|
||||||
@@ -53,7 +53,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token {
|
|||||||
const state = self.it.save();
|
const state = self.it.save();
|
||||||
|
|
||||||
self.it.advanceCodepoint(cp);
|
self.it.advanceCodepoint(cp);
|
||||||
const cp2 = self.peekCodepointSkipLineContinuation() orelse 0;
|
const cp2 = try self.peekCodepointSkipLineContinuation() orelse 0;
|
||||||
|
|
||||||
switch (cp2) {
|
switch (cp2) {
|
||||||
// Wide string
|
// Wide string
|
||||||
@@ -83,7 +83,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token {
|
|||||||
next_cp = try self.peekCodepointSkipLineContinuation();
|
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
|
// TODO Preprocessor
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token {
|
|||||||
} else if (Builtin.isBuiltin(identifier)) |builtin| {
|
} else if (Builtin.isBuiltin(identifier)) |builtin| {
|
||||||
return .{ .builtin = builtin };
|
return .{ .builtin = builtin };
|
||||||
} else {
|
} else {
|
||||||
return .{ .identifier = arena_allocator.dupe(u8, identifier) };
|
return .{ .identifier = try arena_allocator.dupe(u8, identifier) };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// String
|
// String
|
||||||
@@ -106,6 +106,7 @@ pub fn nextToken(self: *Self, arena_allocator: std.mem.Allocator) !?Token {
|
|||||||
self.it.advanceCodepoint(cp);
|
self.it.advanceCodepoint(cp);
|
||||||
// TODO Parse char
|
// TODO Parse char
|
||||||
},
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Higher code points should've been already handled. The code below may
|
// Higher code points should've been already handled. The code below may
|
||||||
@@ -245,7 +246,7 @@ fn skipWhitespace(self: *Self) !void {
|
|||||||
0x000D,
|
0x000D,
|
||||||
// Space (SP)
|
// Space (SP)
|
||||||
0x0020,
|
0x0020,
|
||||||
=> try self.it.advanceCodepoint(cp),
|
=> self.it.advanceCodepoint(cp),
|
||||||
else => return,
|
else => return,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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`.
|
/// Call with value returned by `peekCodepoint`.
|
||||||
pub fn advanceCodepoint(self: *Self, cp: u21) void {
|
pub fn advanceCodepoint(self: *Self, cp: u21) void {
|
||||||
std.debug.assert(blk: {
|
std.debug.assert(blk: {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ pub const Gpr = enum(u4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn x(self: Gpr) bool {
|
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 {
|
pub fn x(self: Xmm) bool {
|
||||||
return @intFromEnum(self & 0b1000) != 0;
|
return @intFromEnum(self) & 0b1000 != 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- EMIT HELPERS ------------------------------------------------------------
|
// --- EMIT HELPERS ------------------------------------------------------------
|
||||||
|
|
||||||
pub const Rex = packed struct(u8) {
|
pub const Rex = packed struct(u8) {
|
||||||
b: bool,
|
b: bool = false,
|
||||||
x: bool,
|
x: bool = false,
|
||||||
r: bool,
|
r: bool = false,
|
||||||
w: bool,
|
w: bool = false,
|
||||||
/// MUST always be the default value
|
/// MUST always be the default value
|
||||||
prefix: u4 = 0b0100,
|
prefix: u4 = 0b0100,
|
||||||
};
|
};
|
||||||
@@ -127,19 +127,19 @@ pub fn imm8(rt: *Runtime, value: u8) !void {
|
|||||||
pub fn imm16(rt: *Runtime, value: u16) !void {
|
pub fn imm16(rt: *Runtime, value: u16) !void {
|
||||||
var bytes: [2]u8 = undefined;
|
var bytes: [2]u8 = undefined;
|
||||||
std.mem.writeInt(u16, &bytes, value, .little);
|
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 {
|
pub fn imm32(rt: *Runtime, value: u32) !void {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
std.mem.writeInt(u32, &bytes, value, .little);
|
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 {
|
pub fn imm64(rt: *Runtime, value: u64) !void {
|
||||||
var bytes: [8]u8 = undefined;
|
var bytes: [8]u8 = undefined;
|
||||||
std.mem.writeInt(u64, &bytes, value, .little);
|
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 {
|
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 {
|
pub fn disp32(rt: *Runtime, value: i32) !void {
|
||||||
var bytes: [4]u8 = undefined;
|
var bytes: [4]u8 = undefined;
|
||||||
std.mem.writeInt(i32, &bytes, value, .little);
|
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) {
|
switch (src_value.value) {
|
||||||
.register => |src_register| {
|
.register => |src_register| {
|
||||||
if (dst_register == src_register) return;
|
if (std.meta.eql(dst_register, src_register)) return;
|
||||||
|
// TODO
|
||||||
},
|
},
|
||||||
.constant => |constant| switch (dst_register) {
|
.constant => |constant| switch (dst_register) {
|
||||||
.gpr => |dest_gpr| switch (size) {
|
.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.
|
// otherwise ah, ch, dh and bh would be used.
|
||||||
try rex(rt, .{ .r = dest_gpr.x() });
|
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));
|
try imm8(rt, @truncate(constant));
|
||||||
},
|
},
|
||||||
2 => {
|
2 => {
|
||||||
@@ -256,7 +257,7 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue)
|
|||||||
if (@intFromEnum(dest_gpr) >= 8) {
|
if (@intFromEnum(dest_gpr) >= 8) {
|
||||||
try rex(rt, .{ .r = dest_gpr.x() });
|
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));
|
try imm16(rt, @truncate(constant));
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
@@ -265,14 +266,14 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue)
|
|||||||
if (@intFromEnum(dest_gpr) >= 8) {
|
if (@intFromEnum(dest_gpr) >= 8) {
|
||||||
try rex(rt, .{ .r = dest_gpr.x() });
|
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));
|
try imm32(rt, @truncate(constant));
|
||||||
},
|
},
|
||||||
8 => {
|
8 => {
|
||||||
// MOV r64, imm64
|
// MOV r64, imm64
|
||||||
// REX.W + B8+ rd io
|
// REX.W + B8+ rd io
|
||||||
try rex(rt, .{ .r = dest_gpr.x(), .w = true });
|
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);
|
try imm64(rt, constant);
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@@ -295,7 +296,7 @@ pub fn load(rt: *Runtime, dst_register: Register, src_value: *const StackValue)
|
|||||||
try op2(rt, 0x0F, 0x6E);
|
try op2(rt, 0x0F, 0x6E);
|
||||||
// [rip + disp32]
|
// [rip + disp32]
|
||||||
try modrm(rt, .{ .mod = 0b00, .reg = dest_xmm.reg(), .rm = Gpr.rbp.reg() });
|
try modrm(rt, .{ .mod = 0b00, .reg = dest_xmm.reg(), .rm = Gpr.rbp.reg() });
|
||||||
try allocRodataDisp32(rt, &data);
|
try allocRodataDisp32(rt, data);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.symbol => |symbol| {},
|
.symbol => |symbol| {},
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ test {
|
|||||||
var rt: cjit.Runtime = try .init(std.testing.allocator);
|
var rt: cjit.Runtime = try .init(std.testing.allocator);
|
||||||
defer rt.deinit();
|
defer rt.deinit();
|
||||||
|
|
||||||
try rt.compile(
|
try rt.compile("test.c",
|
||||||
\\int add(int a, int b);
|
\\int add(int a, int b);
|
||||||
\\
|
\\
|
||||||
\\int add_one(int x)
|
\\int add_one(int x)
|
||||||
|
|||||||
Reference in New Issue
Block a user