Experimental xtensa support

This commit is contained in:
Christoffer Lerno
2024-07-30 22:10:39 +02:00
parent d212f7d946
commit e1a13e433f
11 changed files with 92 additions and 14 deletions

View File

@@ -112,6 +112,7 @@ enum ArchType
WASM64, // WebAssembly with 64-bit pointers WASM64, // WebAssembly with 64-bit pointers
RSCRIPT32, // 32-bit RenderScript RSCRIPT32, // 32-bit RenderScript
RSCRIPT64, // 64-bit RenderScript RSCRIPT64, // 64-bit RenderScript
XTENSA, // Xtensa
} }
const OsType OS_TYPE = (OsType)$$OS_TYPE; const OsType OS_TYPE = (OsType)$$OS_TYPE;

View File

@@ -16,6 +16,7 @@
- c3c init-lib does not create the directory with the .c3l suffix #1253 - c3c init-lib does not create the directory with the .c3l suffix #1253
- Permit foreach values to be optional. - Permit foreach values to be optional.
- Add `--show-backtrace` option to disable backtrace for even smaller binary. - Add `--show-backtrace` option to disable backtrace for even smaller binary.
- Untested Xtensa support.
### Fixes ### Fixes

View File

@@ -317,6 +317,7 @@ typedef enum
ELF_RISCV64, ELF_RISCV64,
ELF_X86, ELF_X86,
ELF_X64, ELF_X64,
ELF_XTENSA,
FREEBSD_X86, FREEBSD_X86,
FREEBSD_X64, FREEBSD_X64,
LINUX_AARCH64, LINUX_AARCH64,

View File

@@ -20,6 +20,7 @@ char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
[ELF_RISCV64] = "elf-riscv64", [ELF_RISCV64] = "elf-riscv64",
[ELF_X86] = "elf-x86", [ELF_X86] = "elf-x86",
[ELF_X64] = "elf-x64", [ELF_X64] = "elf-x64",
[ELF_XTENSA] = "elf-xtensa",
[FREEBSD_X86] = "freebsd-x86", [FREEBSD_X86] = "freebsd-x86",
[FREEBSD_X64] = "freebsd-x64", [FREEBSD_X64] = "freebsd-x64",
[LINUX_AARCH64] = "linux-aarch64", [LINUX_AARCH64] = "linux-aarch64",

View File

@@ -197,25 +197,32 @@ void c_abi_func_create(FunctionPrototype *proto)
{ {
case ABI_X64: case ABI_X64:
c_abi_func_create_x64(proto); c_abi_func_create_x64(proto);
break; return;
case ABI_X86: case ABI_X86:
c_abi_func_create_x86(proto); c_abi_func_create_x86(proto);
break; return;
case ABI_WIN64: case ABI_WIN64:
c_abi_func_create_win64(proto); c_abi_func_create_win64(proto);
break; return;
case ABI_AARCH64: case ABI_AARCH64:
c_abi_func_create_aarch64(proto); c_abi_func_create_aarch64(proto);
break; return;
case ABI_RISCV: case ABI_RISCV:
c_abi_func_create_riscv(proto); c_abi_func_create_riscv(proto);
break; return;
case ABI_WASM: case ABI_WASM:
c_abi_func_create_wasm(proto); c_abi_func_create_wasm(proto);
return;
case ABI_XTENSA:
c_abi_func_create_default(proto);
return;
case ABI_UNKNOWN:
case ABI_ARM:
case ABI_PPC32:
case ABI_PPC64_SVR4:
break; break;
default:
FATAL_ERROR("Unsupported ABI");
} }
FATAL_ERROR("Unsupported ABI");
} }
@@ -242,3 +249,34 @@ ABIArgInfo *c_abi_classify_argument_type_default(Type *type)
return abi_arg_new_direct(); return abi_arg_new_direct();
} }
void c_abi_func_create_default(FunctionPrototype *prototype)
{
prototype->ret_abi_info = c_abi_classify_return_type_default(prototype->abi_ret_type);
if (prototype->ret_by_ref)
{
prototype->ret_by_ref_abi_info = c_abi_classify_return_type_default(type_get_ptr(type_flatten(prototype->ret_by_ref_type)));
}
Type **params = prototype->param_types;
unsigned param_count = vec_size(prototype->param_types);
if (param_count)
{
ABIArgInfo **args = MALLOC(sizeof(ABIArgInfo) * param_count);
for (unsigned i = 0; i < param_count; i++)
{
args[i] = c_abi_classify_argument_type_default(params[i]);
}
prototype->abi_args = args;
}
Type **va_params = prototype->varargs;
unsigned va_param_count = vec_size(va_params);
if (va_param_count)
{
ABIArgInfo **args = MALLOC(sizeof(ABIArgInfo) * va_param_count);
for (unsigned i = 0; i < va_param_count; i++)
{
args[i] = c_abi_classify_argument_type_default(va_params[i]);
}
prototype->abi_varargs = args;
}
}

View File

@@ -459,6 +459,8 @@ void init_asm(void)
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
init_asm_wasm(); init_asm_wasm();
return; return;
case ARCH_TYPE_XTENSA:
error_exit("Xtensa asm support not yet available.");
case ARCH_TYPE_UNKNOWN: case ARCH_TYPE_UNKNOWN:
error_exit("Unknown arch does not support asm."); error_exit("Unknown arch does not support asm.");
UNREACHABLE UNREACHABLE

View File

@@ -53,7 +53,7 @@ void c_abi_func_create_x64(FunctionPrototype *prototype);
void c_abi_func_create_aarch64(FunctionPrototype *prototype); void c_abi_func_create_aarch64(FunctionPrototype *prototype);
void c_abi_func_create_riscv(FunctionPrototype *prototype); void c_abi_func_create_riscv(FunctionPrototype *prototype);
void c_abi_func_create_wasm(FunctionPrototype *prototype); void c_abi_func_create_wasm(FunctionPrototype *prototype);
void c_abi_func_create_default(FunctionPrototype *prototype);
static inline AbiType abi_type_get(Type *type) static inline AbiType abi_type_get(Type *type)
{ {

View File

@@ -125,6 +125,7 @@ bool type_is_homogenous_base_type(Type *type)
case ABI_WASM: case ABI_WASM:
case ABI_PPC32: case ABI_PPC32:
case ABI_RISCV: case ABI_RISCV:
case ABI_XTENSA:
return false; return false;
} }
UNREACHABLE UNREACHABLE
@@ -150,6 +151,7 @@ bool type_homogenous_aggregate_small_enough(Type *type, unsigned members)
case ABI_WASM: case ABI_WASM:
case ABI_PPC32: case ABI_PPC32:
case ABI_RISCV: case ABI_RISCV:
case ABI_XTENSA:
return false; return false;
} }
UNREACHABLE UNREACHABLE

View File

@@ -990,6 +990,9 @@ static int jump_buffer_size()
case LINUX_RISCV32: case LINUX_RISCV32:
// Godbolt test // Godbolt test
return 76; return 76;
case ELF_XTENSA:
// Godbolt 68 => 17 with 32 bit pointers
return 17;
case ELF_RISCV64: case ELF_RISCV64:
case LINUX_RISCV64: case LINUX_RISCV64:
// Godbolt test // Godbolt test

View File

@@ -1028,6 +1028,8 @@ const char *arch_to_linker_arch(ArchType arch)
return "wasm32"; return "wasm32";
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
return "wasm64"; return "wasm64";
case ARCH_TYPE_XTENSA:
return "xtensa";
} }
UNREACHABLE; UNREACHABLE;
} }
@@ -1055,6 +1057,7 @@ static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = {
[ELF_RISCV32] = "riscv32-unknown-elf", [ELF_RISCV32] = "riscv32-unknown-elf",
[LINUX_RISCV64] = "riscv64-unknown-linux", [LINUX_RISCV64] = "riscv64-unknown-linux",
[ELF_RISCV64] = "riscv64-unknown-elf", [ELF_RISCV64] = "riscv64-unknown-elf",
[ELF_XTENSA] = "xtensa-unknown-elf",
[WASM32] = "wasm32-unknown-unknown", [WASM32] = "wasm32-unknown-unknown",
[WASM64] = "wasm64-unknown-unknown", [WASM64] = "wasm64-unknown-unknown",
}; };
@@ -1144,6 +1147,7 @@ static ArchType arch_from_llvm_string(StringSlice slice)
STRCASE("amd64", ARCH_TYPE_X86_64) STRCASE("amd64", ARCH_TYPE_X86_64)
STRCASE("x86_64h", ARCH_TYPE_X86_64) STRCASE("x86_64h", ARCH_TYPE_X86_64)
STRCASE("xcore", ARCH_TYPE_XCORE) STRCASE("xcore", ARCH_TYPE_XCORE)
STRCASE("xtensa", ARCH_TYPE_XTENSA)
STRCASE("nvptx", ARCH_TYPE_NVPTX) STRCASE("nvptx", ARCH_TYPE_NVPTX)
STRCASE("nvptx64", ARCH_TYPE_NVPTX64) STRCASE("nvptx64", ARCH_TYPE_NVPTX64)
STRCASE("le32", ARCH_TYPE_LE32) STRCASE("le32", ARCH_TYPE_LE32)
@@ -1297,6 +1301,7 @@ static unsigned arch_pointer_bit_width(OsType os, ArchType arch)
case ARCH_TYPE_THUMBEB: case ARCH_TYPE_THUMBEB:
case ARCH_TYPE_X86: case ARCH_TYPE_X86:
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_XTENSA:
return 32; return 32;
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
case ARCH_TYPE_AARCH64: case ARCH_TYPE_AARCH64:
@@ -1310,9 +1315,8 @@ static unsigned arch_pointer_bit_width(OsType os, ArchType arch)
case ARCH_TYPE_X86_64: case ARCH_TYPE_X86_64:
if (os == OS_TYPE_NACL) return 32; if (os == OS_TYPE_NACL) return 32;
return 64; return 64;
default:
UNREACHABLE
} }
UNREACHABLE
} }
static unsigned arch_int_register_bit_width(OsType os, ArchType arch) static unsigned arch_int_register_bit_width(OsType os, ArchType arch)
@@ -1330,6 +1334,7 @@ static unsigned arch_int_register_bit_width(OsType os, ArchType arch)
case ARCH_TYPE_THUMBEB: case ARCH_TYPE_THUMBEB:
case ARCH_TYPE_X86: case ARCH_TYPE_X86:
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_XTENSA:
return 32; return 32;
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
case ARCH_TYPE_AARCH64: case ARCH_TYPE_AARCH64:
@@ -1343,9 +1348,8 @@ static unsigned arch_int_register_bit_width(OsType os, ArchType arch)
case ARCH_TYPE_X86_64: case ARCH_TYPE_X86_64:
if (os == OS_TYPE_NACL) return 32; if (os == OS_TYPE_NACL) return 32;
return 64; return 64;
default:
UNREACHABLE
} }
UNREACHABLE
} }
static unsigned os_target_supports_float16(OsType os, ArchType arch) static unsigned os_target_supports_float16(OsType os, ArchType arch)
@@ -1443,6 +1447,7 @@ static unsigned os_target_supports_int128(OsType os, ArchType arch)
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
return true; return true;
case ARCH_TYPE_PPC: case ARCH_TYPE_PPC:
case ARCH_TYPE_XTENSA:
default: default:
return false; return false;
} }
@@ -1547,6 +1552,7 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
case ARCH_TYPE_RISCV32: case ARCH_TYPE_RISCV32:
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_XTENSA:
return (AlignData) { MIN(64u, bits), MIN(64u, bits) }; return (AlignData) { MIN(64u, bits), MIN(64u, bits) };
case ARCH_TYPE_RISCV64: case ARCH_TYPE_RISCV64:
return (AlignData) { bits, bits }; return (AlignData) { bits, bits };
@@ -1578,6 +1584,7 @@ static unsigned arch_big_endian(ArchType arch)
case ARCH_TYPE_RISCV64: case ARCH_TYPE_RISCV64:
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
case ARCH_TYPE_XTENSA:
return false; return false;
case ARCH_TYPE_ARMB: case ARCH_TYPE_ARMB:
case ARCH_TYPE_THUMBEB: case ARCH_TYPE_THUMBEB:
@@ -1615,6 +1622,7 @@ static AlignData os_target_alignment_of_float(OsType os, ArchType arch, uint32_t
case ARCH_TYPE_RISCV64: case ARCH_TYPE_RISCV64:
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
case ARCH_TYPE_XTENSA:
return (AlignData) { bits , bits }; return (AlignData) { bits , bits };
case ARCH_TYPE_ARM: case ARCH_TYPE_ARM:
case ARCH_TYPE_THUMB: case ARCH_TYPE_THUMB:
@@ -1752,6 +1760,13 @@ INLINE const char *llvm_macos_target_triple(const char *triple)
scratch_buffer_printf("%d.%d.0", mac_sdk->macos_min_deploy_target.major, mac_sdk->macos_min_deploy_target.minor); scratch_buffer_printf("%d.%d.0", mac_sdk->macos_min_deploy_target.major, mac_sdk->macos_min_deploy_target.minor);
return scratch_buffer_to_string(); return scratch_buffer_to_string();
} }
#if LLVM_VERSION_MAJOR > 19
#define XTENSA_AVAILABLE 1
#else
#define XTENSA_AVAILABLE 0
#endif
void *llvm_target_machine_create(void) void *llvm_target_machine_create(void)
{ {
static bool llvm_initialized = false; static bool llvm_initialized = false;
@@ -1759,6 +1774,9 @@ void *llvm_target_machine_create(void)
if (!llvm_initialized) if (!llvm_initialized)
{ {
llvm_initialized = true; llvm_initialized = true;
#if XTENSA_AVAILABLE
INITIALIZE_TARGET(Xtensa);
#endif
INITIALIZE_TARGET(ARM); INITIALIZE_TARGET(ARM);
INITIALIZE_TARGET(AArch64); INITIALIZE_TARGET(AArch64);
INITIALIZE_TARGET(RISCV); INITIALIZE_TARGET(RISCV);
@@ -1821,7 +1839,13 @@ void target_setup(BuildTarget *target)
error_exit("Unable to detect the default target, please set an explicit --target value."); error_exit("Unable to detect the default target, please set an explicit --target value.");
} }
if (target->arch_os_target == ELF_XTENSA && !XTENSA_AVAILABLE)
{
error_exit("Xtensa support is not available with this LLVM version.");
}
platform_target.target_triple = arch_to_target_triple[target->arch_os_target]; platform_target.target_triple = arch_to_target_triple[target->arch_os_target];
assert(platform_target.target_triple);
platform_target.alloca_address_space = 0; platform_target.alloca_address_space = 0;
@@ -1856,7 +1880,7 @@ void target_setup(BuildTarget *target)
platform_target.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-')); platform_target.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-'));
if (!arch_is_supported(platform_target.arch)) if (!arch_is_supported(platform_target.arch))
{ {
printf("WARNING! This architecture is not supported.\n"); printf("WARNING! This architecture is unsupported.\n");
} }
platform_target.vendor = vendor_from_llvm_string(slice_next_token(&target_triple_string, '-')); platform_target.vendor = vendor_from_llvm_string(slice_next_token(&target_triple_string, '-'));
platform_target.os = os_from_llvm_string(slice_next_token(&target_triple_string, '-')); platform_target.os = os_from_llvm_string(slice_next_token(&target_triple_string, '-'));
@@ -1924,6 +1948,9 @@ void target_setup(BuildTarget *target)
platform_target.aarch.is_win32 = platform_target.os == OS_TYPE_WIN32; platform_target.aarch.is_win32 = platform_target.os == OS_TYPE_WIN32;
platform_target.abi = ABI_AARCH64; platform_target.abi = ABI_AARCH64;
break; break;
case ARCH_TYPE_XTENSA:
platform_target.abi = ABI_XTENSA;
break;
case ARCH_TYPE_WASM32: case ARCH_TYPE_WASM32:
case ARCH_TYPE_WASM64: case ARCH_TYPE_WASM64:
platform_target.abi = ABI_WASM; platform_target.abi = ABI_WASM;

View File

@@ -59,7 +59,8 @@ typedef enum
ARCH_TYPE_WASM64, // WebAssembly with 64-bit pointers ARCH_TYPE_WASM64, // WebAssembly with 64-bit pointers
ARCH_TYPE_RSCRIPT32, // 32-bit RenderScript ARCH_TYPE_RSCRIPT32, // 32-bit RenderScript
ARCH_TYPE_RSCRIPT64, // 64-bit RenderScript ARCH_TYPE_RSCRIPT64, // 64-bit RenderScript
ARCH_TYPE_LAST = ARCH_TYPE_RSCRIPT64 ARCH_TYPE_XTENSA, // Xtensa
ARCH_TYPE_LAST = ARCH_TYPE_XTENSA
} ArchType; } ArchType;
@@ -201,6 +202,7 @@ typedef enum
ABI_PPC32, ABI_PPC32,
ABI_PPC64_SVR4, ABI_PPC64_SVR4,
ABI_RISCV, ABI_RISCV,
ABI_XTENSA,
} ABI; } ABI;