Basic cross compilation support

This commit is contained in:
gingerBill
2020-06-10 12:26:31 +01:00
parent 9b1cc6e94f
commit 6b3ee447f0
4 changed files with 88 additions and 46 deletions
+21 -22
View File
@@ -123,7 +123,6 @@ struct BuildContext {
bool has_resource; bool has_resource;
String opt_flags; String opt_flags;
String llc_flags; String llc_flags;
String target_triplet;
String link_flags; String link_flags;
String extra_linker_flags; String extra_linker_flags;
BuildModeKind build_mode; BuildModeKind build_mode;
@@ -139,6 +138,7 @@ struct BuildContext {
bool use_lld; bool use_lld;
bool vet; bool vet;
bool cross_compiling; bool cross_compiling;
bool keep_object_files;
bool use_llvm_api; bool use_llvm_api;
@@ -226,7 +226,7 @@ struct NamedTargetMetrics {
gb_global NamedTargetMetrics named_targets[] = { gb_global NamedTargetMetrics named_targets[] = {
{ str_lit("essence_amd64"), &target_essence_amd64 }, { 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_386"), &target_linux_386 },
{ str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("linux_amd64"), &target_linux_amd64 },
{ str_lit("windows_386"), &target_windows_386 }, { 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_VERSION = ODIN_VERSION;
bc->ODIN_ROOT = odin_root_dir(); bc->ODIN_ROOT = odin_root_dir();
TargetMetrics metrics = {}; TargetMetrics *metrics = nullptr;
#if defined(GB_ARCH_64_BIT) #if defined(GB_ARCH_64_BIT)
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
metrics = target_windows_amd64; metrics = &target_windows_amd64;
#elif defined(GB_SYSTEM_OSX) #elif defined(GB_SYSTEM_OSX)
metrics = target_darwin_amd64; metrics = &target_darwin_amd64;
#else #else
metrics = target_linux_amd64; metrics = &target_linux_amd64;
#endif #endif
#else #else
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
metrics = target_windows_386; metrics = &target_windows_386;
#elif defined(GB_SYSTEM_OSX) #elif defined(GB_SYSTEM_OSX)
#error "Build Error: Unsupported architecture" #error "Build Error: Unsupported architecture"
#else #else
metrics = target_linux_386; metrics = &target_linux_386;
#endif #endif
#endif #endif
if (cross_target) { if (cross_target != nullptr && metrics != cross_target) {
metrics = *cross_target; metrics = cross_target;
bc->cross_compiling = true; bc->cross_compiling = true;
} }
GB_ASSERT(metrics.os != TargetOs_Invalid); GB_ASSERT(metrics->os != TargetOs_Invalid);
GB_ASSERT(metrics.arch != TargetArch_Invalid); GB_ASSERT(metrics->arch != TargetArch_Invalid);
GB_ASSERT(metrics.word_size > 1); GB_ASSERT(metrics->word_size > 1);
GB_ASSERT(metrics.max_align > 1); GB_ASSERT(metrics->max_align > 1);
bc->metrics = metrics; bc->metrics = *metrics;
bc->ODIN_OS = target_os_names[metrics.os]; bc->ODIN_OS = target_os_names[metrics->os];
bc->ODIN_ARCH = target_arch_names[metrics.arch]; bc->ODIN_ARCH = target_arch_names[metrics->arch];
bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics.arch]]; bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics->arch]];
bc->endian_kind = target_endians[metrics.arch]; bc->endian_kind = target_endians[metrics->arch];
bc->word_size = metrics.word_size; bc->word_size = metrics->word_size;
bc->max_align = metrics.max_align; bc->max_align = metrics->max_align;
bc->link_flags = str_lit(" "); bc->link_flags = str_lit(" ");
bc->opt_flags = str_lit(" "); bc->opt_flags = str_lit(" ");
bc->target_triplet = metrics.target_triplet;
gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64); gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64);
+43 -21
View File
@@ -1301,38 +1301,52 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
set_procedure_abi_types(heap_allocator(), type); set_procedure_abi_types(heap_allocator(), type);
LLVMTypeRef return_type = LLVMVoidTypeInContext(ctx); LLVMTypeRef return_type = LLVMVoidTypeInContext(ctx);
isize offset = 0;
if (type->Proc.return_by_pointer) { if (type->Proc.return_by_pointer) {
offset = 1; // Void
} else if (type->Proc.abi_compat_result_type != nullptr) { } else if (type->Proc.abi_compat_result_type != nullptr) {
return_type = lb_type(m, type->Proc.abi_compat_result_type); 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) { if (type->Proc.calling_convention == ProcCC_Odin) {
extra_param_count += 1; extra_param_count += 1;
} }
isize param_count = type->Proc.abi_compat_params.count + extra_param_count; isize param_count = type->Proc.abi_compat_params.count + extra_param_count;
LLVMTypeRef *param_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count); auto param_types = array_make<LLVMTypeRef>(heap_allocator(), 0, param_count);
defer (gb_free(heap_allocator(), param_types)); defer (array_free(&param_types));
if (type->Proc.return_by_pointer) {
array_add(&param_types, LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0));
}
isize param_index = offset;
for_array(i, type->Proc.abi_compat_params) { for_array(i, type->Proc.abi_compat_params) {
Type *param = type->Proc.abi_compat_params[i]; Type *param = type->Proc.abi_compat_params[i];
if (param == nullptr) { if (param == nullptr) {
continue; continue;
} }
param_types[param_index++] = lb_type(m, param); if (is_type_tuple(param)) {
} param = base_type(param);
if (type->Proc.return_by_pointer) { for_array(j, param->Tuple.variables) {
param_types[0] = LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0); Entity *v = param->Tuple.variables[j];
if (v->kind != Entity_Variable) {
// Sanity check
continue;
}
array_add(&param_types, lb_type(m, v->type));
}
} else {
array_add(&param_types, lb_type(m, param));
}
} }
if (type->Proc.calling_convention == ProcCC_Odin) { if (type->Proc.calling_convention == ProcCC_Odin) {
param_types[param_index++] = lb_type(m, t_context_ptr); array_add(&param_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); return LLVMPointerType(t, 0);
} }
break; break;
@@ -2251,6 +2265,8 @@ lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbP
kind = lbParamPass_BitCast; kind = lbParamPass_BitCast;
} else if (is_type_tuple(abi_type)) { } else if (is_type_tuple(abi_type)) {
kind = lbParamPass_Tuple; kind = lbParamPass_Tuple;
} else if (is_type_proc(abi_type)) {
kind = lbParamPass_Value;
} else { } else {
GB_PANIC("Invalid abi type pass kind %s", type_to_string(abi_type)); 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) { for_array(i, abi_type->Tuple.variables) {
Type *t = abi_type->Tuple.variables[i]->type; Type *t = abi_type->Tuple.variables[i]->type;
GB_ASSERT(!is_type_tuple(t));
lbParamPasskind elem_kind = lbParamPass_Value; lbParamPasskind elem_kind = lbParamPass_Value;
lbValue elem = lb_value_param(p, nullptr, t, index+cast(i32)i, &elem_kind); 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 *src = core_type(src_type);
Type *dst = core_type(t); Type *dst = core_type(t);
GB_ASSERT(src != nullptr);
GB_ASSERT(dst != nullptr);
if (is_type_untyped_nil(src)) { if (is_type_untyped_nil(src)) {
return lb_const_nil(m, t); 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; case BuiltinProc_atomic_xchg_relaxed: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingMonotonic; break;
} }
LLVMValueRef instr = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false); lbValue res = {};
return {}; res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
res.type = tv.type;
return res;
} }
case BuiltinProc_atomic_cxchg: 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 // TODO(bill): Figure out how to make it weak
LLVMBool single_threaded = !weak; LLVMBool single_threaded = !weak;
LLVMValueRef instr = LLVMBuildAtomicCmpXchg(p->builder, address.value, lbValue res = {};
old_value.value, new_value.value, res.value = LLVMBuildAtomicCmpXchg(p->builder, address.value,
success_ordering, old_value.value, new_value.value,
failure_ordering, success_ordering,
single_threaded); failure_ordering,
single_threaded);
return {}; res.type = tv.type;
return res;
} }
} }
+21 -3
View File
@@ -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", 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)); LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
#else #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 #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 { } else {
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
timings_start_section(timings, str_lit("msvc-link")); timings_start_section(timings, str_lit("msvc-link"));
@@ -1310,7 +1319,7 @@ void remove_temp_files(String output_base) {
} while (0) } while (0)
EXT_REMOVE(".ll"); EXT_REMOVE(".ll");
EXT_REMOVE(".bc"); 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) #if defined(GB_SYSTEM_WINDOWS)
EXT_REMOVE(".obj"); EXT_REMOVE(".obj");
EXT_REMOVE(".res"); 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", 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)); LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
#else #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 #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 { } else {
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
timings_start_section(timings, str_lit("msvc-link")); timings_start_section(timings, str_lit("msvc-link"));
+3
View File
@@ -3526,6 +3526,9 @@ gbString write_type_to_string(gbString str, Type *type) {
case ProcCC_None: case ProcCC_None:
str = gb_string_appendc(str, " \"none\" "); str = gb_string_appendc(str, " \"none\" ");
break; break;
case ProcCC_Pure:
str = gb_string_appendc(str, " \"pure\" ");
break;
// case ProcCC_VectorCall: // case ProcCC_VectorCall:
// str = gb_string_appendc(str, " \"vectorcall\" "); // str = gb_string_appendc(str, " \"vectorcall\" ");
// break; // break;