From aa2f44d3ab505fef912e685f5088cd330f7c9100 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Sat, 31 May 2025 17:56:44 -0600 Subject: [PATCH] wip --- src/compiler.bbb | 152 ++++++++++++++++++++++++++++++++++++++ src/compiler.hpp | 5 ++ src/emitter.cpp | 53 ++++++++++--- tests/enum_debug_info.bbb | 38 ++++++++++ 4 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 tests/enum_debug_info.bbb diff --git a/src/compiler.bbb b/src/compiler.bbb index 97c841d..e7a2090 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -808,6 +808,7 @@ ValueId = enum external_function, function, constant_integer, + global, } ValueConstantInteger = struct @@ -2784,6 +2785,84 @@ parse = fn (module: &Module) void } } +resolve_alias = fn (module: &Module, type: &Type) &Type +{ + >result: &Type = zero; + + switch (type.id) + { + .void, + .integer, + => + { + result = type; + }, + else => + { + #trap(); + }, + } + + assert(result != zero); + + return result; +} + +AbiSystemVClass = enum +{ + none, + integer, + sse, + sse_up, + x87, + x87_up, + complex_x87, + memory, +} + +AbiSystemVClassifyArgument = struct +{ + base_offset: u64, + is_variable_argument: u1, + is_register_call: u1, +} + +abi_system_v_classify_type = fn (type: &Type, options: AbiSystemVClassifyArgument) [2]AbiSystemVClass +{ + >result: [2]AbiSystemVClass = zero; + + >is_memory = options.base_offset >= 8; + >current_index: u64 = #extend(is_memory); + >not_current_index: u64 = #extend(!is_memory); + assert(current_index != not_current_index); + result[current_index] = .memory; + + switch (type.id) + { + .void, .noreturn => + { + result[current_index] = .none; + }, + else => + { + #trap(); + }, + } + + return result; +} + +abi_system_v_classify_return_type = fn (module: &Module, type: &Type) AbiInformation +{ + #trap(); +} + +ResolvedCallingConvention = enum +{ + system_v, + win64, +} + emit = fn (module: &Module) void { assert(!module.current_function); @@ -2889,6 +2968,79 @@ emit = fn (module: &Module) void >name = #enum_name(e); module.llvm.intrinsic_table[i] = LLVMLookupIntrinsicID(name.pointer, name.length); } + + >global = module.first_global; + + while (global) + { + assert(!module.current_function); + assert(!module.current_macro_instantiation); + assert(!module.current_macro_declaration); + + if (global.emitted) + { + continue; + } + + >global_pointer_type = global.variable.storage.type; + assert(global_pointer_type.id == .pointer); + >global_value_type = global_pointer_type.content.pointer.element_type; + + switch (global.variable.storage.id) + { + .function, .external_function => + { + >function_type = &global_value_type.content.function; + >semantic_argument_types = function_type.semantic_argument_types; + >semantic_return_type = function_type.semantic_return_type; + function_type.argument_abis = arena_allocate_slice[AbiInformation](module.arena, semantic_argument_types.length); + >llvm_abi_argument_type_buffer: [64]&LLVMType = undefined; + + >resolved_calling_convention: ResolvedCallingConvention = undefined; + switch (function_type.calling_convention) + { + .c => + { + // TODO: switch on platform + resolved_calling_convention = .system_v; + }, + } + + >is_reg_call = resolved_calling_convention == .system_v and 0; // TODO: regcall calling convention + + switch (resolved_calling_convention) + { + .system_v => + { + function_type.available_registers = { + .system_v = { + .gpr = #select(is_reg_call, 11, 6), + .sse = #select(is_reg_call, 16, 8), + }, + }; + function_type.return_abi = abi_system_v_classify_return_type(module, resolve_alias(module, semantic_return_type)); + #trap(); + }, + .win64 => + { + #trap(); + }, + } + }, + .global => + { + #trap(); + }, + else => + { + report_error(); + }, + } + + global = global.next; + } + + #trap(); } compile = fn (arena: &Arena, options: CompileOptions) void diff --git a/src/compiler.hpp b/src/compiler.hpp index ff9ae29..a40566a 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -629,6 +629,11 @@ fn u64 get_bit_size(Type* type) case TypeId::integer: return type->integer.bit_count; case TypeId::enumerator: return get_bit_size(type->enumerator.backing_type); case TypeId::alias: return get_bit_size(type->alias.type); + case TypeId::array: return get_byte_size(type->array.element_type) * type->array.element_count * 8; + case TypeId::pointer: return 64; + case TypeId::structure: return type->structure.byte_size * 8; + case TypeId::union_type: return type->union_type.byte_size * 8; + case TypeId::enum_array: return get_byte_size(type->enum_array.element_type) * type->enum_array.enum_type->enumerator.fields.length * 8; default: trap(); } } diff --git a/src/emitter.cpp b/src/emitter.cpp index 464114c..14b8d58 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -153,6 +153,7 @@ fn bool is_integral_or_enumeration_type(Type* type) case TypeId::bits: case TypeId::enumerator: return true; + case TypeId::array: case TypeId::structure: return false; default: unreachable(); @@ -738,6 +739,13 @@ fn Type* abi_system_v_get_integer_type_at_offset(Module* module, Type* type, u32 auto backing_type = type->enumerator.backing_type; return abi_system_v_get_integer_type_at_offset(module, backing_type, offset, source_type == type ? backing_type : source_type, source_offset); } break; + case TypeId::array: + { + auto element_type = type->array.element_type; + auto element_size = get_byte_size(element_type); + auto element_offset = offset / element_size * element_size; + return abi_system_v_get_integer_type_at_offset(module, element_type, offset - element_offset, source_type, source_offset); + } break; default: unreachable(); } @@ -1103,7 +1111,7 @@ fn void resolve_type_in_place_debug(Module* module, Type* type) assert(array_element_count); resolve_type_in_place_debug(module, array_element_type); auto bit_alignment = get_byte_alignment(type) * 8; - auto array_type = LLVMDIBuilderCreateArrayType(module->llvm.di_builder, array_element_count, bit_alignment, array_element_type->llvm.debug, 0, 0); + auto array_type = LLVMDIBuilderCreateArrayType(module->llvm.di_builder, get_bit_size(type), bit_alignment, array_element_type->llvm.debug, 0, 0); result = array_type; } break; case TypeId::enumerator: @@ -1119,7 +1127,10 @@ fn void resolve_type_in_place_debug(Module* module, Type* type) field_buffer[i] = enum_field; } - result = LLVMDIBuilderCreateEnumerationType(module->llvm.di_builder, module->scope.llvm, (char*)type->name.pointer, type->name.length, module->llvm.file, type->enumerator.line, get_bit_size(type), get_byte_alignment(type) * 8, field_buffer, type->enumerator.fields.length, backing_type->llvm.debug); + auto debug_aligned_type = align_integer_type(module, backing_type); + resolve_type_in_place_debug(module, debug_aligned_type); + + result = LLVMDIBuilderCreateEnumerationType(module->llvm.di_builder, module->scope.llvm, (char*)type->name.pointer, type->name.length, module->llvm.file, type->enumerator.line, get_bit_size(type), get_byte_alignment(type) * 8, field_buffer, type->enumerator.fields.length, debug_aligned_type->llvm.debug); } break; case TypeId::structure: { @@ -1136,7 +1147,7 @@ fn void resolve_type_in_place_debug(Module* module, Type* type) auto& field = fields[i]; auto field_type = field.type; resolve_type_in_place_debug(module, field_type); - auto member_type = LLVMDIBuilderCreateMemberType(module->llvm.di_builder, module->scope.llvm, (char*)field.name.pointer, field.name.length, module->llvm.file, field.line, get_byte_size(field_type) * 8, get_byte_alignment(field_type) * 8, field.offset * 8, flags, field_type->llvm.debug); + auto member_type = LLVMDIBuilderCreateMemberType(module->llvm.di_builder, module->scope.llvm, (char*)field.name.pointer, field.name.length, module->llvm.file, field.line, get_bit_size(field_type), get_byte_alignment(field_type) * 8, field.offset * 8, flags, field_type->llvm.debug); llvm_type_buffer[i] = member_type; } @@ -2278,8 +2289,8 @@ enum class IndexType struct TypeAnalysis { + Type* indexing_type; bool must_be_constant; - bool is_index; }; fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnalysis analysis); @@ -2692,7 +2703,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal { if (!expected_type) { - if (analysis.is_index) + if (analysis.indexing_type) { expected_type = uint64(module); } @@ -3268,7 +3279,9 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal } auto pointer_element_type = array_like_type->pointer.element_type; - analyze_type(module, value->array_expression.index, 0, { .must_be_constant = analysis.must_be_constant, .is_index = true }); + auto indexing_type = pointer_element_type->id == TypeId::enum_array ? pointer_element_type->enum_array.enum_type : uint64(module); + + analyze_type(module, value->array_expression.index, 0, { .indexing_type = indexing_type, .must_be_constant = analysis.must_be_constant }); Type* element_type = 0; switch (pointer_element_type->id) @@ -3311,6 +3324,11 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal } break; case ValueId::enum_literal: { + if (!expected_type) + { + expected_type = analysis.indexing_type; + } + if (!expected_type) { report_error(); @@ -4379,10 +4397,20 @@ fn ValueTypePair enter_struct_pointer_for_coerced_access(Module* module, LLVMVal if (!(first_field_size < destination_size && first_field_size < source_size)) { - trap(); + auto gep = LLVMBuildStructGEP2(module->llvm.builder, source_type->llvm.abi, source_value, 0, "coerce.dive"); + if (first_field_type->id == TypeId::structure) + { + trap(); + } + else + { + return { gep, first_field_type }; + } + } + else + { + return { source_value, source_type }; } - - return { source_value, source_type }; } fn LLVMValueRef coerce_integer_or_pointer_to_integer_or_pointer(Module* module, LLVMValueRef source, Type* source_type, Type* destination_type) @@ -4418,7 +4446,12 @@ fn LLVMValueRef create_coerced_load(Module* module, LLVMValueRef source, Type* s if (type_is_integer_backing(source_type) && type_is_integer_backing(destination_type)) { - trap(); + auto load = create_load(module, { + .type = source_type, + .pointer = source, + }); + auto result = coerce_integer_or_pointer_to_integer_or_pointer(module, load, source_type, destination_type); + return result; } else { diff --git a/tests/enum_debug_info.bbb b/tests/enum_debug_info.bbb new file mode 100644 index 0000000..9fb82ec --- /dev/null +++ b/tests/enum_debug_info.bbb @@ -0,0 +1,38 @@ +TypeId = enum +{ + void, + noreturn, + forward_declaration, + integer, + function, + pointer, + array, + enum, + struct, + bits, + alias, + union, + unresolved, + vector, + floating_point, + enum_array, + opaque, +} + +Type = struct +{ + arr: [5]u32, + id: TypeId, + a: [2]u64, + b: u64, +} + +[export] main = fn [cc(c)] () s32 +{ + >t: Type = { + .id = .integer, + zero, + }; + t.arr[0] = 1; + return 0; +}