mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-20 04:35:00 -07:00
Basic cross compilation support
This commit is contained in:
+21
-22
@@ -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);
|
||||
|
||||
+43
-21
@@ -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<LLVMTypeRef>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-3
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user