Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable opaque pointers in LLVM 16 #641

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 83 additions & 15 deletions src/tcompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,6 @@ int terra_inittarget(lua_State *L) {

TT->next_unused_id = 0;
TT->ctx = new LLVMContext();
#if LLVM_VERSION >= 150
// Hack: This is a workaround to avoid the opaque pointer
// transition, but we will need to deal with it eventually.
// FIXME: https://github.com/terralang/terra/issues/553
TT->ctx->setOpaquePointers(false);
#endif
std::string err;
const Target *TheTarget = TargetRegistry::lookupTarget(TT->Triple, err);
if (!TheTarget) {
Expand Down Expand Up @@ -1223,14 +1217,19 @@ struct CCallingConv {
assert(t1->isAggregateType());
LoadInst *l = dyn_cast<LoadInst>(src);
if ((t1->isStructTy() || (t1->isArrayTy())) && l) {
// create bitcasts of src and dest address
Value *addr_src = l->getOperand(0);
#if LLVM_VERSION < 150
// create bitcasts of src and dest address
unsigned as_src = addr_src->getType()->getPointerAddressSpace();
Type *t_src = Type::getInt8PtrTy(*CU->TT->ctx, as_src);
unsigned as_dst = addr_dst->getType()->getPointerAddressSpace();
Type *t_dst = Type::getInt8PtrTy(*CU->TT->ctx, as_dst);
Value *addr_dest = B->CreateBitCast(addr_dst, t_dst);
Value *addr_source = B->CreateBitCast(addr_src, t_src);
#else
Value *addr_dest = addr_dst;
Value *addr_source = addr_src;
#endif
uint64_t size = 0;
MaybeAlign a1;
if (t1->isStructTy()) {
Expand Down Expand Up @@ -1312,17 +1311,26 @@ struct CCallingConv {
++ai;
break;
case C_AGGREGATE_REG: {
#if LLVM_VERSION < 150
unsigned as = v->getType()->getPointerAddressSpace();
Value *dest = B->CreateBitCast(v, Ptr(p->cctype, as));
EmitEntryAggReg(B, dest, p->cctype, ai);
#else
EmitEntryAggReg(B, v, p->cctype, ai);
#endif
} break;
case C_ARRAY_REG: {
Value *scratch = CreateAlloca(B, p->cctype);
unsigned as = scratch->getType()->getPointerAddressSpace();
emitStoreAgg(B, p->cctype, &*ai, scratch);
#if LLVM_VERSION < 150
unsigned as = scratch->getType()->getPointerAddressSpace();
Value *casted = B->CreateBitCast(scratch, Ptr(p->type->type, as));
emitStoreAgg(B, p->type->type, B->CreateLoad(p->type->type, casted),
v);
#else
emitStoreAgg(B, p->type->type, B->CreateLoad(p->type->type, scratch),
v);
#endif
++ai;
} break;
}
Expand All @@ -1343,10 +1351,14 @@ struct CCallingConv {
B->CreateRetVoid();
} else if (C_AGGREGATE_REG == kind) {
Value *dest = CreateAlloca(B, info->returntype.type->type);
unsigned as = dest->getType()->getPointerAddressSpace();
emitStoreAgg(B, info->returntype.type->type, result, dest);
StructType *type = cast<StructType>(info->returntype.cctype);
#if LLVM_VERSION < 150
unsigned as = dest->getType()->getPointerAddressSpace();
Value *result = B->CreateBitCast(dest, Ptr(type, as));
#else
Value *result = dest;
#endif
Type *result_type = type;
if (info->returntype.GetNumberOfTypesInParamList() == 1) {
do {
Expand All @@ -1357,10 +1369,14 @@ struct CCallingConv {
B->CreateRet(B->CreateLoad(result_type, result));
} else if (C_ARRAY_REG == kind) {
Value *dest = CreateAlloca(B, info->returntype.type->type);
unsigned as = dest->getType()->getPointerAddressSpace();
emitStoreAgg(B, info->returntype.type->type, result, dest);
ArrayType *result_type = cast<ArrayType>(info->returntype.cctype);
#if LLVM_VERSION < 150
unsigned as = dest->getType()->getPointerAddressSpace();
Value *result = B->CreateBitCast(dest, Ptr(result_type, as));
#else
Value *result = dest;
#endif
B->CreateRet(B->CreateLoad(result_type, result));
} else {
assert(!"unhandled return value");
Expand Down Expand Up @@ -1408,17 +1424,25 @@ struct CCallingConv {
} break;
case C_AGGREGATE_REG: {
Value *scratch = CreateAlloca(B, a->type->type);
unsigned as = scratch->getType()->getPointerAddressSpace();
emitStoreAgg(B, a->type->type, actual, scratch);
#if LLVM_VERSION < 150
unsigned as = scratch->getType()->getPointerAddressSpace();
Value *casted = B->CreateBitCast(scratch, Ptr(a->cctype, as));
EmitCallAggReg(B, casted, a->cctype, arguments);
#else
EmitCallAggReg(B, scratch, a->cctype, arguments);
#endif
} break;
case C_ARRAY_REG: {
Value *scratch = CreateAlloca(B, a->type->type);
unsigned as = scratch->getType()->getPointerAddressSpace();
emitStoreAgg(B, a->type->type, actual, scratch);
#if LLVM_VERSION < 150
unsigned as = scratch->getType()->getPointerAddressSpace();
Value *casted = B->CreateBitCast(scratch, Ptr(a->cctype, as));
EmitCallAggReg(B, casted, a->cctype, arguments);
#else
EmitCallAggReg(B, scratch, a->cctype, arguments);
#endif
} break;
default: {
assert(!"unhandled argument kind");
Expand All @@ -1427,9 +1451,13 @@ struct CCallingConv {
}

// emit call
#if LLVM_VERSION < 150
// function pointers are stored as &int8 to avoid calling convension issues
// cast it back to the real pointer type right before calling it
callee = B->CreateBitCast(callee, Ptr(info.fntype));
#else
assert(callee->getType()->isPointerTy());
#endif
CallInst *call = B->CreateCall(info.fntype, callee, arguments);
// annotate call with byval and sret
AttributeFnOrCall(call, &info);
Expand All @@ -1444,9 +1472,13 @@ struct CCallingConv {
aggregate = arguments[0];
} else if (C_AGGREGATE_REG == info.returntype.kind) {
aggregate = CreateAlloca(B, info.returntype.type->type);
unsigned as = aggregate->getType()->getPointerAddressSpace();
StructType *type = cast<StructType>(info.returntype.cctype);
#if LLVM_VERSION < 150
unsigned as = aggregate->getType()->getPointerAddressSpace();
Value *casted = B->CreateBitCast(aggregate, Ptr(type, as));
#else
Value *casted = aggregate;
#endif
if (info.returntype.GetNumberOfTypesInParamList() == 1) {
do {
casted = CreateConstGEP2_32(B, casted, type, 0, 0);
Expand All @@ -1456,10 +1488,14 @@ struct CCallingConv {
B->CreateStore(call, casted);
} else if (C_ARRAY_REG == info.returntype.kind) {
aggregate = CreateAlloca(B, info.returntype.type->type);
unsigned as = aggregate->getType()->getPointerAddressSpace();
ArrayType *type = cast<ArrayType>(info.returntype.cctype);
#if LLVM_VERSION < 150
unsigned as = aggregate->getType()->getPointerAddressSpace();
Value *casted = B->CreateBitCast(aggregate, Ptr(type, as));
emitStoreAgg(B, type, call, casted);
#else
emitStoreAgg(B, type, call, aggregate);
#endif
} else {
assert(!"unhandled argument kind");
}
Expand Down Expand Up @@ -2347,13 +2383,17 @@ struct FunctionEmitter {
result = B->CreateInsertElement(result, v, ConstantInt::get(integerType, i));
return result;
}
#if LLVM_VERSION < 150
bool isPointerToFunction(Type *t) {
return t->isPointerTy() && t->getPointerElementType()->isFunctionTy();
}
#endif
Value *emitStructSelect(Obj *structType, Value *structPtr, int index,
Obj *entryType) {
assert(structPtr->getType()->isPointerTy());
#if LLVM_VERSION < 150
assert(structPtr->getType()->getPointerElementType()->isStructTy());
#endif
Ty->EnsureTypeIsComplete(structType);

Obj layout;
Expand All @@ -2377,7 +2417,11 @@ struct FunctionEmitter {
// in all cases we simply bitcast cast the resulting pointer to the expected type
entry.obj("type", entryType);
TType *entryTType = getType(entryType);
if (entry.boolean("inunion") || isPointerToFunction(entryTType->type)) {
if (entry.boolean("inunion")
#if LLVM_VERSION < 150
|| isPointerToFunction(entryTType->type)
#endif
) {
unsigned as = addr->getType()->getPointerAddressSpace();
Type *resultType = PointerType::get(entryTType->type, as);
addr = B->CreateBitCast(addr, resultType);
Expand All @@ -2390,6 +2434,7 @@ struct FunctionEmitter {
LoadInst *l = dyn_cast<LoadInst>(&*value);
Type *t1 = value->getType();
if ((t1->isStructTy() || t1->isArrayTy()) && l) {
#if LLVM_VERSION < 150
unsigned as_dst = addr->getType()->getPointerAddressSpace();
// create bitcasts of src and dest address
Type *t_dst = Type::getInt8PtrTy(*CU->TT->ctx, as_dst);
Expand All @@ -2400,6 +2445,10 @@ struct FunctionEmitter {
unsigned as_src = addr_src->getType()->getPointerAddressSpace();
Type *t_src = Type::getInt8PtrTy(*CU->TT->ctx, as_src);
addr_src = B->CreateBitCast(addr_src, t_src);
#else
Value *addr_dst = addr;
Value *addr_src = l->getOperand(0);
#endif
uint64_t size = 0;
MaybeAlign a1;
if (t1->isStructTy()) {
Expand Down Expand Up @@ -2480,18 +2529,26 @@ struct FunctionEmitter {
if (T_globalvariable == global.kind("kind")) {
GlobalVariable *gv =
EmitGlobalVariable(CU, &global, exp->string("name"));
#if LLVM_VERSION < 150
// Clang (as of LLVM 7) changes the types of certain globals
// (like arrays). Change the type back to what we expect
// here so we don't cause issues downstream in the compiler.
return B->CreateBitCast(
gv,
PointerType::get(typeOfValue(exp)->type,
gv->getType()->getPointerAddressSpace()));
#else
return gv;
#endif
} else {
#if LLVM_VERSION < 150
// functions are represented with &int8 pointers to avoid
// calling convension issues, so cast the literal to this type now
return B->CreateBitCast(EmitFunction(CU, &global, fstate),
typeOfValue(exp)->type);
#else
return EmitFunction(CU, &global, fstate);
#endif
}
} break;
case T_allocvar: {
Expand Down Expand Up @@ -2619,7 +2676,11 @@ struct FunctionEmitter {
lua_pop(L, 1);
mapSymbol(CU->symbols, &stringvalue, str);
}
#if LLVM_VERSION < 150
return B->CreateBitCast(str, pt);
#else
return str;
#endif
} else {
assert(!"NYI - pointer literal");
}
Expand Down Expand Up @@ -2709,7 +2770,11 @@ struct FunctionEmitter {
Value *v = emitExp(&a);
if (fromT->type->isPointerTy()) {
if (toT->type->isPointerTy()) {
#if LLVM_VERSION < 150
return B->CreateBitCast(v, toT->type);
#else
return v;
#endif
} else {
assert(toT->type->isIntegerTy());
return B->CreatePtrToInt(v, toT->type);
Expand Down Expand Up @@ -3614,7 +3679,10 @@ static int terra_deletefunction(lua_State *L) {
VERBOSE_ONLY(CU->T) {
printf("... uses not empty, removing body but keeping declaration.\n");
}
#if LLVM_VERSION < 150
// FIXME: LLVM crashes if we attempt to delete with opaque pointers enabled
func->deleteBody();
#endif
VERBOSE_ONLY(CU->T) { printf("... finish delete.\n"); }
fstate->func = NULL;
freecompilationunit(CU);
Expand Down
6 changes: 5 additions & 1 deletion tests/dgemm3.t
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ end

local function isinteger(x) return math.floor(x) == x end

llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
if terralib.llvm_version < 160 then
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
else
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0",{&opaque,int,int,int} -> {})
end

local function alignedload(addr)
return `terralib.attrload(addr, { align = 8 })
Expand Down
6 changes: 5 additions & 1 deletion tests/dgemmpaper.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ function symmat(typ,name,I,...)
end
return r
end
prefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
if terralib.llvm_version < 160 then
prefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
else
prefetch = terralib.intrinsic("llvm.prefetch.p0",{&opaque,int,int,int} -> {})
end

function genkernel(NB, RM, RN, V,alpha)
local VT = vector(double,V)
Expand Down
6 changes: 5 additions & 1 deletion tests/diffuse.t
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ terra diffuse(output : &float, N : int, M : int, stride : int, x : &float, x0 :

end

llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
if terralib.llvm_version < 160 then
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
else
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0",{&opaque,int,int,int} -> {})
end

terra diffuse2(output : &float, N : int, M : int, stride : int, x : &float, x0 : &float, a : float,xi : &float)
var invD = 1.f / (1 + 4.f*a)
Expand Down
6 changes: 5 additions & 1 deletion tests/gemm.t
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ end

local function isinteger(x) return math.floor(x) == x end

llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
if terralib.llvm_version < 160 then
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
else
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0",{&opaque,int,int,int} -> {})
end
local function unalignedload(addr)
return `terralib.attrload(addr, { align = alignment })
end
Expand Down
6 changes: 5 additions & 1 deletion tests/sgemm3.t
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ function symmat(typ,name,I,...)
end


llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
if terralib.llvm_version < 160 then
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0i8",{&opaque,int,int,int} -> {})
else
llvmprefetch = terralib.intrinsic("llvm.prefetch.p0",{&opaque,int,int,int} -> {})
end



Expand Down
Loading