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;
}