Merge "Add regression tests for 32-bit x86 struct layout bug fixes."
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/RSTestCore.java b/tests/java_api/RsTest/src/com/android/rs/test/RSTestCore.java
index 0583cb7..ac8dad5 100644
--- a/tests/java_api/RsTest/src/com/android/rs/test/RSTestCore.java
+++ b/tests/java_api/RsTest/src/com/android/rs/test/RSTestCore.java
@@ -106,7 +106,10 @@
         unitTests.add(new UT_reduce(this, mCtx));
         unitTests.add(new UT_reduce_backward(this, mCtx));
         unitTests.add(new UT_small_struct(this, mCtx));
+        unitTests.add(new UT_small_struct_2(this, mCtx));
         unitTests.add(new UT_struct_field(this, mCtx));
+        unitTests.add(new UT_struct_field_simple(this, mCtx));
+        unitTests.add(new UT_bitfield(this, mCtx));
 
         /*
         unitTests.add(new UnitTest(null, "<Pass>", 1));
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/UT_bitfield.java b/tests/java_api/RsTest/src/com/android/rs/test/UT_bitfield.java
new file mode 100644
index 0000000..4ba4b69
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/UT_bitfield.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.renderscript.RenderScript;
+
+public class UT_bitfield extends UnitTest {
+
+    protected UT_bitfield(RSTestCore rstc, Context ctx) {
+        super(rstc, "Bitfield", ctx);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bitfield s = new ScriptC_bitfield(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        final long L = 0x76543210fedcba98L;
+        final int I = 0x12345678;
+
+        s.invoke_choose(1);
+        s.invoke_setUnion(L, I);
+        s.invoke_testUnion(L, I);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct.java b/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct.java
index 4f23b5d..ca96b61 100644
--- a/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct.java
+++ b/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct.java
@@ -21,6 +21,8 @@
 import android.renderscript.RenderScript;
 import android.renderscript.Type;
 
+// Same as UT_small_struct_2.java except for names of classes and of test.
+
 public class UT_small_struct extends UnitTest {
     private Allocation A;
     private Allocation B;
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct_2.java b/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct_2.java
new file mode 100644
index 0000000..7f03b44
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/UT_small_struct_2.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+
+// Same as UT_small_struct.java except for names of classes and of test.
+
+public class UT_small_struct_2 extends UnitTest {
+    private Allocation A;
+    private Allocation B;
+    private static final int dimX = 3;
+    private static final int dimY = 2;
+
+    protected UT_small_struct_2(RSTestCore rstc, Context ctx) {
+        super(rstc, "Small Structs 2", ctx);
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_small_struct_2 s) {
+        s.set_gDimX(dimX);
+        s.set_gDimY(dimY);
+
+        Type.Builder builderA = new Type.Builder(RS, ScriptField_small_struct_2.createElement(RS));
+        builderA.setX(dimX);
+        builderA.setY(dimY);
+
+        A = Allocation.createTyped(RS, builderA.create());
+        s.set_A(A);
+
+        Type.Builder builderB = new Type.Builder(RS, ScriptField_struct_of_struct_2.createElement(RS));
+        builderB.setX(dimX);
+        builderB.setY(dimY);
+
+        B = Allocation.createTyped(RS, builderB.create());
+        s.set_B(B);
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_small_struct_2 s = new ScriptC_small_struct_2(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        initializeGlobals(pRS, s);
+        s.forEach_setStruct(A);
+        s.forEach_setArrayOfStruct(B);
+        s.invoke_test();
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/UT_struct_field_simple.java b/tests/java_api/RsTest/src/com/android/rs/test/UT_struct_field_simple.java
new file mode 100644
index 0000000..748c2a3
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/UT_struct_field_simple.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.renderscript.RenderScript;
+
+public class UT_struct_field_simple extends UnitTest {
+
+    protected UT_struct_field_simple(RSTestCore rstc, Context ctx) {
+        super(rstc, "Structure Fields", ctx);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_struct_field_simple s = new ScriptC_struct_field_simple(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        ScriptField_Simple.Item simple = new ScriptField_Simple.Item();
+        final int I = 0x12345678;
+        final long L = 0x76543210fedcba98L;
+        simple.I = I;
+        simple.L = L;
+        s.set_simple(simple);
+
+        s.invoke_checkSimple(I, L);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
+// struct Simple {
+//     int I;
+//     long L;
+// };
+//
+// Consistently padded, we expect:
+//   I    = 0x12345678
+//   L.lo = 0xfedcba98
+//   L.hi = 0x76543210
+//
+// And indeed on N9 --abi armeabi-v7a (i.e., ARM-32) we see:
+//
+//   09-23 21:55:51.026  5990  6005 D RenderScript: argI        305419896  0x12345678
+//   09-23 21:55:51.026  5990  6005 D RenderScript: simple.I    305419896  0x12345678
+//   09-23 21:55:51.026  5990  6005 D RenderScript: argL.lo     4275878552  0xfedcba98
+//   09-23 21:55:51.026  5990  6005 D RenderScript: simple.L.lo 4275878552  0xfedcba98
+//   09-23 21:55:51.026  5990  6005 D RenderScript: argL.hi     1985229328  0x76543210
+//   09-23 21:55:51.026  5990  6005 D RenderScript: simple.L.hi 1985229328  0x76543210
+//   09-23 21:55:51.026  5990  6005 D RenderScript: struct_field_simple PASSED 0  0x0
+//
+// Inconsistently padded (Java pads, x86-32 script does not), we expect:
+//   I    = 0x12345678  // fine
+//   L.lo = 0           // oops, script read the padding
+//   L.hi = 0xfedcba98  // oops, script read L.lo
+//
+// And indeed on fugu (i.e., x86-32) before the fix for http://b/29154200 and http://b/28070272
+// we see:
+//
+//   09-23 21:39:19.775  4090  4107 D RenderScript: argI        305419896  0x12345678
+//   09-23 21:39:19.775  4090  4107 D RenderScript: simple.I    305419896  0x12345678
+//   09-23 21:39:19.775  4090  4107 D RenderScript: argL.lo     4275878552  0xfedcba98
+//   09-23 21:39:19.775  4090  4107 D RenderScript: simple.L.lo 0  0x0
+//   09-23 21:39:19.775  4090  4107 D RenderScript: argL.hi     1985229328  0x76543210
+//   09-23 21:39:19.775  4090  4107 D RenderScript: simple.L.hi 4275878552  0xfedcba98
+//   09-23 21:39:19.775  4090  4107 D RenderScript: simple.L == argL FAILED 0  0x0
+//   09-23 21:39:19.775  4090  4107 D RenderScript: struct_field_simple FAILED 0  0x0
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/bitfield.rs b/tests/java_api/RsTest/src/com/android/rs/test/bitfield.rs
new file mode 100644
index 0000000..bce32f7
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/bitfield.rs
@@ -0,0 +1,87 @@
+#include "shared.rsh"
+
+// There is a C99 rule (under "Structure and union members") that
+// reads "One special guarantee is made in order to simplify the use
+// of unions: if a union contains several structures that share a
+// common initial sequence, and if the union object currently contains
+// one of these structures, it is permitted to inspect the common
+// initial part of any of them anywhere that a declaration of the
+// completed type of the union is visible. Two structures share a
+// common initial sequence if corresponding members have compatible
+// types (and, for bit-fields, the same widths) for a sequence of one
+// or more initial members."
+//
+// We want to ensure that the common initial sequences of exported
+// and non-exported types have the same layout.
+
+// An exported type (because we declare a global variable of this type)
+struct NoBitfield {
+    int I;
+    // expect 4 bytes of padding here
+    long L;
+    float F;
+    // expect 4 bytes of padding here
+};
+
+struct NoBitfield junk;  // just to make this an exported type
+
+// A non-exported type that shares a common initial sequence with NoBitfield
+struct Bitfield {
+    int I;
+    // expect 4 bytes of padding here
+    long L;
+    uint U:3;
+};
+
+union CommonInitialSequence {
+    struct NoBitfield nbf;
+    struct   Bitfield  bf;
+};
+
+static union CommonInitialSequence U, V;
+
+static struct NoBitfield *nbf;
+static struct   Bitfield * bf;
+
+// Note: Sets through the exported type (NoBitfield)
+void setUnion(long argL, int argI) {
+    nbf->L = argL;
+    nbf->I = argI;
+}
+
+// Note: Tests through the non-exported type (Bitfield)
+void testUnion(long argL, int argI) {
+    bool failed = false;
+
+    rsDebug("argI    ", argI);
+    rsDebug("bf->I   ", bf->I);
+    rsDebug("argL.lo ", (unsigned)argL & ~0U);
+    rsDebug("bf->L.lo", (unsigned)bf->L & ~0U);
+    rsDebug("argL.hi ", (unsigned)((ulong)argL >> 32));
+    rsDebug("bf->L.hi", (unsigned)((ulong)bf->L >> 32));
+
+    _RS_ASSERT(bf->I == argI);
+    _RS_ASSERT(bf->L == argL);
+
+    if (failed) {
+        rsDebug("bitfield FAILED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("bitfield PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
+// Note: Prevent compiler from optimizing setUnion()/testUnion()
+//       to convert indirect accesses through nbf/bf into direct
+//       accesses through U or V.
+void choose(int i) {
+    if (i) {
+        nbf = &U.nbf;
+         bf = &U. bf;
+    } else {
+        nbf = &V.nbf;
+         bf = &V. bf;
+    }
+}
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/small_struct.rs b/tests/java_api/RsTest/src/com/android/rs/test/small_struct.rs
index 9aa9677..4c1f437 100644
--- a/tests/java_api/RsTest/src/com/android/rs/test/small_struct.rs
+++ b/tests/java_api/RsTest/src/com/android/rs/test/small_struct.rs
@@ -1,3 +1,5 @@
+// Same as small_struct_2.rs except for location of padding in struct small_struct[_2].
+
 #include "shared.rsh"
 
 int gDimX;
@@ -11,6 +13,7 @@
 
 typedef struct small_struct {
     int i;
+    // expect 4 bytes of padding here
     long l;
 } small_struct;
 
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/small_struct_2.rs b/tests/java_api/RsTest/src/com/android/rs/test/small_struct_2.rs
new file mode 100644
index 0000000..f56f999
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/small_struct_2.rs
@@ -0,0 +1,70 @@
+// Same as small_struct.rs except for location of padding in struct small_struct[_2].
+
+#include "shared.rsh"
+
+int gDimX;
+int gDimY;
+
+rs_allocation A;
+rs_allocation B;
+
+static int gIntStart = 0x7;
+static long gLongStart = 0x12345678abcdef12;
+
+typedef struct small_struct_2 {
+    long l;
+    int i;
+    // expect 4 bytes of padding here
+} small_struct_2;
+
+#define ARRAY_LEN 3
+
+typedef struct struct_of_struct_2 {
+    small_struct_2 arr[ARRAY_LEN];
+} struct_of_struct_2;
+
+void test() {
+    bool failed = false;
+    for (int x = 0; x < gDimX; x ++) {
+        for (int y = 0; y < gDimY; y ++) {
+            small_struct_2 *v = (small_struct_2 *) rsGetElementAt(A, x, y);
+            _RS_ASSERT_EQU(v->i, gIntStart + y * gDimX + x);
+            _RS_ASSERT_EQU(v->l, gLongStart + y * gDimX + x);
+        }
+    }
+
+    for (int x = 0; x < gDimX; x ++) {
+        for (int y = 0; y < gDimY; y ++) {
+            struct_of_struct_2 *v = (struct_of_struct_2 *) rsGetElementAt(B, x, y);
+            for (int idx = 0; idx < ARRAY_LEN; idx ++) {
+                _RS_ASSERT_EQU((*v).arr[idx].i, gIntStart + y * gDimX + x + idx);
+                _RS_ASSERT_EQU((*v).arr[idx].l, gLongStart + y * gDimX + x + idx);
+            }
+        }
+    }
+
+    if (failed) {
+        rsDebug("small_struct_2 test FAILED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("small_struct_2 test PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
+small_struct_2 RS_KERNEL setStruct(int x, int y) {
+    small_struct_2 output;
+    output.i = gIntStart + y * gDimX + x;
+    output.l = gLongStart + y * gDimX + x;
+    return output;
+}
+
+struct_of_struct_2 RS_KERNEL setArrayOfStruct(int x, int y) {
+    struct_of_struct_2 output;
+    for (int idx = 0; idx < ARRAY_LEN; idx ++) {
+        output.arr[idx].i = gIntStart + y * gDimX + x + idx;
+        output.arr[idx].l = gLongStart + y * gDimX + x + idx;
+    }
+    return output;
+}
diff --git a/tests/java_api/RsTest/src/com/android/rs/test/struct_field_simple.rs b/tests/java_api/RsTest/src/com/android/rs/test/struct_field_simple.rs
new file mode 100644
index 0000000..fb5ccbd
--- /dev/null
+++ b/tests/java_api/RsTest/src/com/android/rs/test/struct_field_simple.rs
@@ -0,0 +1,31 @@
+#include "shared.rsh"
+
+struct Simple {
+    int I;
+    long L;
+};
+
+struct Simple simple;
+
+void checkSimple(int argI, long argL) {
+    bool failed = false;
+
+    rsDebug("argI       ", argI);
+    rsDebug("simple.I   ", simple.I);
+    rsDebug("argL.lo    ", (unsigned)argL & ~0U);
+    rsDebug("simple.L.lo", (unsigned)simple.L & ~0U);
+    rsDebug("argL.hi    ", (unsigned)((ulong)argL >> 32));
+    rsDebug("simple.L.hi", (unsigned)((ulong)simple.L >> 32));
+
+    _RS_ASSERT(simple.I == argI);
+    _RS_ASSERT(simple.L == argL);
+
+    if (failed) {
+        rsDebug("struct_field_simple FAILED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("struct_field_simple PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}