authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-03-05 12:37:49+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-03-12 11:50:56+01:00
log7813068e218457b074576d3dac8926b7923f97ba
tree77bbd16f28956ab8466801fb7dc2376eeba6b243
parent9f722f43ac449caa0e09c1b7bb1bad0581ef323d

stage1: Follow the C ABI for return types

The current implementation of the target C ABI rules is hopelessly bad, let's tack some more rules on top in order to prevent some miscompilations. Truth to be told the same rule should be applied also to parameters, but I really can't stand stage1.

1 files changed, 47 insertions(+), 0 deletions(-)

src/stage1/codegen.cpp+47
......@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
487487 addLLVMFnAttr(llvm_fn, "noreturn");
488488 }
489489
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
490537 if (fn->body_node != nullptr) {
491538 maybe_export_dll(g, llvm_fn, linkage);
492539