diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 5d0c3df13..9b19ac9e1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9183,6 +9183,9 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c gb_string_free(b); gb_string_free(a); } + if (is_arch_wasm() && !check_target_feature_is_enabled(str_lit("tail-call"), nullptr)) { + error(call, "'#must_tail' on a WebAssembly target requires the 'tail-call' target feature, e.g. '-target-features:tail-call'"); + } break; } diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 4af0fed0f..02da1c835 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -150,6 +150,15 @@ gb_internal LLVMTypeRef lb_function_type_to_llvm_raw(lbFunctionType *ft, bool is // return LLVMPointerType(func_type, 0); // } +gb_internal lbCallingConventionKind lb_calling_convention_kind(ProcCallingConvention cc) { + if (selected_subtarget == Subtarget_Playdate) { + return lbCallingConvention_ARM_AAPCS_VFP; + } + if (is_arch_wasm()) { + return lbCallingConvention_C; + } + return lb_calling_convention_map[cc]; +} gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType *ft, ProcCallingConvention calling_convention) { if (ft == nullptr) { @@ -204,13 +213,7 @@ gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType LLVMAddAttributeAtIndex(fn, offset, noalias_attr); } - lbCallingConventionKind cc_kind = lbCallingConvention_C; - // TODO(bill): Clean up this logic - if (selected_subtarget == Subtarget_Playdate) { - cc_kind = lbCallingConvention_ARM_AAPCS_VFP; - } else if (!is_arch_wasm()) { - cc_kind = lb_calling_convention_map[calling_convention]; - } + lbCallingConventionKind cc_kind = lb_calling_convention_kind(calling_convention); // if (build_context.metrics.arch == TargetArch_amd64) { // if (build_context.metrics.os == TargetOs_windows) { // if (cc_kind == lbCallingConvention_C) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 6e933d152..828566c38 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -718,6 +718,8 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = { }; +gb_internal lbCallingConventionKind lb_calling_convention_kind(ProcCallingConvention cc); + enum : LLVMDWARFTypeEncoding { LLVMDWARFTypeEncoding_Address = 1, LLVMDWARFTypeEncoding_Boolean = 2, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 5b55bbf14..d5c066eb2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -471,13 +471,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name p->value = LLVMAddFunction(m->mod, c_link_name, func_type); Type *pt = p->type; - lbCallingConventionKind cc_kind = lbCallingConvention_C; - if (selected_subtarget == Subtarget_Playdate) { - 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); + LLVMSetFunctionCallConv(p->value, lb_calling_convention_kind(pt->Proc.calling_convention)); lbValue proc_value = {p->value, p->type}; lb_add_member(m, p->name, proc_value); lb_add_procedure_value(m, p); @@ -1074,11 +1068,7 @@ 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 (selected_subtarget == Subtarget_Playdate) { - llvm_cc = lbCallingConvention_ARM_AAPCS_VFP; - } - LLVMSetInstructionCallConv(ret, llvm_cc); + LLVMSetInstructionCallConv(ret, lb_calling_convention_kind(proc_type->Proc.calling_convention)); LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex; if (return_ptr.value != nullptr) {