feat(arm32 cdecl): Added thumb as the triple for cortex-m7. Updated the calling convention for cortex-m7 arm32 micro processors as the soft float register was being used when calling across the C ABI boundary causing guff data to be passed.

This commit is contained in:
MauriceElliott
2026-06-24 21:07:48 +01:00
parent ab11e45a4a
commit a3fa3476c6
3 changed files with 27 additions and 10 deletions

View File

@@ -1072,6 +1072,12 @@ gb_internal bool is_arch_wasm(void) {
return false;
}
gb_internal bool is_cortex_m7(void) {
return build_context.metrics.os == TargetOs_freestanding &&
build_context.metrics.arch == TargetArch_arm32 &&
build_context.microarch == str_lit("cortex-m7");
}
gb_internal bool is_arch_x86(void) {
switch (build_context.metrics.arch) {
case TargetArch_i386:
@@ -1832,9 +1838,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
bc->metrics = *metrics;
if (bc->metrics.os == TargetOs_freestanding &&
bc->metrics.arch == TargetArch_arm32 &&
bc->microarch == str_lit("cortex-m7")) {
if (is_cortex_m7()) {
bc->metrics.target_triplet = str_lit("thumbv7em-none-eabihf");
}

View File

@@ -186,9 +186,11 @@ gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType
lbCallingConventionKind cc_kind = lbCallingConvention_C;
// TODO(bill): Clean up this logic
if (!is_arch_wasm()) {
if (is_cortex_m7()) {
cc_kind = lbCallingConvention_ARM_AAPCS_VFP;
} else if (!is_arch_wasm()) {
cc_kind = lb_calling_convention_map[calling_convention];
}
}
// if (build_context.metrics.arch == TargetArch_amd64) {
// if (build_context.metrics.os == TargetOs_windows) {
// if (cc_kind == lbCallingConvention_C) {
@@ -1554,14 +1556,14 @@ namespace lbAbiWasm {
namespace lbAbiArm32 {
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention);
gb_internal lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
gb_internal lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, ProcCallingConvention calling_convention);
gb_internal LB_ABI_INFO(abi_info) {
LLVMContextRef c = m->ctx;
lbFunctionType *ft = permanent_alloc_item<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->ret = compute_return_type(c, return_type, return_is_defined, calling_convention);
ft->calling_convention = calling_convention;
return ft;
}
@@ -1604,7 +1606,10 @@ namespace lbAbiArm32 {
} else {
i64 sz = lb_sizeof(t);
i64 a = lb_alignof(t);
if (is_calling_convention_odin(calling_convention) && sz > 8) {
// Added to support hard floats included in the playdates cortex-m7.
if (calling_convention == ProcCC_CDecl && is_cortex_m7()) {
args[i] = lb_arg_type_direct(t);
} else 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) {
@@ -1619,10 +1624,13 @@ namespace lbAbiArm32 {
return args;
}
gb_internal lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) {
gb_internal lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, ProcCallingConvention calling_convention) {
if (!return_is_defined) {
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
} else if (!is_register(return_type, true)) {
if (calling_convention == ProcCC_CDecl && is_cortex_m7()) {
return lb_arg_type_direct(return_type);
}
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);

View File

@@ -452,7 +452,9 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name
Type *pt = p->type;
lbCallingConventionKind cc_kind = lbCallingConvention_C;
if (!is_arch_wasm()) {
if (is_cortex_m7()) {
cc_kind = lbCallingConvention_ARM_AAPCS_VFP;
} else if (!is_arch_wasm()) {
cc_kind = lb_calling_convention_map[pt->Proc.calling_convention];
}
LLVMSetFunctionCallConv(p->value, cc_kind);
@@ -994,6 +996,9 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue
LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
auto llvm_cc = lb_calling_convention_map[proc_type->Proc.calling_convention];
if (is_cortex_m7()) {
llvm_cc = lbCallingConvention_ARM_AAPCS_VFP;
}
LLVMSetInstructionCallConv(ret, llvm_cc);
LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;