bridge: create byval args in address space 0

Technically, byval args are passed on stack, which is in address
space 0. Do it so.

When GC is enabled and build with -O3, the optimizer's argument
promotion may replace a byval arg with an alloca, which is in
address space 0. So byval arg needs also to be in address space
0.

TODO: should also do this for StructRet?

Change-Id: I5ff76a7757f2b0848cca9abc5257d43b84092f18
Reviewed-on: https://go-review.googlesource.com/c/154345
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm-cabi-oracle.cpp b/bridge/go-llvm-cabi-oracle.cpp
index abe87db..be6d0f6 100644
--- a/bridge/go-llvm-cabi-oracle.cpp
+++ b/bridge/go-llvm-cabi-oracle.cpp
@@ -652,8 +652,9 @@
   int sigOff = state.argCount();
 
   if (pdisp == ParmIndirect) {
-    // Value will be passed in memory
-    llvm::Type *ptrTyp = tm()->makeLLVMPointerType(ptyp);
+    // Value will be passed in memory on stack.
+    // Stack is always in address space 0.
+    llvm::Type *ptrTyp = llvm::PointerType::get(ptyp, 0);
     state.addIndirectArg();
     return CABIParamInfo(ptrTyp, ParmIndirect, AttrByVal, sigOff);
   }
@@ -684,7 +685,7 @@
     return CABIParamInfo(abiTypes, ParmDirect, attr, sigOff);
   } else {
     state.addIndirectArg();
-    llvm::Type *ptrTyp = tm()->makeLLVMPointerType(ptyp);
+    llvm::Type *ptrTyp = llvm::PointerType::get(ptyp, 0);
     return CABIParamInfo(ptrTyp, ParmIndirect, AttrByVal, sigOff);
   }
 }
diff --git a/bridge/go-llvm-materialize.cpp b/bridge/go-llvm-materialize.cpp
index 49c6238..1f9c669 100644
--- a/bridge/go-llvm-materialize.cpp
+++ b/bridge/go-llvm-materialize.cpp
@@ -155,9 +155,9 @@
       valType = val->getType();
     }
     if (lvalue || useCopyForLoadStore(type->type())) {
-      llvm::Type *pet = llvm::PointerType::get(expr->btype()->type(),
-                                               addressSpace_);
-      if (valType == pet)
+      llvm::Type *et = expr->btype()->type();
+      if (valType->isPointerTy() &&
+          valType->getPointerElementType() == et)
         toType = llvm::PointerType::get(toType, addressSpace_);
     }
   }
@@ -1141,6 +1141,8 @@
     if (paramInfo.attr() == AttrNest)
       continue;
 
+    BinstructionsLIRBuilder &builder = state.builder;
+
     // For arguments not passed by value, no call to resolveVarContext
     // (we want var address, not var value).
     if (paramInfo.disp() == ParmIndirect) {
@@ -1156,7 +1158,14 @@
         Bvariable *cv = genVarForConstant(cval, fn_args[idx]->btype());
         val = cv->value();
       }
-      assert(val->getType()->isPointerTy());
+      llvm::Type *vt = val->getType();
+      assert(vt->isPointerTy());
+      if (paramInfo.attr() == AttrByVal && vt->getPointerAddressSpace() != 0) {
+        // We pass a stack address, which is always in address space 0.
+        std::string castname(namegen("ascast"));
+        llvm::Type *pt = llvm::PointerType::get(vt->getPointerElementType(), 0);
+        val = builder.CreateAddrSpaceCast(val, pt, castname);
+      }
       state.llargs.push_back(val);
       continue;
     }
@@ -1177,7 +1186,6 @@
 
     llvm::Value *val = resarg->value();
 
-    BinstructionsLIRBuilder &builder = state.builder;
     if (paramInfo.abiTypes().size() == 1) {
       if (ctx == VE_lvalue) {
         // Passing single-eightbyte struct or array directly.
@@ -1243,7 +1251,8 @@
 
     // Cast the value to the struct type
     std::string tag(namegen("cast"));
-    llvm::Value *bitcast = builder.CreateBitCast(val, ptst, tag);
+    llvm::Value *bitcast =
+        builder.CreatePointerBitCastOrAddrSpaceCast(val, ptst, tag);
 
     // Load up each field
     std::string ftag0(namegen("field0"));
@@ -1566,7 +1575,8 @@
   std::set<llvm::Type *> visited;
   if (fcnPointerCompatible(dstToType, srcType, visited)) {
     std::string tag(namegen("cast"));
-    llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag);
+    llvm::Value *bitcast =
+        builder->CreatePointerBitCastOrAddrSpaceCast(srcVal, dstToType, tag);
     return bitcast;
   }