authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-12 20:12:36-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-12 20:12:36-05:00
logce14bc7176f9e441064ffdde2d85e35fd78977f2
tree3b1d25c042403d9e6d071bfd6de71b0b6ec4b21a
parent95eb711ca8c0843ede117f61025c5eda0102f845
parent36c4037144bdc3d80530205c0e2e9c31bee0f114
signature Signed by PGP key 4AEE18F83AFDEB23

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

stage1: Follow the C ABI for return types

3 files changed, 151 insertions(+), 0 deletions(-)

src/stage1/codegen.cpp+47
...@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -487,6 +487,53 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
487 addLLVMFnAttr(llvm_fn, "noreturn");487 addLLVMFnAttr(llvm_fn, "noreturn");
488 }488 }
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
490 if (fn->body_node != nullptr) {537 if (fn->body_node != nullptr) {
491 maybe_export_dll(g, llvm_fn, linkage);538 maybe_export_dll(g, llvm_fn, linkage);
492539
test/stage1/c_abi/cfuncs.c+52
...@@ -24,6 +24,16 @@ void zig_f32(float);...@@ -24,6 +24,16 @@ void zig_f32(float);
24void zig_f64(double);24void zig_f64(double);
25void zig_five_floats(float, float, float, float, float);25void zig_five_floats(float, float, float, float, float);
2626
27bool zig_ret_bool();
28uint8_t zig_ret_u8();
29uint16_t zig_ret_u16();
30uint32_t zig_ret_u32();
31uint64_t zig_ret_u64();
32int8_t zig_ret_i8();
33int16_t zig_ret_i16();
34int32_t zig_ret_i32();
35int64_t zig_ret_i64();
36
27void zig_ptr(void *);37void zig_ptr(void *);
2838
29void zig_bool(bool);39void zig_bool(bool);
...@@ -119,6 +129,20 @@ void run_c_tests(void) {...@@ -119,6 +129,20 @@ void run_c_tests(void) {
119 assert_or_panic(res.d == 23);129 assert_or_panic(res.d == 23);
120 assert_or_panic(res.e == 24);130 assert_or_panic(res.e == 24);
121 }131 }
132
133 {
134 assert_or_panic(zig_ret_bool() == 1);
135
136 assert_or_panic(zig_ret_u8() == 0xff);
137 assert_or_panic(zig_ret_u16() == 0xffff);
138 assert_or_panic(zig_ret_u32() == 0xffffffff);
139 assert_or_panic(zig_ret_u64() == 0xffffffffffffffff);
140
141 assert_or_panic(zig_ret_i8() == -1);
142 assert_or_panic(zig_ret_i16() == -1);
143 assert_or_panic(zig_ret_i32() == -1);
144 assert_or_panic(zig_ret_i64() == -1);
145 }
122}146}
123147
124void c_u8(uint8_t x) {148void c_u8(uint8_t x) {
...@@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {...@@ -236,3 +260,31 @@ void c_big_struct_floats(Vector5 vec) {
236 assert_or_panic(vec.w == 69);260 assert_or_panic(vec.w == 69);
237 assert_or_panic(vec.q == 55);261 assert_or_panic(vec.q == 55);
238}262}
263
264bool c_ret_bool() {
265 return 1;
266}
267uint8_t c_ret_u8() {
268 return 0xff;
269}
270uint16_t c_ret_u16() {
271 return 0xffff;
272}
273uint32_t c_ret_u32() {
274 return 0xffffffff;
275}
276uint64_t c_ret_u64() {
277 return 0xffffffffffffffff;
278}
279int8_t c_ret_i8() {
280 return -1;
281}
282int16_t c_ret_i16() {
283 return -1;
284}
285int32_t c_ret_i32() {
286 return -1;
287}
288int64_t c_ret_i64() {
289 return -1;
290}
test/stage1/c_abi/main.zig+52
...@@ -284,3 +284,55 @@ test "C ABI structs of floats as parameter" {...@@ -284,3 +284,55 @@ test "C ABI structs of floats as parameter" {
284 };284 };
285 c_big_struct_floats(v5);285 c_big_struct_floats(v5);
286}286}
287
288export fn zig_ret_bool() bool {
289 return true;
290}
291export fn zig_ret_u8() u8 {
292 return 0xff;
293}
294export fn zig_ret_u16() u16 {
295 return 0xffff;
296}
297export fn zig_ret_u32() u32 {
298 return 0xffffffff;
299}
300export fn zig_ret_u64() u64 {
301 return 0xffffffffffffffff;
302}
303export fn zig_ret_i8() i8 {
304 return -1;
305}
306export fn zig_ret_i16() i16 {
307 return -1;
308}
309export fn zig_ret_i32() i32 {
310 return -1;
311}
312export fn zig_ret_i64() i64 {
313 return -1;
314}
315
316extern fn c_ret_bool() bool;
317extern fn c_ret_u8() u8;
318extern fn c_ret_u16() u16;
319extern fn c_ret_u32() u32;
320extern fn c_ret_u64() u64;
321extern fn c_ret_i8() i8;
322extern fn c_ret_i16() i16;
323extern fn c_ret_i32() i32;
324extern fn c_ret_i64() i64;
325
326test "C ABI integer return types" {
327 expect(c_ret_bool() == true);
328
329 expect(c_ret_u8() == 0xff);
330 expect(c_ret_u16() == 0xffff);
331 expect(c_ret_u32() == 0xffffffff);
332 expect(c_ret_u64() == 0xffffffffffffffff);
333
334 expect(c_ret_i8() == -1);
335 expect(c_ret_i16() == -1);
336 expect(c_ret_i32() == -1);
337 expect(c_ret_i64() == -1);
338}