diff --git a/src/compiler.bbb b/src/compiler.bbb index 97c841d..e5b91c3 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,34 @@ parse = fn (module: &Module) void } } +resolve_alias = fn (module: &Module, type: &Type) &Type +{ + >result: &Type = zero; + + switch (type.id) + { + else => + { + #trap(); + }, + } + + //assert(result != zero); + + //eturn 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 +2918,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/emitter.cpp b/src/emitter.cpp index 464114c..39d0081 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -4379,10 +4379,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 +4428,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 {