bridge: preserve pointerness in C-ABI oracle

To support stack maps it is necessary to preserve pointerness.
Make sure we don't lose pointerness in the C-ABI oracle.

Change-Id: I6a73f3350c1e280aef7921097bc8938538ac3456
Reviewed-on: https://go-review.googlesource.com/137757
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm-cabi-oracle.cpp b/bridge/go-llvm-cabi-oracle.cpp
index 023c664..abe87db 100644
--- a/bridge/go-llvm-cabi-oracle.cpp
+++ b/bridge/go-llvm-cabi-oracle.cpp
@@ -372,13 +372,20 @@
       unsigned bytes = ebr.offsets[nel-1] - ebr.offsets[0] +
           tm()->llvmTypeSize(ebr.types[nel-1]);
       assert(bytes && bytes <= 8);
-      ebr.abiDirectType = tm()->llvmArbitraryIntegerType(bytes);
+      // Preserve pointerness for the use of GC.
+      // TODO: this assumes pointer is 8 byte, so we never pack pointer
+      // and other stuff together.
+      if (ebr.types[0]->isPointerTy())
+        ebr.abiDirectType = tm()->llvmPtrType();
+      else
+        ebr.abiDirectType = tm()->llvmArbitraryIntegerType(bytes);
       intRegions += 1;
     }
   }
 
   // See the example above for more on why this is needed.
-  if (intRegions == 2)
+  if (intRegions == 2 &&
+      ebrs_[0].abiDirectType->isIntegerTy())
     ebrs_[0].abiDirectType = tm()->llvmArbitraryIntegerType(8);
   else if (floatRegions == 2 &&
            ebrs_[0].abiDirectType == tm()->llvmFloatType())
diff --git a/unittests/BackendCore/BackendCABIOracleTests.cpp b/unittests/BackendCore/BackendCABIOracleTests.cpp
index 0c431b6..29ff26b 100644
--- a/unittests/BackendCore/BackendCABIOracleTests.cpp
+++ b/unittests/BackendCore/BackendCABIOracleTests.cpp
@@ -68,6 +68,7 @@
   Btype *bi16t = be->integer_type(false, 16);
   Btype *bf32t = be->float_type(32);
   Btype *bf64t = be->float_type(64);
+  Btype *bpu64t = be->pointer_type(bu64t);
   Btype *bpf64t = be->pointer_type(bf64t);
   Btype *st0 = mkBackendStruct(be, nullptr);
   Btype *st1 = mkBackendStruct(be, bi8t, "a", bu8t, "b", bf32t, "c", nullptr);
@@ -79,6 +80,10 @@
                                bu64t, "c", nullptr);
   Btype *st7 = mkBackendStruct(be, bf32t, "f1", bu32t, "f2", nullptr);
   Btype *st8 = mkBackendStruct(be, bi8t, "f1", bi16t, "f2", st7, "f3", nullptr);
+  Btype *stii = mkBackendStruct(be, bu64t, "a", bu64t, "b", nullptr);
+  Btype *stip = mkBackendStruct(be, bu64t, "a", bpu64t, "b", nullptr);
+  Btype *stpi = mkBackendStruct(be, bpu64t, "a", bu64t, "b", nullptr);
+  Btype *stpp = mkBackendStruct(be, bpu64t, "a", bpu64t, "b", nullptr);
   Btype *at0 = be->array_type(bu32t, mkInt64Const(be, int64_t(0)));
   Btype *at1 = be->array_type(bu32t, mkInt64Const(be, int64_t(1)));
   Btype *at2 = be->array_type(bu32t, mkInt64Const(be, int64_t(3)));
@@ -182,6 +187,16 @@
              "Param 1: Direct AttrNest { i8* } sigOffset: 0 "
              "Param 2: Direct { i64, i64 } sigOffset: 1",
              "{ i64, i32 } (i8*, i64, i64)"),
+
+    // 12
+    // Make sure pointerness is preserved.
+    FcnItem( { stip }, { stii, stpp, stpi },
+             "Return: Direct { { i64, i8* } } sigOffset: -1 "
+             "Param 1: Direct AttrNest { i8* } sigOffset: 0 "
+             "Param 2: Direct { i64, i64 } sigOffset: 1 "
+             "Param 3: Direct { i8*, i8* } sigOffset: 3 "
+             "Param 4: Direct { i8*, i64 } sigOffset: 5",
+             "{ i64, i8* } (i8*, i64, i64, i8*, i8*, i8*, i64)"),
   };
 
   unsigned count = 1;