This commit is contained in:
David Gonzalez Martin 2025-06-19 11:49:21 -06:00
parent 14f856b550
commit ec13634b8c
2 changed files with 206 additions and 42 deletions

View File

@ -101,6 +101,29 @@ assert = macro (ok: u1) void
} }
} }
ArgumentBuilder = struct
{
buffer: [128]&u8,
count: u64,
}
add_argument = fn (builder: &ArgumentBuilder, argument: []u8) void
{
assert(argument.pointer[argument.length] == 0);
>index = builder.count;
assert(index < builder.buffer.length);
builder.buffer[index] = argument.pointer;
builder.count = index + 1;
}
flush_arguments = fn (builder: &ArgumentBuilder) []&u8
{
>argument_count = builder.count;
assert(argument_count < builder.buffer.length);
builder.buffer[argument_count] = zero;
return builder.buffer[..argument_count];
}
align_forward = fn (value: u64, alignment: u64) u64 align_forward = fn (value: u64, alignment: u64) u64
{ {
assert(alignment != 0); assert(alignment != 0);
@ -154,6 +177,22 @@ string_equal = fn(a: []u8, b: []u8) u1
return result; return result;
} }
string_first_character = fn (string: []u8, character: u8) u64
{
>result = string_no_match;
for (i: 0..string.length)
{
if (character == string[i])
{
result = i;
break;
}
}
return result;
}
string_last_character = fn(string: []u8, character: u8) u64 string_last_character = fn(string: []u8, character: u8) u64
{ {
>i = string.length; >i = string.length;
@ -1727,6 +1766,11 @@ get_byte_size = fn (type: &Type) u64
>result = element_size * element_count; >result = element_size * element_count;
return result; return result;
}, },
.alias =>
{
>result = get_byte_size(type.content.alias.type);
return result;
},
else => else =>
{ {
#trap(); #trap();
@ -1820,6 +1864,15 @@ get_bit_size = fn (type: &Type) u64
>result = type.content.union.byte_size * 8; >result = type.content.union.byte_size * 8;
return result; return result;
}, },
.enum_array =>
{
>enum_type = type.content.enum_array.enum_type;
>element_type = type.content.enum_array.element_type;
>element_bit_size = get_byte_size(element_type) * 8;
assert(enum_type.id == .enum);
>element_count = enum_type.content.enum.fields.length;
return element_bit_size * element_count;
},
else => else =>
{ {
#trap(); #trap();
@ -1876,6 +1929,10 @@ is_promotable_integer_type_for_abi = fn (type: &Type) u1
>backing_type = type.content.enum.backing_type; >backing_type = type.content.enum.backing_type;
return is_promotable_integer_type_for_abi(backing_type); return is_promotable_integer_type_for_abi(backing_type);
}, },
.pointer =>
{
return 0;
},
else => else =>
{ {
#trap(); #trap();
@ -1927,6 +1984,7 @@ ValueId = enum
string_to_enum, string_to_enum,
macro_instantiation, macro_instantiation,
field_parent_pointer, field_parent_pointer,
build_mode,
} }
ValueConstantInteger = struct ValueConstantInteger = struct
@ -3761,6 +3819,7 @@ TypeKeyword = enum
void, void,
noreturn, noreturn,
enum_array, enum_array,
fn,
} }
type_is_slice = fn (type: &Type) u1 type_is_slice = fn (type: &Type) u1
@ -4545,6 +4604,15 @@ parse_type = fn (module: &Module, scope: &Scope) &Type
>enum_array_type = get_enum_array_type(module, enum_type, element_type); >enum_array_type = get_enum_array_type(module, enum_type, element_type);
return enum_array_type; return enum_array_type;
}, },
.fn =>
{
skip_space(module);
>mandate_argument_names: u1 = 0;
>function_header = parse_function_header(module, scope, mandate_argument_names);
>result = function_header.type;
return result;
},
else => { unreachable; },
} }
} }
else else
@ -5751,7 +5819,10 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
}, },
.build_mode => .build_mode =>
{ {
#trap(); result.& = {
.id = .build_mode,
zero,
};
}, },
.field_parent_pointer => .field_parent_pointer =>
{ {
@ -5785,7 +5856,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
.left_bracket => .left_bracket =>
{ {
>element_count: u64 = 0; >element_count: u64 = 0;
>value_buffer: [64]&Value = undefined; >value_buffer: [128]&Value = undefined;
skip_space(module); skip_space(module);
@ -5826,6 +5897,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
} }
>value = parse_value(module, scope, zero); >value = parse_value(module, scope, zero);
assert(element_count < value_buffer.length);
value_buffer[element_count] = value; value_buffer[element_count] = value;
element_count += 1; element_count += 1;
@ -5851,7 +5923,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
}, },
.dot => .dot =>
{ {
>identifier = parse_identifier(module); >identifier = parse_name(module);
result = new_value(module); result = new_value(module);
result.& = { result.& = {
.content = { .content = {
@ -6565,7 +6637,12 @@ parse_statement = fn (module: &Module, scope: &Scope) &Statement
}, },
.return => .return =>
{ {
>return_value = parse_value(module, scope, zero); >return_value: &Value = zero;
// TODO: make this better
if (module.content[module.offset] != ';')
{
return_value = parse_value(module, scope, zero);
}
statement.content.return = return_value; statement.content.return = return_value;
statement.id = .return; statement.id = .return;
}, },
@ -8690,19 +8767,16 @@ get_member_at_offset = fn (struct_type: &Type, offset: u64) &Field
>byte_size = get_byte_size(struct_type); >byte_size = get_byte_size(struct_type);
if (byte_size > offset) if (byte_size > offset)
{ {
>offset_it: u64 = 0;
>fields = struct_type.content.struct.fields; >fields = struct_type.content.struct.fields;
for (&field: fields) for (&field: fields)
{ {
if (offset_it > offset) if (field.offset > offset)
{ {
break; break;
} }
result = field; result = field;
assert(offset_it == field.offset);
offset_it = align_forward(offset_it + get_byte_size(field.type), #extend(get_byte_alignment(field.type)));
} }
assert(result != zero); assert(result != zero);
@ -8922,7 +8996,11 @@ abi_system_v_get_indirect_result = fn (module: &Module, type: &Type, free_gpr: u
{ {
if (is_promotable_integer_type_for_abi(type)) if (is_promotable_integer_type_for_abi(type))
{ {
#trap(); return abi_system_v_get_extend({
.semantic_type = type,
.sign = type_is_signed(type),
zero,
});
} }
else else
{ {
@ -13336,7 +13414,8 @@ emit_call = fn (module: &Module, value: &Value, left_llvm: &LLVMValue, left_type
emit_constant_array = fn (module: &Module, elements: []&Value, element_type: &Type) &LLVMValue emit_constant_array = fn (module: &Module, elements: []&Value, element_type: &Type) &LLVMValue
{ {
>value_buffer: [64]&LLVMValue = undefined; >value_buffer: [128]&LLVMValue = undefined;
assert(elements.length <= value_buffer.length);
resolve_type_in_place(module, element_type); resolve_type_in_place(module, element_type);
@ -15222,6 +15301,10 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
}, },
} }
}, },
.undefined =>
{
llvm_value = LLVMGetPoison(get_llvm_type(resolved_value_type, type_kind));
},
else => else =>
{ {
#trap(); #trap();
@ -16627,29 +16710,6 @@ generate_object = fn (module: &LLVMModule, target_machine: &LLVMTargetMachine, o
return result; return result;
} }
ArgumentBuilder = struct
{
buffer: [128]&u8,
count: u64,
}
add_argument = fn (builder: &ArgumentBuilder, argument: []u8) void
{
assert(argument.pointer[argument.length] == 0);
>index = builder.count;
assert(index < builder.buffer.length);
builder.buffer[index] = argument.pointer;
builder.count = index + 1;
}
flush_arguments = fn (builder: &ArgumentBuilder) []&u8
{
>argument_count = builder.count;
assert(argument_count < builder.buffer.length);
builder.buffer[argument_count] = zero;
return builder.buffer[..argument_count];
}
link = fn (module: &Module) void link = fn (module: &Module) void
{ {
>arena = module.arena; >arena = module.arena;
@ -17550,7 +17610,7 @@ emit = fn (module: &Module) void
>semantic_return_type = return_abi.semantic_type; >semantic_return_type = return_abi.semantic_type;
if (semantic_return_type == noreturn_type(module) or function.content.function.attributes.naked) if (semantic_return_type == noreturn_type(module) or function.content.function.attributes.naked)
{ {
#trap(); LLVMBuildUnreachable(module.llvm.builder);
} }
else if (semantic_return_type == void_type(module)) else if (semantic_return_type == void_type(module))
{ {
@ -17824,7 +17884,7 @@ compile = fn (arena: &Arena, options: CompileOptions) void
emit(&module); emit(&module);
} }
compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8 compile_file = fn (arena: &Arena, compile_options: CompileFile, envp: &&u8) []u8
{ {
>relative_file_path = compile_options.relative_file_path; >relative_file_path = compile_options.relative_file_path;
if (relative_file_path.length < 5) if (relative_file_path.length < 5)
@ -17901,7 +17961,113 @@ compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8
if (is_compiler) if (is_compiler)
{ {
#trap(); >builder: ArgumentBuilder = zero;
add_argument(&builder, "/home/david/dev/llvm/install/llvm_20.1.3_x86_64-linux-Release/bin/llvm-config");
add_argument(&builder, "--libdir");
add_argument(&builder, "--libs");
add_argument(&builder, "--system-libs");
>arguments = flush_arguments(&builder);
>llvm_config = os_execute(arena, arguments, envp, {
.policies = [ .pipe, .ignore ],
zero,
});
>success = llvm_config.termination_kind == .exit and llvm_config.termination_code == 0;
if (!success)
{
report_error();
}
>stream = llvm_config.streams[0];
>line = string_first_character(stream, '\n');
if (line == string_no_match)
{
report_error();
}
library_directory = stream[..line];
library_directories = { .pointer = &library_directory, .length = 1 };
stream = stream[line + 1..];
line = string_first_character(stream, '\n');
if (line == string_no_match)
{
report_error();
}
>llvm_library_stream = stream[..line];
stream = stream[line + 1..];
>library_count: u64 = 0;
while (1)
{
>space = string_first_character(llvm_library_stream, ' ');
if (space == string_no_match)
{
>library_argument = llvm_library_stream;
library_buffer[library_count] = library_argument[2..];
library_count += 1;
break;
}
// Omit the first two characters: "-l"
>library_argument = llvm_library_stream[2..space];
library_buffer[library_count] = library_argument;
library_count += 1;
llvm_library_stream = llvm_library_stream[space + 1..];
}
line = string_first_character(stream, '\n');
if (line == string_no_match)
{
report_error();
}
assert(line == stream.length - 1);
>system_library_stream = stream[..line];
while (1)
{
>space = string_first_character(system_library_stream, ' ');
if (space == string_no_match)
{
>library_argument = llvm_library_stream;
library_buffer[library_count] = library_argument[2..];
library_count += 1;
break;
}
// Omit the first two characters: "-l"
>library_argument = system_library_stream[2..space];
library_buffer[library_count] = library_argument;
library_count += 1;
system_library_stream = system_library_stream[space + 1..];
}
library_buffer[library_count] = "gcc";
library_count += 1;
library_buffer[library_count] = "gcc_s";
library_count += 1;
library_buffer[library_count] = "lldCommon";
library_count += 1;
library_buffer[library_count] = "lldELF";
library_count += 1;
library_names = library_buffer[..library_count];
library_paths = { .pointer = &llvm_bindings_library, .length = 1 };
} }
else if (string_equal(base_name, "c_abi")) else if (string_equal(base_name, "c_abi"))
{ {
@ -18125,7 +18291,7 @@ names: [_][]u8 =
.build_mode = build_mode, .build_mode = build_mode,
.has_debug_info = has_debug_info, .has_debug_info = has_debug_info,
.silent = 0, .silent = 0,
}); }, envp);
}, },
.test => .test =>
{ {
@ -18149,7 +18315,7 @@ names: [_][]u8 =
.build_mode = build_mode, .build_mode = build_mode,
.has_debug_info = has_debug_info, .has_debug_info = has_debug_info,
.silent = 1, .silent = 1,
}); }, envp);
>arguments: [_]&u8 = [ >arguments: [_]&u8 = [
executable_path.pointer, executable_path.pointer,

View File

@ -686,20 +686,18 @@ fn Field* get_member_at_offset(Type* struct_type, u32 offset)
if (struct_type->structure.byte_size > offset) if (struct_type->structure.byte_size > offset)
{ {
u32 offset_it = 0;
auto fields = struct_type->structure.fields; auto fields = struct_type->structure.fields;
for (u64 i = 0; i < fields.length; i += 1) for (u64 i = 0; i < fields.length; i += 1)
{ {
auto* field = &fields[i]; auto* field = &fields[i];
auto field_offset = field->offset;
if (offset_it > offset) if (field_offset > offset)
{ {
break; break;
} }
result = field; result = field;
offset_it = (u32)align_forward(offset_it + get_byte_size(field->type), get_byte_alignment(field->type));
} }
assert(result); assert(result);