authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-02-15 20:22:01+07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-17 14:46:04+02:00
log755d116ecf2d221e2ad8b572c58a7d4f99163ff9
tree91cd4f2689e323750c0f539bfb60777afcd3e3c4
parent02902cc099d9736d589ac4f0e0ff671d7dfa9557

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.

1 files changed, 28 insertions(+), 4 deletions(-)

src/stage1/codegen.cpp+28-4
...@@ -1620,13 +1620,23 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty...@@ -1620,13 +1620,23 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty
1620 LLVMTypeRef return_type;1620 LLVMTypeRef return_type;
1621 const char *func_name;1621 const char *func_name;
16221622
1623 LLVMValueRef result;
1624 bool castTruncatedToF16 = false;
1625
1623 if (actual_bits == wanted_bits) {1626 if (actual_bits == wanted_bits) {
1624 return expr_val;1627 return expr_val;
1625 } else if (actual_bits == 80) {1628 } else if (actual_bits == 80) {
1626 param_type = g->builtin_types.entry_f80->llvm_type;1629 param_type = g->builtin_types.entry_f80->llvm_type;
1627 switch (wanted_bits) {1630 switch (wanted_bits) {
1628 case 16:1631 case 16:
1629 return_type = g->builtin_types.entry_f16->llvm_type;1632 // Only Arm has a native f16 type, other platforms soft-implement it
1633 // using u16 instead.
1634 if (target_is_arm(g->zig_target)) {
1635 return_type = g->builtin_types.entry_f16->llvm_type;
1636 } else {
1637 return_type = g->builtin_types.entry_u16->llvm_type;
1638 castTruncatedToF16 = true;
1639 }
1630 func_name = "__truncxfhf2";1640 func_name = "__truncxfhf2";
1631 break;1641 break;
1632 case 32:1642 case 32:
...@@ -1648,7 +1658,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty...@@ -1648,7 +1658,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty
1648 return_type = g->builtin_types.entry_f80->llvm_type;1658 return_type = g->builtin_types.entry_f80->llvm_type;
1649 switch (actual_bits) {1659 switch (actual_bits) {
1650 case 16:1660 case 16:
1651 param_type = g->builtin_types.entry_f16->llvm_type;1661 // Only Arm has a native f16 type, other platforms soft-implement it
1662 // using u16 instead.
1663 if (target_is_arm(g->zig_target)) {
1664 param_type = g->builtin_types.entry_f16->llvm_type;
1665 } else {
1666 param_type = g->builtin_types.entry_u16->llvm_type;
1667 expr_val = LLVMBuildBitCast(g->builder, expr_val, param_type, "");
1668 }
1652 func_name = "__extendhfxf2";1669 func_name = "__extendhfxf2";
1653 break;1670 break;
1654 case 32:1671 case 32:
...@@ -1676,7 +1693,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty...@@ -1676,7 +1693,14 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty
1676 func_ref = LLVMAddFunction(g->module, func_name, fn_type);1693 func_ref = LLVMAddFunction(g->module, func_name, fn_type);
1677 }1694 }
16781695
1679 return LLVMBuildCall(g->builder, func_ref, &expr_val, 1, "");1696 result = LLVMBuildCall(g->builder, func_ref, &expr_val, 1, "");
1697
1698 // On non-Arm platforms we need to bitcast __truncxfhf2 result back to f16
1699 if (castTruncatedToF16) {
1700 result = LLVMBuildBitCast(g->builder, result, g->builtin_types.entry_f16->llvm_type, "");
1701 }
1702
1703 return result;
1680}1704}
16811705
1682static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,1706static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
...@@ -10475,7 +10499,7 @@ void codegen_build_object(CodeGen *g) {...@@ -10475,7 +10499,7 @@ void codegen_build_object(CodeGen *g) {
1047510499
10476 codegen_add_time_event(g, "Done");10500 codegen_add_time_event(g, "Done");
10477 codegen_switch_sub_prog_node(g, nullptr);10501 codegen_switch_sub_prog_node(g, nullptr);
10478 10502
10479 // append all export symbols to stage2 so we can provide them to the linker10503 // append all export symbols to stage2 so we can provide them to the linker
10480 if (target_is_wasm(g->zig_target)){10504 if (target_is_wasm(g->zig_target)){
10481 Error err;10505 Error err;