This commit is contained in:
David Gonzalez Martin 2025-04-20 21:20:12 -06:00
parent b8873564af
commit 1d9a43d66d
2 changed files with 287 additions and 10 deletions

View File

@ -516,6 +516,7 @@ pub const Type = struct {
.integer => |integer| integer.signed,
.bits => |bits| bits.backing_type.is_signed(),
.enumerator => |enumerator| enumerator.backing_type.is_signed(),
.alias => |alias| alias.type.is_signed(),
else => @trap(),
};
}
@ -602,6 +603,7 @@ pub const Type = struct {
.array => |array| array.element_type.get_bit_size() * array.element_count,
.structure => |structure| structure.bit_size,
.enumerator => |enumerator| enumerator.backing_type.get_bit_size(),
.alias => |alias| alias.type.get_bit_size(),
else => @trap(),
};
return bit_size;
@ -3880,7 +3882,7 @@ pub const Module = struct {
const backing_type = maybe_backing_type orelse blk: {
const bits_needed = 64 - @clz(highest_value);
const int_type = module.integer_type(bits_needed, false);
const int_type = module.integer_type(if (bits_needed == 0) 1 else bits_needed, false);
break :blk int_type;
};
@ -5472,7 +5474,10 @@ pub const Module = struct {
pub fn check_types(module: *Module, expected_type: *Type, source_type: *Type) void {
if (expected_type != source_type) {
const dst_p_src_i = expected_type.bb == .pointer and source_type.bb == .integer;
const result = dst_p_src_i;
const dst_alias_src_not = expected_type.bb == .alias and expected_type.bb.alias.type == source_type;
const src_alias_dst_not = source_type.bb == .alias and source_type.bb.alias.type == expected_type;
const both_alias_to_same_type = expected_type.bb == .alias and source_type.bb == .alias and expected_type.bb.alias.type == source_type.bb.alias.type;
const result = dst_p_src_i or dst_alias_src_not or src_alias_dst_not or both_alias_to_same_type;
if (!result) {
module.report_error();
}
@ -6782,7 +6787,11 @@ pub const Module = struct {
}
const llvm_value = extended_value.llvm orelse unreachable;
const destination_type = value_type.llvm.abi.?;
const extension_instruction = switch (extended_value.type.?.bb.integer.signed) {
const extension_type = switch (extended_value.type.?.bb) {
.alias => |alias| alias.type,
else => extended_value.type.?,
};
const extension_instruction = switch (extension_type.bb.integer.signed) {
true => module.llvm.builder.create_sign_extend(llvm_value, destination_type),
false => module.llvm.builder.create_zero_extend(llvm_value, destination_type),
};

View File

@ -1,9 +1,85 @@
mode_t = typealias u64;
int = typealias s32;
usize = typealias u64;
ssize = typealias s64;
File = typealias s32;
[extern] memcmp = fn [cc(c)] (a: &u8, b: &u8, byte_count: u64) s32;
uid_t = typealias u32;
gid_t = typealias u32;
off_t = typealias s64;
ino_t = typealias u64;
dev_t = typealias u64;
timespec = struct
{
seconds: ssize,
nanoseconds: ssize,
};
Stat = struct
{
dev: dev_t,
ino: ino_t,
nlink: usize,
mode: u32,
uid: uid_t,
gid: gid_t,
_: u32,
rdev: dev_t,
size: off_t,
blksize: ssize,
blocks: s64,
atim: timespec,
mtime: timespec,
ctim: timespec,
_: [3]ssize,
}
OAccessMode = enum u2
{
read_only = 0,
write_only = 1,
read_write = 2,
}
O = bits u32
{
access_mode: OAccessMode,
_: u4,
creat: u1,
excl: u1,
noctty: u1,
trunc: u1,
append: u1,
nonblock: u1,
dsync: u1,
async: u1,
direct: u1,
_: u1,
directory: u1,
nofollow: u1,
noatime: u1,
cloexec: u1,
sync: u1,
path: u1,
tmpfile: u1,
_: u9,
}
[extern] memcmp = fn [cc(c)] (a: &u8, b: &u8, byte_count: usize) int;
[extern] memcpy = fn [cc(c)] (destination: &u8, source: &u8, byte_count: u64) &u8;
[extern] exit = fn [cc(c)] (exit_code: s32) noreturn;
[extern] mkdir = fn [cc(c)] (path: &u8, mode: mode_t) s32;
[extern] exit = fn [cc(c)] (exit_code: int) noreturn;
[extern] realpath = fn [cc(c)] (source_path: &u8, resolved_path: &u8) &u8;
[extern] mkdir = fn [cc(c)] (path: &u8, mode: mode_t) int;
[extern] open = fn [cc(c)] (path: &u8, o: O, ...) int;
[extern] close = fn [cc(c)] (fd: File) int;
[extern] fstat = fn [cc(c)] (fd: File, s: &Stat) int;
[extern] write = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
[extern] read = fn [cc(c)] (fd: File, pointer: &u8, byte_count: u64) ssize;
assert = fn (ok: u1) void
{
@ -177,6 +253,109 @@ os_make_directory = fn (path: &u8) void
>result = mkdir(path, 0o755);
}
OpenFlags = bits
{
truncate: u1,
execute: u1,
write: u1,
read: u1,
create: u1,
directory: u1,
}
OpenPermissions = bits
{
read: u1,
write: u1,
execute: u1,
}
os_file_open = fn (path: &u8, flags: OpenFlags, permissions: OpenPermissions) File
{
>access_mode: OAccessMode = undefined;
if (flags.read and flags.write)
{
access_mode = .read_write;
}
else if (flags.read)
{
access_mode = .read_only;
}
else if (flags.write)
{
access_mode = .write_only;
}
else
{
unreachable;
}
>o: O = {
.access_mode = access_mode,
.trunc = flags.truncate,
.creat = flags.create,
.directory = flags.directory,
};
>mode: mode_t = #select(permissions.execute, 0o755, 0o644);
>fd = open(path, o, mode);
return fd;
}
os_file_close = fn (fd: File) void
{
>result = close(fd);
assert(result == 0);
}
os_file_is_valid = fn (fd: File) u1
{
return fd >= 0;
}
os_file_get_size = fn (fd: File) u64
{
>stat: Stat = undefined;
>result = fstat(fd, &stat);
assert(result == 0);
return #extend(stat.size);
}
os_file_read_partially = fn (fd: File, pointer: &u8, length: u64) u64
{
>result = read(fd, pointer, length);
assert(result > 0);
return #extend(result);
}
os_file_read = fn (fd: File, buffer: []u8, byte_count: u64) void
{
assert(byte_count <= buffer.length);
>total_read_byte_count: u64 = 0;
while (total_read_byte_count < byte_count)
{
>read_byte_count = os_file_read_partially(fd, buffer.pointer + total_read_byte_count, byte_count - total_read_byte_count);
total_read_byte_count += read_byte_count;
}
}
os_path_absolute_stack = fn (buffer: []u8, relative_file_path: &u8) []u8
{
>syscall_result = realpath(relative_file_path, buffer.pointer);
>result: []u8 = zero;
if (syscall_result)
{
result = c_string_to_slice(syscall_result);
assert(result.length < buffer.length);
}
return result;
}
Arena = struct
{
reserved_size: u64,
@ -264,6 +443,13 @@ arena_allocate_bytes = fn (arena: &Arena, size: u64, alignment: u64) &u8
return result;
}
arena_duplicate_string = fn (arena: &Arena, string: []u8) []u8
{
>result = arena_allocate_bytes(arena, string.length + 1, 1);
memcpy(result, string.pointer, string.length);
return result[..string.length];
}
arena_join_string = fn (arena: &Arena, pieces: [][]u8) []u8
{
>size: u64 = 0;
@ -288,6 +474,32 @@ arena_join_string = fn (arena: &Arena, pieces: [][]u8) []u8
return pointer[..size];
}
file_read = fn (arena: &Arena, path: []u8) []u8
{
>fd = os_file_open(path.pointer, { .read = 1 }, { .read = 1 });
>result: []u8 = zero;
if (os_file_is_valid(fd))
{
>file_size = os_file_get_size(fd);
>file_buffer = arena_allocate_bytes(arena, file_size, 1);
result = file_buffer[..file_size];
os_file_read(fd, result, file_size);
os_file_close(fd);
}
return result;
}
path_absolute = fn (arena: &Arena, relative_file_path: &u8) []u8
{
>buffer: [4096]u8 = undefined;
>stack_slice = os_path_absolute_stack(buffer[..], relative_file_path);
>result = arena_duplicate_string(arena, stack_slice);
return result;
}
GlobalState = struct
{
arena: &Arena,
@ -335,9 +547,42 @@ CompileFile = struct
base_cache_dir = "bb-cache";
compile_file = fn (arena: &Arena, compile: CompileFile) void
CPUArchitecture = enum
{
>relative_file_path = compile.relative_file_path;
x86_64,
}
OperatingSystem = enum
{
linux,
}
Target = struct
{
cpu: CPUArchitecture,
os: OperatingSystem,
}
CompileOptions = struct
{
content: []u8,
path: []u8,
executable: []u8,
name: []u8,
objects: [][]u8,
target: Target,
build_mode: BuildMode,
has_debug_info: u1,
silent: u1,
}
compile = fn (arena: &Arena, options: CompileOptions) void
{
}
compile_file = fn (arena: &Arena, compile_options: CompileFile) void
{
>relative_file_path = compile_options.relative_file_path;
if (relative_file_path.length < 5)
{
fail();
@ -367,10 +612,33 @@ compile_file = fn (arena: &Arena, compile: CompileFile) void
>outputh_path_dir = arena_join_string(arena, [
base_cache_dir,
#select(is_compiler, "/compiler/", "/"),
#enum_name(compile.build_mode),
#enum_name(compile_options.build_mode),
"_",
#select(compile.has_debug_info, "di", "nodi"),
#select(compile_options.has_debug_info, "di", "nodi"),
][..]);
os_make_directory(base_cache_dir.pointer);
if (is_compiler)
{
>compiler_dir = arena_join_string(arena, [ base_cache_dir, "/compiler" ][..]);
os_make_directory(compiler_dir.pointer);
}
os_make_directory(outputh_path_dir.pointer);
>outputh_path_base = arena_join_string(arena, [ outputh_path_dir, "/", base_name ][..]);
>output_object_path = arena_join_string(arena, [ outputh_path_base, ".o" ][..]);
>output_executable_path = outputh_path_base;
>file_content = file_read(arena, relative_file_path);
>file_path = path_absolute(arena, relative_file_path.pointer);
>c_abi_object_path = ""; // TODO
>options: CompileOptions = {
zero,
};
compile(arena, options);
}
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8) s32