diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-03-12 20:12:36 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-12 20:12:36 -0500 |
| commit | ce14bc7176f9e441064ffdde2d85e35fd78977f2 (patch) | |
| tree | 3b1d25c042403d9e6d071bfd6de71b0b6ec4b21a /src/stage1 | |
| parent | 95eb711ca8c0843ede117f61025c5eda0102f845 (diff) | |
| parent | 36c4037144bdc3d80530205c0e2e9c31bee0f114 (diff) | |
| download | zig-ce14bc7176f9e441064ffdde2d85e35fd78977f2.tar.gz zig-ce14bc7176f9e441064ffdde2d85e35fd78977f2.zip | |
Merge pull request #8152 from LemonBoy/fix-riscv-ret
stage1: Follow the C ABI for return types
Diffstat (limited to 'src/stage1')
| -rw-r--r-- | src/stage1/codegen.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 97daf249b1..5c37a1247b 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { addLLVMFnAttr(llvm_fn, "noreturn"); } + if (!calling_convention_allows_zig_types(cc)) { + // A simplistic and desperate attempt at making the compiler respect the + // target ABI for return types. + // This is just enough to avoid miscompiling the test suite, it will be + // better in stage2. + ZigType *int_type = return_type->id == ZigTypeIdInt ? return_type : + return_type->id == ZigTypeIdEnum ? return_type->data.enumeration.tag_int_type : + nullptr; + + if (int_type != nullptr) { + const bool is_signed = int_type->data.integral.is_signed; + const uint32_t bit_width = int_type->data.integral.bit_count; + bool should_extend = false; + + // Rough equivalent of Clang's isPromotableIntegerType. + switch (bit_width) { + case 1: // bool + case 8: // {un,}signed char + case 16: // {un,}signed short + should_extend = true; + break; + default: + break; + } + + switch (g->zig_target->arch) { + case ZigLLVM_sparcv9: + case ZigLLVM_riscv64: + case ZigLLVM_ppc64: + case ZigLLVM_ppc64le: + // Always extend to the register width. + should_extend = bit_width < 64; + break; + default: + break; + } + + // {zero,sign}-extend the result. + if (should_extend) { + if (is_signed) + addLLVMAttr(llvm_fn, 0, "signext"); + else + addLLVMAttr(llvm_fn, 0, "zeroext"); + } + } + } + if (fn->body_node != nullptr) { maybe_export_dll(g, llvm_fn, linkage); |
