| ... | ... | @@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 487 | 487 | addLLVMFnAttr(llvm_fn, "noreturn"); |
| 488 | 488 | } |
| 489 | 489 | |
| 490 | if (!calling_convention_allows_zig_types(cc)) { |
| 491 | // A simplistic and desperate attempt at making the compiler respect the |
| 492 | // target ABI for return types. |
| 493 | // This is just enough to avoid miscompiling the test suite, it will be |
| 494 | // better in stage2. |
| 495 | ZigType *int_type = return_type->id == ZigTypeIdInt ? return_type : |
| 496 | return_type->id == ZigTypeIdEnum ? return_type->data.enumeration.tag_int_type : |
| 497 | nullptr; |
| 498 | |
| 499 | if (int_type != nullptr) { |
| 500 | const bool is_signed = int_type->data.integral.is_signed; |
| 501 | const uint32_t bit_width = int_type->data.integral.bit_count; |
| 502 | bool should_extend = false; |
| 503 | |
| 504 | // Rough equivalent of Clang's isPromotableIntegerType. |
| 505 | switch (bit_width) { |
| 506 | case 1: // bool |
| 507 | case 8: // {un,}signed char |
| 508 | case 16: // {un,}signed short |
| 509 | should_extend = true; |
| 510 | break; |
| 511 | default: |
| 512 | break; |
| 513 | } |
| 514 | |
| 515 | switch (g->zig_target->arch) { |
| 516 | case ZigLLVM_sparcv9: |
| 517 | case ZigLLVM_riscv64: |
| 518 | case ZigLLVM_ppc64: |
| 519 | case ZigLLVM_ppc64le: |
| 520 | // Always extend to the register width. |
| 521 | should_extend = bit_width < 64; |
| 522 | break; |
| 523 | default: |
| 524 | break; |
| 525 | } |
| 526 | |
| 527 | // {zero,sign}-extend the result. |
| 528 | if (should_extend) { |
| 529 | if (is_signed) |
| 530 | addLLVMAttr(llvm_fn, 0, "signext"); |
| 531 | else |
| 532 | addLLVMAttr(llvm_fn, 0, "zeroext"); |
| 533 | } |
| 534 | } |
| 535 | } |
| 536 | |
| 490 | 537 | if (fn->body_node != nullptr) { |
| 491 | 538 | maybe_export_dll(g, llvm_fn, linkage); |
| 492 | 539 | |