Merge pull request #8152 from LemonBoy/fix-riscv-ret

stage1: Follow the C ABI for return types
This commit is contained in:
Andrew Kelley 2021-03-12 20:12:36 -05:00 committed by GitHub
commit ce14bc7176
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 0 deletions

View File

@ -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);

View File

@ -24,6 +24,16 @@ void zig_f32(float);
void zig_f64(double);
void zig_five_floats(float, float, float, float, float);
bool zig_ret_bool();
uint8_t zig_ret_u8();
uint16_t zig_ret_u16();
uint32_t zig_ret_u32();
uint64_t zig_ret_u64();
int8_t zig_ret_i8();
int16_t zig_ret_i16();
int32_t zig_ret_i32();
int64_t zig_ret_i64();
void zig_ptr(void *);
void zig_bool(bool);
@ -119,6 +129,20 @@ void run_c_tests(void) {
assert_or_panic(res.d == 23);
assert_or_panic(res.e == 24);
}
{
assert_or_panic(zig_ret_bool() == 1);
assert_or_panic(zig_ret_u8() == 0xff);
assert_or_panic(zig_ret_u16() == 0xffff);
assert_or_panic(zig_ret_u32() == 0xffffffff);
assert_or_panic(zig_ret_u64() == 0xffffffffffffffff);
assert_or_panic(zig_ret_i8() == -1);
assert_or_panic(zig_ret_i16() == -1);
assert_or_panic(zig_ret_i32() == -1);
assert_or_panic(zig_ret_i64() == -1);
}
}
void c_u8(uint8_t x) {
@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {
assert_or_panic(vec.w == 69);
assert_or_panic(vec.q == 55);
}
bool c_ret_bool() {
return 1;
}
uint8_t c_ret_u8() {
return 0xff;
}
uint16_t c_ret_u16() {
return 0xffff;
}
uint32_t c_ret_u32() {
return 0xffffffff;
}
uint64_t c_ret_u64() {
return 0xffffffffffffffff;
}
int8_t c_ret_i8() {
return -1;
}
int16_t c_ret_i16() {
return -1;
}
int32_t c_ret_i32() {
return -1;
}
int64_t c_ret_i64() {
return -1;
}

View File

@ -284,3 +284,55 @@ test "C ABI structs of floats as parameter" {
};
c_big_struct_floats(v5);
}
export fn zig_ret_bool() bool {
return true;
}
export fn zig_ret_u8() u8 {
return 0xff;
}
export fn zig_ret_u16() u16 {
return 0xffff;
}
export fn zig_ret_u32() u32 {
return 0xffffffff;
}
export fn zig_ret_u64() u64 {
return 0xffffffffffffffff;
}
export fn zig_ret_i8() i8 {
return -1;
}
export fn zig_ret_i16() i16 {
return -1;
}
export fn zig_ret_i32() i32 {
return -1;
}
export fn zig_ret_i64() i64 {
return -1;
}
extern fn c_ret_bool() bool;
extern fn c_ret_u8() u8;
extern fn c_ret_u16() u16;
extern fn c_ret_u32() u32;
extern fn c_ret_u64() u64;
extern fn c_ret_i8() i8;
extern fn c_ret_i16() i16;
extern fn c_ret_i32() i32;
extern fn c_ret_i64() i64;
test "C ABI integer return types" {
expect(c_ret_bool() == true);
expect(c_ret_u8() == 0xff);
expect(c_ret_u16() == 0xffff);
expect(c_ret_u32() == 0xffffffff);
expect(c_ret_u64() == 0xffffffffffffffff);
expect(c_ret_i8() == -1);
expect(c_ret_i16() == -1);
expect(c_ret_i32() == -1);
expect(c_ret_i64() == -1);
}