aarch32: longs may be passed in incorrect register

XMLWordPrintable

    • aarch32
    • linux

      Current java calling convention have a bug: when last long argument fitting to be passed on registers, high word could occupy register outside of register set intended for argument passing. With java c/c argument on registers r1,r2,r3,r0: r4 may be used. Test case for this issue is not straightforward, because only few places uses r4 directly, so it's rarely destroyed. However, itable_stub is one of them, so here is a test.

      === Test ===

      class Test {
              public static final long goldValue = (0xdeadL << 32) | 0xdead;

              public static void checkLong(long j3) {
                      System.out.printf("%s: got %x, should be %x\n", j3 == goldValue ? "OK" : "Fail", j3, goldValue);
              }

              interface TestInterface {
                      public abstract void callee(int i1, long j3);
              }

              class TestImpl1 implements TestInterface {
                      @Override
                      public void callee(int i1, long j3) {
                              checkLong(j3);
                      }
              }

              class TestImpl2 implements TestInterface {
                      @Override
                      public void callee(int i1, long j3) {
                              checkLong(j3);
                      }
              }

              class TestImpl3 implements TestInterface {
                      @Override
                      public void callee(int i1, long j3) {
                              checkLong(j3);
                      }
              }

              public void vmain() {
                      TestInterface ifaces[] = { new TestImpl1(), new TestImpl2(), new TestImpl3() };
                      TestInterface iface = null;
                      for (int i = 0; i < ifaces.length; ++i) {
                              iface = ifaces[i];
                              iface.callee(0, goldValue);
                      }
              }

              public static void main(String[] args) {
                      Test test = new Test();
                      test.vmain();
              }
      }
      === End of Test ===

      However, problem could be verified by hands easier. Calling java_calling_convention for checkLong2 signature will allocate r1 for i1, r2 for i2 and r4:r3 for j3; however, r0:r3 expected.

      === TestLongPass ===
      class TestLongPass {
              public static final long goldValue = (0x31414L << 32) | 0x31415;

              public static void checkLong2(int i1, int i2, long j3) {
                      System.out.printf("%s: got %x, should be %x\n", j3 == goldValue ? "OK" : "Fail", j3, goldValue);
              }

              public static void main(String[] args) {
                      checkLong2(0, 0, goldValue);
              }
      }
      === End of TestLongPass

            Assignee:
            Ed Nevill
            Reporter:
            Ed Nevill
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: