tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] [PATCH] Fix passing of large function arguments on riscv6


From: Ziyao
Subject: [Tinycc-devel] [PATCH] Fix passing of large function arguments on riscv64
Date: Sun, 09 Apr 2023 06:08:35 +0800

Hi list,

I was working with riscv64-tcc and found that it failed to compile this
simple code.

  struct foo {
          int a[768];
  };
  void f(struct foo a)
  {
          (void)a.a[767];
  }
  int main(void)
  {
          struct foo a;
          f(a);
          return 0;
  }

riscv64-tcc ended up with an assertion failure.

  $ riscv64-tcc test.c -c
  Assertion failed: ! ((imm + (1 << 11)) >> 12) (riscv64-gen.c: EI: 135)
  Aborted
  $ riscv64-tcc -v
tcc version 0.9.27 mob:e7262ac 2023-03-23T20:02:19+01:00 (riscv64 Linux)

It is caused by wrong adjustment of stack in gfunc_call() in
riscv64-gen.c. Instruction ADDIW on riscv64 could accept a 12-bit
immediate number only, which will be sign-extended. So only adjustments
up to 2048 bytes could be done in a single ADDIW instruction. For the
same reasons, more works need done when bit 11 (the 12th bit) of the
immediate number is set.

This patch fixes the problem and has been pushed to mob branch. A
regression test is also included.

---
Ziyao

---

diff --git a/riscv64-gen.c b/riscv64-gen.c
index 490eca7..8a17b70 100644
--- a/riscv64-gen.c
+++ b/riscv64-gen.c
@@ -627,10 +627,14 @@ ST_FUNC void gfunc_call(int nb_args)
     if ((vtop->r & VT_VALMASK) == VT_CMP)
       gv(RC_INT);

+
     if (stack_add) {
-        if (stack_add >= 0x1000) {
- o(0x37 | (5 << 7) | (-stack_add & 0xfffff000)); //lui t0, upper(v) - EI(0x13, 0, 5, 5, -stack_add << 20 >> 20); // addi t0, t0, lo(v)
+        if (stack_add >= 0x800) {
+ unsigned int bit11 = (((unsigned int)-stack_add) >> 11) & 1;
+            o(0x37 | (5 << 7) |
+ ((-stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v) + EI(0x13, 0, 5, 5, ((-stack_add & 0xfff) - bit11 * (1 << 12))); + // addi t0, t0, lo(v)
             ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0
         }
         else
@@ -757,9 +761,12 @@ done:
     gcall_or_jmp(1);
     vtop -= nb_args + 1;
     if (stack_add) {
-        if (stack_add >= 0x1000) {
- o(0x37 | (5 << 7) | (stack_add & 0xfffff000)); //lui t0, upper(v) - EI(0x13, 0, 5, 5, stack_add << 20 >> 20); // addi t0, t0, lo(v)
+        if (stack_add >= 0x800) {
+            unsigned int bit11 = ((unsigned int)stack_add >> 11) & 1;
+            o(0x37 | (5 << 7) |
+ ((stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v)
+            EI(0x13, 0, 5, 5, (stack_add & 0xfff) - bit11 * (1 << 12));
+ // addi t0, t0, lo(v)
             ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0
         }
         else
diff --git a/tests/tests2/130_large_argument.c b/tests/tests2/130_large_argument.c
new file mode 100644
index 0000000..8415c85
--- /dev/null
+++ b/tests/tests2/130_large_argument.c
@@ -0,0 +1,41 @@
+#include<stdio.h>
+
+struct large1 {
+    int a[768];
+};
+
+struct large2 {
+    int a[1920];
+};
+
+void pass_large_struct1(struct large1 in)
+{
+    printf("%d %d\n", in.a[200], in.a[767]);
+    return;
+}
+
+void pass_large_struct2(struct large2 in)
+{
+    printf("%d %d %d\n", in.a[200], in.a[1023], in.a[1919]);
+    return;
+}
+
+void pass_many_args(int a, int b, int c, int d, int e, int f, int g, int h, int i,
+                    int j, int k, int l, int m)
+{
+ printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i,
+           j, k, l, m);
+    return;
+}
+
+struct large1 l1 = { .a = { [200] = 1, [767] = 2 } };
+struct large2 l2 = { .a = { [200] = 3, [1023] = 4, [1919] = 5} };
+
+int main(void)
+{
+    pass_large_struct1(l1);
+    pass_large_struct2(l2);
+    pass_many_args(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
+
+    return 0;
+}
diff --git a/tests/tests2/130_large_argument.expect b/tests/tests2/130_large_argument.expect
new file mode 100644
index 0000000..8c5d9cd
--- /dev/null
+++ b/tests/tests2/130_large_argument.expect
@@ -0,0 +1,3 @@
+1 2
+3 4 5
+13 12 11 10 9 8 7 6 5 4 3 2 1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]