mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Add basic arm32 ABI support (linux_arm32)
This commit is contained in:
@@ -30,6 +30,7 @@ enum TargetArchKind : u16 {
|
||||
|
||||
TargetArch_amd64,
|
||||
TargetArch_i386,
|
||||
TargetArch_arm32,
|
||||
TargetArch_arm64,
|
||||
TargetArch_wasm32,
|
||||
TargetArch_wasm64,
|
||||
@@ -75,6 +76,7 @@ String target_arch_names[TargetArch_COUNT] = {
|
||||
str_lit(""),
|
||||
str_lit("amd64"),
|
||||
str_lit("i386"),
|
||||
str_lit("arm32"),
|
||||
str_lit("arm64"),
|
||||
str_lit("wasm32"),
|
||||
str_lit("wasm64"),
|
||||
@@ -98,6 +100,7 @@ TargetEndianKind target_endians[TargetArch_COUNT] = {
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
};
|
||||
|
||||
#ifndef ODIN_VERSION_RAW
|
||||
@@ -367,7 +370,16 @@ gb_global TargetMetrics target_linux_arm64 = {
|
||||
8,
|
||||
16,
|
||||
str_lit("aarch64-linux-elf"),
|
||||
str_lit("e-m:e-i8:8:32-i16:32-i64:64-i128:128-n32:64-S128"),
|
||||
str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_linux_arm32 = {
|
||||
TargetOs_linux,
|
||||
TargetArch_arm32,
|
||||
4,
|
||||
8,
|
||||
str_lit("aapcs-linux-gnu"),
|
||||
str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_darwin_amd64 = {
|
||||
@@ -483,6 +495,7 @@ gb_global NamedTargetMetrics named_targets[] = {
|
||||
{ str_lit("linux_i386"), &target_linux_i386 },
|
||||
{ str_lit("linux_amd64"), &target_linux_amd64 },
|
||||
{ str_lit("linux_arm64"), &target_linux_arm64 },
|
||||
{ str_lit("linux_arm32"), &target_linux_arm32 },
|
||||
{ str_lit("windows_i386"), &target_windows_i386 },
|
||||
{ str_lit("windows_amd64"), &target_windows_amd64 },
|
||||
{ str_lit("freebsd_i386"), &target_freebsd_i386 },
|
||||
|
||||
@@ -516,6 +516,10 @@ namespace lbAbiAmd64SysV {
|
||||
|
||||
bool is_register(LLVMTypeRef type) {
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(type);
|
||||
i64 sz = lb_sizeof(type);
|
||||
if (sz == 0) {
|
||||
return false;
|
||||
}
|
||||
switch (kind) {
|
||||
case LLVMIntegerTypeKind:
|
||||
case LLVMHalfTypeKind:
|
||||
@@ -1164,6 +1168,88 @@ namespace lbAbiWasm32 {
|
||||
}
|
||||
}
|
||||
|
||||
namespace lbAbiArm32 {
|
||||
Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention);
|
||||
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
|
||||
|
||||
LB_ABI_INFO(abi_info) {
|
||||
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
|
||||
ft->ctx = c;
|
||||
ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention);
|
||||
ft->ret = compute_return_type(c, return_type, return_is_defined);
|
||||
ft->calling_convention = calling_convention;
|
||||
return ft;
|
||||
}
|
||||
|
||||
bool is_register(LLVMTypeRef type, bool is_return) {
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(type);
|
||||
switch (kind) {
|
||||
case LLVMHalfTypeKind:
|
||||
case LLVMFloatTypeKind:
|
||||
case LLVMDoubleTypeKind:
|
||||
return true;
|
||||
case LLVMIntegerTypeKind:
|
||||
return lb_sizeof(type) <= 8;
|
||||
case LLVMFunctionTypeKind:
|
||||
return true;
|
||||
case LLVMPointerTypeKind:
|
||||
return true;
|
||||
case LLVMVectorTypeKind:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
lbArgType non_struct(LLVMContextRef c, LLVMTypeRef type, bool is_return) {
|
||||
LLVMAttributeRef attr = nullptr;
|
||||
LLVMTypeRef i1 = LLVMInt1TypeInContext(c);
|
||||
if (type == i1) {
|
||||
attr = lb_create_enum_attribute(c, "zeroext");
|
||||
}
|
||||
return lb_arg_type_direct(type, nullptr, nullptr, attr);
|
||||
}
|
||||
|
||||
Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention) {
|
||||
auto args = array_make<lbArgType>(heap_allocator(), arg_count);
|
||||
|
||||
for (unsigned i = 0; i < arg_count; i++) {
|
||||
LLVMTypeRef t = arg_types[i];
|
||||
if (is_register(t, false)) {
|
||||
args[i] = non_struct(c, t, false);
|
||||
} else {
|
||||
i64 sz = lb_sizeof(t);
|
||||
i64 a = lb_alignof(t);
|
||||
if (is_calling_convention_odin(calling_convention) && sz > 8) {
|
||||
// Minor change to improve performance using the Odin calling conventions
|
||||
args[i] = lb_arg_type_indirect(t, nullptr);
|
||||
} else if (a <= 4) {
|
||||
unsigned n = cast(unsigned)((sz + 3) / 4);
|
||||
args[i] = lb_arg_type_direct(LLVMArrayType(LLVMIntTypeInContext(c, 32), n));
|
||||
} else {
|
||||
unsigned n = cast(unsigned)((sz + 7) / 8);
|
||||
args[i] = lb_arg_type_direct(LLVMArrayType(LLVMIntTypeInContext(c, 64), n));
|
||||
}
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) {
|
||||
if (!return_is_defined) {
|
||||
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
||||
} else if (!is_register(return_type, true)) {
|
||||
switch (lb_sizeof(return_type)) {
|
||||
case 1: return lb_arg_type_direct(LLVMIntTypeInContext(c, 8), return_type, nullptr, nullptr);
|
||||
case 2: return lb_arg_type_direct(LLVMIntTypeInContext(c, 16), return_type, nullptr, nullptr);
|
||||
case 3: case 4: return lb_arg_type_direct(LLVMIntTypeInContext(c, 32), return_type, nullptr, nullptr);
|
||||
}
|
||||
LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type);
|
||||
return lb_arg_type_indirect(return_type, attr);
|
||||
}
|
||||
return non_struct(c, return_type, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
LB_ABI_INFO(lb_get_abi_info) {
|
||||
switch (calling_convention) {
|
||||
@@ -1203,6 +1289,8 @@ LB_ABI_INFO(lb_get_abi_info) {
|
||||
}
|
||||
case TargetArch_i386:
|
||||
return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
|
||||
case TargetArch_arm32:
|
||||
return lbAbiArm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
|
||||
case TargetArch_arm64:
|
||||
return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
|
||||
case TargetArch_wasm32:
|
||||
|
||||
Reference in New Issue
Block a user