diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c3cf1e808..c39f893c0 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -123,7 +123,6 @@ struct BuildContext { bool has_resource; String opt_flags; String llc_flags; - String target_triplet; String link_flags; String extra_linker_flags; BuildModeKind build_mode; @@ -139,6 +138,7 @@ struct BuildContext { bool use_lld; bool vet; bool cross_compiling; + bool keep_object_files; bool use_llvm_api; @@ -226,7 +226,7 @@ struct NamedTargetMetrics { gb_global NamedTargetMetrics named_targets[] = { { str_lit("essence_amd64"), &target_essence_amd64 }, - { str_lit("darwin_amd64"), &target_darwin_amd64 }, + { str_lit("darwin_amd64"), &target_darwin_amd64 }, { str_lit("linux_386"), &target_linux_386 }, { str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("windows_386"), &target_windows_386 }, @@ -604,47 +604,46 @@ void init_build_context(TargetMetrics *cross_target) { bc->ODIN_VERSION = ODIN_VERSION; bc->ODIN_ROOT = odin_root_dir(); - TargetMetrics metrics = {}; + TargetMetrics *metrics = nullptr; #if defined(GB_ARCH_64_BIT) #if defined(GB_SYSTEM_WINDOWS) - metrics = target_windows_amd64; + metrics = &target_windows_amd64; #elif defined(GB_SYSTEM_OSX) - metrics = target_darwin_amd64; + metrics = &target_darwin_amd64; #else - metrics = target_linux_amd64; + metrics = &target_linux_amd64; #endif #else #if defined(GB_SYSTEM_WINDOWS) - metrics = target_windows_386; + metrics = &target_windows_386; #elif defined(GB_SYSTEM_OSX) #error "Build Error: Unsupported architecture" #else - metrics = target_linux_386; + metrics = &target_linux_386; #endif #endif - if (cross_target) { - metrics = *cross_target; + if (cross_target != nullptr && metrics != cross_target) { + metrics = cross_target; bc->cross_compiling = true; } - GB_ASSERT(metrics.os != TargetOs_Invalid); - GB_ASSERT(metrics.arch != TargetArch_Invalid); - GB_ASSERT(metrics.word_size > 1); - GB_ASSERT(metrics.max_align > 1); + GB_ASSERT(metrics->os != TargetOs_Invalid); + GB_ASSERT(metrics->arch != TargetArch_Invalid); + GB_ASSERT(metrics->word_size > 1); + GB_ASSERT(metrics->max_align > 1); - bc->metrics = metrics; - bc->ODIN_OS = target_os_names[metrics.os]; - bc->ODIN_ARCH = target_arch_names[metrics.arch]; - bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics.arch]]; - bc->endian_kind = target_endians[metrics.arch]; - bc->word_size = metrics.word_size; - bc->max_align = metrics.max_align; + bc->metrics = *metrics; + bc->ODIN_OS = target_os_names[metrics->os]; + bc->ODIN_ARCH = target_arch_names[metrics->arch]; + bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics->arch]]; + bc->endian_kind = target_endians[metrics->arch]; + bc->word_size = metrics->word_size; + bc->max_align = metrics->max_align; bc->link_flags = str_lit(" "); bc->opt_flags = str_lit(" "); - bc->target_triplet = metrics.target_triplet; gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a141dbb14..c6245fe8a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1301,38 +1301,52 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { set_procedure_abi_types(heap_allocator(), type); LLVMTypeRef return_type = LLVMVoidTypeInContext(ctx); - isize offset = 0; if (type->Proc.return_by_pointer) { - offset = 1; + // Void } else if (type->Proc.abi_compat_result_type != nullptr) { return_type = lb_type(m, type->Proc.abi_compat_result_type); } - isize extra_param_count = offset; + isize extra_param_count = 0; + if (type->Proc.return_by_pointer) { + extra_param_count += 1; + } if (type->Proc.calling_convention == ProcCC_Odin) { extra_param_count += 1; } isize param_count = type->Proc.abi_compat_params.count + extra_param_count; - LLVMTypeRef *param_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count); - defer (gb_free(heap_allocator(), param_types)); + auto param_types = array_make(heap_allocator(), 0, param_count); + defer (array_free(¶m_types)); + + if (type->Proc.return_by_pointer) { + array_add(¶m_types, LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0)); + } - isize param_index = offset; for_array(i, type->Proc.abi_compat_params) { Type *param = type->Proc.abi_compat_params[i]; if (param == nullptr) { continue; } - param_types[param_index++] = lb_type(m, param); - } - if (type->Proc.return_by_pointer) { - param_types[0] = LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0); + if (is_type_tuple(param)) { + param = base_type(param); + for_array(j, param->Tuple.variables) { + Entity *v = param->Tuple.variables[j]; + if (v->kind != Entity_Variable) { + // Sanity check + continue; + } + array_add(¶m_types, lb_type(m, v->type)); + } + } else { + array_add(¶m_types, lb_type(m, param)); + } } if (type->Proc.calling_convention == ProcCC_Odin) { - param_types[param_index++] = lb_type(m, t_context_ptr); + array_add(¶m_types, lb_type(m, t_context_ptr)); } - LLVMTypeRef t = LLVMFunctionType(return_type, param_types, cast(unsigned)param_index, type->Proc.c_vararg); + LLVMTypeRef t = LLVMFunctionType(return_type, param_types.data, cast(unsigned)param_types.count, type->Proc.c_vararg); return LLVMPointerType(t, 0); } break; @@ -2251,6 +2265,8 @@ lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbP kind = lbParamPass_BitCast; } else if (is_type_tuple(abi_type)) { kind = lbParamPass_Tuple; + } else if (is_type_proc(abi_type)) { + kind = lbParamPass_Value; } else { GB_PANIC("Invalid abi type pass kind %s", type_to_string(abi_type)); } @@ -2310,6 +2326,7 @@ lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 i } for_array(i, abi_type->Tuple.variables) { Type *t = abi_type->Tuple.variables[i]->type; + GB_ASSERT(!is_type_tuple(t)); lbParamPasskind elem_kind = lbParamPass_Value; lbValue elem = lb_value_param(p, nullptr, t, index+cast(i32)i, &elem_kind); @@ -5829,6 +5846,8 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { Type *src = core_type(src_type); Type *dst = core_type(t); + GB_ASSERT(src != nullptr); + GB_ASSERT(dst != nullptr); if (is_type_untyped_nil(src)) { return lb_const_nil(m, t); @@ -7818,8 +7837,10 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_atomic_xchg_relaxed: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingMonotonic; break; } - LLVMValueRef instr = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false); - return {}; + lbValue res = {}; + res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false); + res.type = tv.type; + return res; } case BuiltinProc_atomic_cxchg: @@ -7877,13 +7898,14 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, // TODO(bill): Figure out how to make it weak LLVMBool single_threaded = !weak; - LLVMValueRef instr = LLVMBuildAtomicCmpXchg(p->builder, address.value, - old_value.value, new_value.value, - success_ordering, - failure_ordering, - single_threaded); - - return {}; + lbValue res = {}; + res.value = LLVMBuildAtomicCmpXchg(p->builder, address.value, + old_value.value, new_value.value, + success_ordering, + failure_ordering, + single_threaded); + res.type = tv.type; + return res; } } diff --git a/src/main.cpp b/src/main.cpp index 3f0d71043..ea370a03f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -157,8 +157,17 @@ i32 linker_stage(lbGenerator *gen) { system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s", LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags)); #else - gb_printf_err("Don't know how to cross compile to selected target.\n"); + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); #endif + } else if (build_context.cross_compiling) { + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); + build_context.keep_object_files = true; } else { #if defined(GB_SYSTEM_WINDOWS) timings_start_section(timings, str_lit("msvc-link")); @@ -1310,7 +1319,7 @@ void remove_temp_files(String output_base) { } while (0) EXT_REMOVE(".ll"); EXT_REMOVE(".bc"); - if (build_context.build_mode != BuildMode_Object) { + if (build_context.build_mode != BuildMode_Object && !build_context.keep_object_files) { #if defined(GB_SYSTEM_WINDOWS) EXT_REMOVE(".obj"); EXT_REMOVE(".res"); @@ -1847,8 +1856,17 @@ int main(int arg_count, char const **arg_ptr) { system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s", LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags)); #else - gb_printf_err("Don't know how to cross compile to selected target.\n"); + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); #endif + } else if (build_context.cross_compiling) { + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); + build_context.keep_object_files = true; } else { #if defined(GB_SYSTEM_WINDOWS) timings_start_section(timings, str_lit("msvc-link")); diff --git a/src/types.cpp b/src/types.cpp index 3a0613b2c..7fd363dd4 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3526,6 +3526,9 @@ gbString write_type_to_string(gbString str, Type *type) { case ProcCC_None: str = gb_string_appendc(str, " \"none\" "); break; + case ProcCC_Pure: + str = gb_string_appendc(str, " \"pure\" "); + break; // case ProcCC_VectorCall: // str = gb_string_appendc(str, " \"vectorcall\" "); // break;