From 3263a5749945a4c41bba3505d9ff822c7e5dffcf Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Fri, 25 Aug 2023 11:28:21 -0700 Subject: [PATCH 1/5] Enable opaque pointers in LLVM 16. --- src/tcompiler.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index abf13ac6..ac789b98 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -270,7 +270,7 @@ int terra_inittarget(lua_State *L) { TT->next_unused_id = 0; TT->ctx = new LLVMContext(); -#if LLVM_VERSION >= 150 +#if LLVM_VERSION >= 150 && LLVM_VERSION < 160 // 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 @@ -2348,12 +2348,18 @@ struct FunctionEmitter { return result; } bool isPointerToFunction(Type *t) { - return t->isPointerTy() && t->getPointerElementType()->isFunctionTy(); + return t->isPointerTy() +#if LLVM_VERSION < 160 + && t->getPointerElementType()->isFunctionTy() +#endif +; } Value *emitStructSelect(Obj *structType, Value *structPtr, int index, Obj *entryType) { assert(structPtr->getType()->isPointerTy()); +#if LLVM_VERSION < 160 assert(structPtr->getType()->getPointerElementType()->isStructTy()); +#endif Ty->EnsureTypeIsComplete(structType); Obj layout; From 93eeef0777042ab89145fcddfe13cd4241eba9c7 Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Fri, 25 Aug 2023 11:33:50 -0700 Subject: [PATCH 2/5] Format. --- src/tcompiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index ac789b98..e071ee07 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -2350,9 +2350,9 @@ struct FunctionEmitter { bool isPointerToFunction(Type *t) { return t->isPointerTy() #if LLVM_VERSION < 160 - && t->getPointerElementType()->isFunctionTy() + && t->getPointerElementType()->isFunctionTy() #endif -; + ; } Value *emitStructSelect(Obj *structType, Value *structPtr, int index, Obj *entryType) { From ce659255c4e500d5e51f10b925c316f71e982d9c Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Fri, 25 Aug 2023 13:04:31 -0700 Subject: [PATCH 3/5] Fixes for opaque pointers. --- src/tcompiler.cpp | 91 +++++++++++++++++++++++++++++++++++++++------- tests/dgemm3.t | 6 ++- tests/dgemmpaper.t | 6 ++- tests/diffuse.t | 6 ++- tests/gemm.t | 6 ++- tests/sgemm3.t | 6 ++- 6 files changed, 102 insertions(+), 19 deletions(-) diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index e071ee07..51492e4f 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -1223,14 +1223,19 @@ struct CCallingConv { assert(t1->isAggregateType()); LoadInst *l = dyn_cast(src); if ((t1->isStructTy() || (t1->isArrayTy())) && l) { - // create bitcasts of src and dest address Value *addr_src = l->getOperand(0); +#if LLVM_VERSION < 160 + // 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()) { @@ -1312,17 +1317,26 @@ struct CCallingConv { ++ai; break; case C_AGGREGATE_REG: { +#if LLVM_VERSION < 160 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 < 160 + 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; } @@ -1343,10 +1357,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(info->returntype.cctype); +#if LLVM_VERSION < 160 + 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 { @@ -1357,10 +1375,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(info->returntype.cctype); +#if LLVM_VERSION < 160 + 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"); @@ -1408,17 +1430,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 < 160 + 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 < 160 + 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"); @@ -1427,9 +1457,11 @@ struct CCallingConv { } // emit call +#if LLVM_VERSION < 160 // 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)); +#endif CallInst *call = B->CreateCall(info.fntype, callee, arguments); // annotate call with byval and sret AttributeFnOrCall(call, &info); @@ -1444,9 +1476,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(info.returntype.cctype); +#if LLVM_VERSION < 160 + 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); @@ -1456,10 +1492,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(info.returntype.cctype); +#if LLVM_VERSION < 160 + 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"); } @@ -2347,13 +2387,11 @@ struct FunctionEmitter { result = B->CreateInsertElement(result, v, ConstantInt::get(integerType, i)); return result; } - bool isPointerToFunction(Type *t) { - return t->isPointerTy() #if LLVM_VERSION < 160 - && t->getPointerElementType()->isFunctionTy() -#endif - ; + 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()); @@ -2383,7 +2421,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 < 160 + || isPointerToFunction(entryTType->type) +#endif + ) { unsigned as = addr->getType()->getPointerAddressSpace(); Type *resultType = PointerType::get(entryTType->type, as); addr = B->CreateBitCast(addr, resultType); @@ -2396,6 +2438,7 @@ struct FunctionEmitter { LoadInst *l = dyn_cast(&*value); Type *t1 = value->getType(); if ((t1->isStructTy() || t1->isArrayTy()) && l) { +#if LLVM_VERSION < 160 unsigned as_dst = addr->getType()->getPointerAddressSpace(); // create bitcasts of src and dest address Type *t_dst = Type::getInt8PtrTy(*CU->TT->ctx, as_dst); @@ -2406,6 +2449,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()) { @@ -2486,6 +2533,7 @@ struct FunctionEmitter { if (T_globalvariable == global.kind("kind")) { GlobalVariable *gv = EmitGlobalVariable(CU, &global, exp->string("name")); +#if LLVM_VERSION < 160 // 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. @@ -2493,11 +2541,18 @@ struct FunctionEmitter { gv, PointerType::get(typeOfValue(exp)->type, gv->getType()->getPointerAddressSpace())); +#else + return gv; +#endif } else { +#if LLVM_VERSION < 160 // 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: { @@ -2625,7 +2680,11 @@ struct FunctionEmitter { lua_pop(L, 1); mapSymbol(CU->symbols, &stringvalue, str); } +#if LLVM_VERSION < 160 return B->CreateBitCast(str, pt); +#else + return str; +#endif } else { assert(!"NYI - pointer literal"); } @@ -2715,7 +2774,11 @@ struct FunctionEmitter { Value *v = emitExp(&a); if (fromT->type->isPointerTy()) { if (toT->type->isPointerTy()) { +#if LLVM_VERSION < 160 return B->CreateBitCast(v, toT->type); +#else + return v; +#endif } else { assert(toT->type->isIntegerTy()); return B->CreatePtrToInt(v, toT->type); diff --git a/tests/dgemm3.t b/tests/dgemm3.t index 1260cf73..8645b553 100644 --- a/tests/dgemm3.t +++ b/tests/dgemm3.t @@ -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 }) diff --git a/tests/dgemmpaper.t b/tests/dgemmpaper.t index d4156930..0abb1e94 100644 --- a/tests/dgemmpaper.t +++ b/tests/dgemmpaper.t @@ -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) diff --git a/tests/diffuse.t b/tests/diffuse.t index 169af608..71d1d9cc 100644 --- a/tests/diffuse.t +++ b/tests/diffuse.t @@ -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) diff --git a/tests/gemm.t b/tests/gemm.t index 19c6497a..c8e696c7 100644 --- a/tests/gemm.t +++ b/tests/gemm.t @@ -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 diff --git a/tests/sgemm3.t b/tests/sgemm3.t index 7af73a5c..aa601669 100644 --- a/tests/sgemm3.t +++ b/tests/sgemm3.t @@ -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 From 55b83bb8164973789082a7418f304b702b003bd5 Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Fri, 25 Aug 2023 16:46:00 -0700 Subject: [PATCH 4/5] Enable opaque pointers in LLVM 15. --- src/tcompiler.cpp | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index 51492e4f..4927231d 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -270,12 +270,6 @@ int terra_inittarget(lua_State *L) { TT->next_unused_id = 0; TT->ctx = new LLVMContext(); -#if LLVM_VERSION >= 150 && LLVM_VERSION < 160 - // 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) { @@ -1224,7 +1218,7 @@ struct CCallingConv { LoadInst *l = dyn_cast(src); if ((t1->isStructTy() || (t1->isArrayTy())) && l) { Value *addr_src = l->getOperand(0); -#if LLVM_VERSION < 160 +#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); @@ -1317,7 +1311,7 @@ struct CCallingConv { ++ai; break; case C_AGGREGATE_REG: { -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = v->getType()->getPointerAddressSpace(); Value *dest = B->CreateBitCast(v, Ptr(p->cctype, as)); EmitEntryAggReg(B, dest, p->cctype, ai); @@ -1328,7 +1322,7 @@ struct CCallingConv { case C_ARRAY_REG: { Value *scratch = CreateAlloca(B, p->cctype); emitStoreAgg(B, p->cctype, &*ai, scratch); -#if LLVM_VERSION < 160 +#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), @@ -1359,7 +1353,7 @@ struct CCallingConv { Value *dest = CreateAlloca(B, info->returntype.type->type); emitStoreAgg(B, info->returntype.type->type, result, dest); StructType *type = cast(info->returntype.cctype); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = dest->getType()->getPointerAddressSpace(); Value *result = B->CreateBitCast(dest, Ptr(type, as)); #else @@ -1377,7 +1371,7 @@ struct CCallingConv { Value *dest = CreateAlloca(B, info->returntype.type->type); emitStoreAgg(B, info->returntype.type->type, result, dest); ArrayType *result_type = cast(info->returntype.cctype); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = dest->getType()->getPointerAddressSpace(); Value *result = B->CreateBitCast(dest, Ptr(result_type, as)); #else @@ -1431,7 +1425,7 @@ struct CCallingConv { case C_AGGREGATE_REG: { Value *scratch = CreateAlloca(B, a->type->type); emitStoreAgg(B, a->type->type, actual, scratch); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = scratch->getType()->getPointerAddressSpace(); Value *casted = B->CreateBitCast(scratch, Ptr(a->cctype, as)); EmitCallAggReg(B, casted, a->cctype, arguments); @@ -1442,7 +1436,7 @@ struct CCallingConv { case C_ARRAY_REG: { Value *scratch = CreateAlloca(B, a->type->type); emitStoreAgg(B, a->type->type, actual, scratch); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = scratch->getType()->getPointerAddressSpace(); Value *casted = B->CreateBitCast(scratch, Ptr(a->cctype, as)); EmitCallAggReg(B, casted, a->cctype, arguments); @@ -1457,10 +1451,12 @@ struct CCallingConv { } // emit call -#if LLVM_VERSION < 160 +#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 @@ -1477,7 +1473,7 @@ struct CCallingConv { } else if (C_AGGREGATE_REG == info.returntype.kind) { aggregate = CreateAlloca(B, info.returntype.type->type); StructType *type = cast(info.returntype.cctype); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = aggregate->getType()->getPointerAddressSpace(); Value *casted = B->CreateBitCast(aggregate, Ptr(type, as)); #else @@ -1493,7 +1489,7 @@ struct CCallingConv { } else if (C_ARRAY_REG == info.returntype.kind) { aggregate = CreateAlloca(B, info.returntype.type->type); ArrayType *type = cast(info.returntype.cctype); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 unsigned as = aggregate->getType()->getPointerAddressSpace(); Value *casted = B->CreateBitCast(aggregate, Ptr(type, as)); emitStoreAgg(B, type, call, casted); @@ -2387,7 +2383,7 @@ struct FunctionEmitter { result = B->CreateInsertElement(result, v, ConstantInt::get(integerType, i)); return result; } -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 bool isPointerToFunction(Type *t) { return t->isPointerTy() && t->getPointerElementType()->isFunctionTy(); } @@ -2395,7 +2391,7 @@ struct FunctionEmitter { Value *emitStructSelect(Obj *structType, Value *structPtr, int index, Obj *entryType) { assert(structPtr->getType()->isPointerTy()); -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 assert(structPtr->getType()->getPointerElementType()->isStructTy()); #endif Ty->EnsureTypeIsComplete(structType); @@ -2422,7 +2418,7 @@ struct FunctionEmitter { entry.obj("type", entryType); TType *entryTType = getType(entryType); if (entry.boolean("inunion") -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 || isPointerToFunction(entryTType->type) #endif ) { @@ -2438,7 +2434,7 @@ struct FunctionEmitter { LoadInst *l = dyn_cast(&*value); Type *t1 = value->getType(); if ((t1->isStructTy() || t1->isArrayTy()) && l) { -#if LLVM_VERSION < 160 +#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); @@ -2533,7 +2529,7 @@ struct FunctionEmitter { if (T_globalvariable == global.kind("kind")) { GlobalVariable *gv = EmitGlobalVariable(CU, &global, exp->string("name")); -#if LLVM_VERSION < 160 +#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. @@ -2545,7 +2541,7 @@ struct FunctionEmitter { return gv; #endif } else { -#if LLVM_VERSION < 160 +#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), @@ -2680,7 +2676,7 @@ struct FunctionEmitter { lua_pop(L, 1); mapSymbol(CU->symbols, &stringvalue, str); } -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 return B->CreateBitCast(str, pt); #else return str; @@ -2774,7 +2770,7 @@ struct FunctionEmitter { Value *v = emitExp(&a); if (fromT->type->isPointerTy()) { if (toT->type->isPointerTy()) { -#if LLVM_VERSION < 160 +#if LLVM_VERSION < 150 return B->CreateBitCast(v, toT->type); #else return v; From 2227d784a32f9146b813bd4ba0431f78fcfe8606 Mon Sep 17 00:00:00 2001 From: Elliott Slaughter Date: Fri, 25 Aug 2023 16:59:15 -0700 Subject: [PATCH 5/5] Workaround for free crash in LLVM. --- src/tcompiler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index 4927231d..12e8bd79 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -3679,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);