| ... | @@ -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; |
| 1622 | | 1622 | |
| | 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 | } |
| 1678 | | 1695 | |
| 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 | } |
| 1681 | | 1705 | |
| 1682 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, | 1706 | 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) { | ... | @@ -10475,7 +10499,7 @@ void codegen_build_object(CodeGen *g) { |
| 10475 | | 10499 | |
| 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 linker | 10503 | // 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; |