Compile the compiler
All checks were successful
CI / ci (MinSizeRel, ubuntu-latest) (pull_request) Successful in 6m10s
CI / ci (RelWithDebInfo, ubuntu-latest) (pull_request) Successful in 6m8s
CI / ci (Release, ubuntu-latest) (pull_request) Successful in 5m51s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 18m34s

This commit is contained in:
David Gonzalez Martin 2025-06-19 11:49:21 -06:00
parent 14f856b550
commit c7056f2520
4 changed files with 629 additions and 105 deletions

File diff suppressed because it is too large Load Diff

View File

@ -898,6 +898,7 @@ enum class UnaryTypeId
{ {
align_of, align_of,
byte_size, byte_size,
enum_names,
enum_values, enum_values,
integer_max, integer_max,
}; };
@ -2063,8 +2064,7 @@ fn Type* resolve_alias(Module* module, Type* type)
fn u64 enum_bit_count(u64 highest_value) fn u64 enum_bit_count(u64 highest_value)
{ {
auto needed_bit_count = 64 - (u64)clz(highest_value); auto needed_bit_count = highest_value == 0 ? 1 : 64 - clz(highest_value);
needed_bit_count = needed_bit_count ? needed_bit_count : 1;
return needed_bit_count; return needed_bit_count;
} }

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);
@ -3099,7 +3097,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
auto alloca = create_alloca(module, { auto alloca = create_alloca(module, {
.type = string_type, .type = string_type,
.name = string_literal("retval"), .name = string_literal("return_value"),
}); });
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block"); auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
@ -3278,6 +3276,15 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
} break; } break;
} }
} }
else if (unary_type_id == UnaryTypeId::enum_names)
{
if (unary_type->id != TypeId::enumerator)
{
report_error();
}
value_type = get_slice_type(module, get_slice_type(module, uint8(module)));
}
else else
{ {
if (expected_type) if (expected_type)
@ -3312,6 +3319,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
{ {
value = integer_max_value(unary_type->integer.bit_count, unary_type->integer.is_signed); value = integer_max_value(unary_type->integer.bit_count, unary_type->integer.is_signed);
} break; } break;
case UnaryTypeId::enum_names:
case UnaryTypeId::enum_values: case UnaryTypeId::enum_values:
{ {
unreachable(); unreachable();
@ -4302,12 +4310,12 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
auto return_value_alloca = create_alloca(module, { auto return_value_alloca = create_alloca(module, {
.type = enum_type, .type = enum_type,
.name = string_literal("retval"), .name = string_literal("return_value"),
}); });
auto return_boolean_alloca = create_alloca(module, { auto return_boolean_alloca = create_alloca(module, {
.type = u8_type, .type = u8_type,
.name = string_literal("retbool"), .name = string_literal("return_bool"),
}); });
auto index_alloca = create_alloca(module, { auto index_alloca = create_alloca(module, {
@ -6732,6 +6740,37 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
auto value = emit_field_access(module, right, left_llvm, left_type, TypeKind::memory); auto value = emit_field_access(module, right, left_llvm, left_type, TypeKind::memory);
right->llvm = value; right->llvm = value;
} break; } break;
case ValueId::unary_type:
{
auto unary_type_id = right->unary_type.id;
auto unary_type = right->unary_type.type;
switch (unary_type_id)
{
case UnaryTypeId::enum_names:
{
assert(unary_type->id == TypeId::enumerator);
auto global = get_enum_name_array_global(module, unary_type);
auto u64_type = uint64(module);
resolve_type_in_place(module, u64_type);
LLVMValueRef slice_values[] = {
global->variable.storage->llvm,
LLVMConstInt(u64_type->llvm.abi, unary_type->enumerator.fields.length, 0),
};
auto slice = LLVMConstStructInContext(module->llvm.context, slice_values, array_length(slice_values), 0);
create_store(module, {
.source = slice,
.destination = left_llvm,
.type = resolved_value_type,
});
} break;
default:
trap();
}
} break;
default: unreachable(); default: unreachable();
} }
} break; } break;
@ -7042,11 +7081,6 @@ fn void emit_macro_instantiation(Module* module, Value* value)
LLVMPositionBuilderAtEnd(module->llvm.builder, return_block); LLVMPositionBuilderAtEnd(module->llvm.builder, return_block);
// END OF SCOPE
if (module->has_debug_info)
{
LLVMSetCurrentDebugLocation2(module->llvm.builder, caller_debug_location);
}
module->llvm.inlined_at = older_inlined_at; module->llvm.inlined_at = older_inlined_at;
module->current_macro_instantiation = old_macro_instantiation; module->current_macro_instantiation = old_macro_instantiation;
module->current_function = current_function; module->current_function = current_function;
@ -7055,7 +7089,7 @@ fn void emit_macro_instantiation(Module* module, Value* value)
} }
} }
fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u32* last_line, u32* last_column, LLVMMetadataRef* last_debug_location); fn void analyze_statement(Module* module, Scope* scope, Statement* statement);
fn void analyze_block(Module* module, Block* block) fn void analyze_block(Module* module, Block* block)
{ {
@ -7071,7 +7105,7 @@ fn void analyze_block(Module* module, Block* block)
for (auto* statement = block->first_statement; statement; statement = statement->next) for (auto* statement = block->first_statement; statement; statement = statement->next)
{ {
analyze_statement(module, &block->scope, statement, &last_line, &last_column, &last_debug_location); analyze_statement(module, &block->scope, statement);
} }
} }
@ -7305,7 +7339,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
{ {
assert(unary_type->id == TypeId::integer); assert(unary_type->id == TypeId::integer);
auto is_signed = unary_type->integer.is_signed; auto is_signed = unary_type->integer.is_signed;
auto max_value = integer_max_value(resolved_value_type->integer.bit_count, is_signed); auto max_value = integer_max_value(unary_type->integer.bit_count, is_signed);
auto constant_integer = LLVMConstInt(resolved_value_type->llvm.abi, max_value, is_signed); auto constant_integer = LLVMConstInt(resolved_value_type->llvm.abi, max_value, is_signed);
llvm_value = constant_integer; llvm_value = constant_integer;
} break; } break;
@ -7344,6 +7378,10 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
} break; } break;
} }
} break; } break;
case UnaryTypeId::enum_names:
{
trap();
} break;
} }
} break; } break;
case ValueId::binary: case ValueId::binary:
@ -8177,7 +8215,7 @@ fn void analyze_value(Module* module, Value* value, Type* expected_type, TypeKin
emit_value(module, value, type_kind, must_be_constant); emit_value(module, value, type_kind, must_be_constant);
} }
fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u32* last_line, u32* last_column, LLVMMetadataRef* last_debug_location) fn void analyze_statement(Module* module, Scope* scope, Statement* statement)
{ {
Global* parent_function_global; Global* parent_function_global;
if (module->current_function) if (module->current_function)
@ -8196,16 +8234,12 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
auto* llvm_function = parent_function_global->variable.storage->llvm; auto* llvm_function = parent_function_global->variable.storage->llvm;
assert(llvm_function); assert(llvm_function);
LLVMMetadataRef statement_location = 0;
if (module->has_debug_info) if (module->has_debug_info)
{ {
if (statement->line != *last_line || statement->column != *last_column) statement_location = LLVMDIBuilderCreateDebugLocation(module->llvm.context, statement->line, statement->column, scope->llvm, module->llvm.inlined_at);
{ LLVMSetCurrentDebugLocation2(module->llvm.builder, statement_location);
auto new_location = LLVMDIBuilderCreateDebugLocation(module->llvm.context, statement->line, statement->column, scope->llvm, module->llvm.inlined_at);
*last_debug_location = new_location;
LLVMSetCurrentDebugLocation2(module->llvm.builder, new_location);
*last_line = statement->line;
*last_column = statement->column;
}
} }
switch (statement->id) switch (statement->id)
@ -8237,7 +8271,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
{ {
if (module->has_debug_info) if (module->has_debug_info)
{ {
LLVMSetCurrentDebugLocation2(module->llvm.builder, *last_debug_location); LLVMSetCurrentDebugLocation2(module->llvm.builder, statement_location);
} }
auto return_alloca = module->current_function->variable.storage->function.llvm.return_alloca; auto return_alloca = module->current_function->variable.storage->function.llvm.return_alloca;
@ -8304,7 +8338,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block); LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block);
LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block); LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block);
analyze_statement(module, scope, statement->if_st.if_statement, last_line, last_column, last_debug_location); analyze_statement(module, scope, statement->if_st.if_statement);
if (LLVMGetInsertBlock(module->llvm.builder)) if (LLVMGetInsertBlock(module->llvm.builder))
{ {
@ -8315,7 +8349,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
auto else_statement = statement->if_st.else_statement; auto else_statement = statement->if_st.else_statement;
if (else_statement) if (else_statement)
{ {
analyze_statement(module, scope, else_statement, last_line, last_column, last_debug_location); analyze_statement(module, scope, else_statement);
} }
if (LLVMGetInsertBlock(module->llvm.builder)) if (LLVMGetInsertBlock(module->llvm.builder))
@ -8950,7 +8984,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
assert(!local); assert(!local);
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate, last_line, last_column, last_debug_location); analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate);
if (LLVMGetInsertBlock(module->llvm.builder)) if (LLVMGetInsertBlock(module->llvm.builder))
{ {
@ -9054,7 +9088,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
LLVMBuildCondBr(module->llvm.builder, index_compare, body_block, exit_block); LLVMBuildCondBr(module->llvm.builder, index_compare, body_block, exit_block);
LLVMPositionBuilderAtEnd(module->llvm.builder, body_block); LLVMPositionBuilderAtEnd(module->llvm.builder, body_block);
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate, last_line, last_column, last_debug_location); analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate);
if (LLVMGetInsertBlock(module->llvm.builder)) if (LLVMGetInsertBlock(module->llvm.builder))
{ {
@ -9601,7 +9635,7 @@ void emit(Module* module)
{ {
auto alloca = create_alloca(module, { auto alloca = create_alloca(module, {
.type = function_type->abi.return_abi.semantic_type, .type = function_type->abi.return_abi.semantic_type,
.name = string_literal("retval"), .name = string_literal("return_value"),
}); });
global->variable.storage->function.llvm.return_alloca = alloca; global->variable.storage->function.llvm.return_alloca = alloca;
} break; } break;

View File

@ -7,6 +7,7 @@ enum class ValueIntrinsic
byte_size, byte_size,
enum_from_int, enum_from_int,
enum_name, enum_name,
enum_names,
enum_values, enum_values,
extend, extend,
field_parent_pointer, field_parent_pointer,
@ -1179,6 +1180,7 @@ fn Token tokenize(Module* module)
string_literal("byte_size"), string_literal("byte_size"),
string_literal("enum_from_int"), string_literal("enum_from_int"),
string_literal("enum_name"), string_literal("enum_name"),
string_literal("enum_names"),
string_literal("enum_values"), string_literal("enum_values"),
string_literal("extend"), string_literal("extend"),
string_literal("field_parent_pointer"), string_literal("field_parent_pointer"),
@ -1743,6 +1745,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
case ValueIntrinsic::align_of: case ValueIntrinsic::align_of:
case ValueIntrinsic::byte_size: case ValueIntrinsic::byte_size:
case ValueIntrinsic::enum_values: case ValueIntrinsic::enum_values:
case ValueIntrinsic::enum_names:
case ValueIntrinsic::integer_max: case ValueIntrinsic::integer_max:
{ {
skip_space(module); skip_space(module);
@ -1758,6 +1761,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
{ {
case ValueIntrinsic::align_of: id = UnaryTypeId::align_of; break; case ValueIntrinsic::align_of: id = UnaryTypeId::align_of; break;
case ValueIntrinsic::byte_size: id = UnaryTypeId::byte_size; break; case ValueIntrinsic::byte_size: id = UnaryTypeId::byte_size; break;
case ValueIntrinsic::enum_names: id = UnaryTypeId::enum_names; break;
case ValueIntrinsic::enum_values: id = UnaryTypeId::enum_values; break; case ValueIntrinsic::enum_values: id = UnaryTypeId::enum_values; break;
case ValueIntrinsic::integer_max: id = UnaryTypeId::integer_max; break; case ValueIntrinsic::integer_max: id = UnaryTypeId::integer_max; break;
default: unreachable(); default: unreachable();