From 755d116ecf2d221e2ad8b572c58a7d4f99163ff9 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Tue, 15 Feb 2022 20:22:01 +0700 Subject: [PATCH] stage1: use u16 for __truncxfhf2/__extendhfxf2 on non-Arm CPUs Non-Arm CPUs use u16 as the parameter to __extendhfxf2 and the return value of __truncxfhf2, so insert appropriate bitcasts in gen_soft_f80_widen_or_shorten. Otherwise, LLVM might crash because the functions are called in a different way than its compiler-rt definition. This fixes stage1 build on SPARCv9, and possibly other non-x86, non-Arm CPUs. --- src/stage1/codegen.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index dc8f5e590e..2c63d85089 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1620,13 +1620,23 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty LLVMTypeRef return_type; const char *func_name; + LLVMValueRef result; + bool castTruncatedToF16 = false; + if (actual_bits == wanted_bits) { return expr_val; } else if (actual_bits == 80) { param_type = g->builtin_types.entry_f80->llvm_type; switch (wanted_bits) { case 16: - return_type = g->builtin_types.entry_f16->llvm_type; + // Only Arm has a native f16 type, other platforms soft-implement it + // using u16 instead. + if (target_is_arm(g->zig_target)) { + return_type = g->builtin_types.entry_f16->llvm_type; + } else { + return_type = g->builtin_types.entry_u16->llvm_type; + castTruncatedToF16 = true; + } func_name = "__truncxfhf2"; break; case 32: @@ -1648,7 +1658,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty return_type = g->builtin_types.entry_f80->llvm_type; switch (actual_bits) { case 16: - param_type = g->builtin_types.entry_f16->llvm_type; + // Only Arm has a native f16 type, other platforms soft-implement it + // using u16 instead. + if (target_is_arm(g->zig_target)) { + param_type = g->builtin_types.entry_f16->llvm_type; + } else { + param_type = g->builtin_types.entry_u16->llvm_type; + expr_val = LLVMBuildBitCast(g->builder, expr_val, param_type, ""); + } func_name = "__extendhfxf2"; break; case 32: @@ -1676,7 +1693,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty func_ref = LLVMAddFunction(g->module, func_name, fn_type); } - return LLVMBuildCall(g->builder, func_ref, &expr_val, 1, ""); + result = LLVMBuildCall(g->builder, func_ref, &expr_val, 1, ""); + + // On non-Arm platforms we need to bitcast __truncxfhf2 result back to f16 + if (castTruncatedToF16) { + result = LLVMBuildBitCast(g->builder, result, g->builtin_types.entry_f16->llvm_type, ""); + } + + return result; } static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, @@ -10475,7 +10499,7 @@ void codegen_build_object(CodeGen *g) { codegen_add_time_event(g, "Done"); codegen_switch_sub_prog_node(g, nullptr); - + // append all export symbols to stage2 so we can provide them to the linker if (target_is_wasm(g->zig_target)){ Error err;