Date: Saturday, January 7, 2023 @ 14:01:32 Author: arojas Revision: 1381673
upgpkg: julia 2:1.8.4-2: Rebuld with llvm-14 Added: julia/trunk/0db596e6.patch julia/trunk/190565c2.patch julia/trunk/23f39f83.patch julia/trunk/2ef4aba7.patch julia/trunk/3423639d.patch julia/trunk/68adc00e.patch julia/trunk/700c69b1.patch julia/trunk/7b2d1e08.patch julia/trunk/LLVM-14.patch julia/trunk/julia-llvm-15.patch julia/trunk/julia-mpfr-4.2.patch Modified: julia/trunk/PKGBUILD julia/trunk/julia-hardcoded-libs.patch Deleted: julia/trunk/julia-llvm-14.patch ----------------------------+ 0db596e6.patch | 285 ++++++++++++++++++++++++++ 190565c2.patch | 91 ++++++++ 23f39f83.patch | 460 +++++++++++++++++++++++++++++++++++++++++++ 2ef4aba7.patch | 233 +++++++++++++++++++++ 3423639d.patch | 21 + 68adc00e.patch | 55 +++++ 700c69b1.patch | 22 ++ 7b2d1e08.patch | 264 ++++++++++++++++++++++++ LLVM-14.patch | 13 + PKGBUILD | 53 ++++ julia-hardcoded-libs.patch | 2 julia-llvm-14.patch | 14 - julia-llvm-15.patch | 31 ++ julia-mpfr-4.2.patch | 22 ++ 14 files changed, 1541 insertions(+), 25 deletions(-) Added: 0db596e6.patch =================================================================== --- 0db596e6.patch (rev 0) +++ 0db596e6.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,285 @@ +From 0db596e6f5e785b51e6810baa035f9ef9f4094e6 Mon Sep 17 00:00:00 2001 +From: pchintalapudi <[email protected]> +Date: Tue, 22 Feb 2022 22:12:06 -0500 +Subject: [PATCH] Remove uses of PointerType::getElementType for opaque + pointers (#44310) + +Co-authored-by: Jameson Nash <[email protected]> +--- + src/ccall.cpp | 8 ++++++-- + src/cgutils.cpp | 13 +++++++------ + src/codegen_shared.h | 4 +--- + src/llvm-alloc-opt.cpp | 6 ++---- + src/llvm-propagate-addrspaces.cpp | 14 +++++++------- + src/llvm-remove-addrspaces.cpp | 25 +++++++++++++++++-------- + src/llvmcalltest.cpp | 2 +- + 7 files changed, 41 insertions(+), 31 deletions(-) + +diff --git a/src/ccall.cpp b/src/ccall.cpp +index 5f260d9178ff..1902aed9f794 100644 +--- a/src/ccall.cpp ++++ b/src/ccall.cpp +@@ -1879,6 +1879,8 @@ jl_cgval_t function_sig_t::emit_a_ccall( + } + + Value *result = NULL; ++ //This is only needed if !retboxed && srt && !jlretboxed ++ Type *sretty = nullptr; + // First, if the ABI requires us to provide the space for the return + // argument, allocate the box and store that as the first argument type + bool sretboxed = false; +@@ -1886,6 +1888,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( + assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid"); + if (jl_is_pointerfree(rt)) { + result = emit_static_alloca(ctx, lrt); ++ sretty = lrt; + argvals[0] = ctx.builder.CreateBitCast(result, fargt_sig.at(0)); + } + else { +@@ -1895,6 +1898,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( + assert(jl_datatype_size(rt) > 0 && "sret shouldn't be a singleton instance"); + result = emit_allocobj(ctx, jl_datatype_size(rt), + literal_pointer_val(ctx, (jl_value_t*)rt)); ++ sretty = ctx.types().T_jlvalue; + sretboxed = true; + gc_uses.push_back(result); + argvals[0] = ctx.builder.CreateBitCast(emit_pointer_from_objref(ctx, result), fargt_sig.at(0)); +@@ -1983,7 +1987,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( + if (cc != CallingConv::C) + ((CallInst*)ret)->setCallingConv(cc); + if (!sret) +- result = ret; ++ result = ret; // no need to update sretty here because we know !sret + if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall + ctx.f->addFnAttr(Attribute::StackProtectReq); + } +@@ -2008,7 +2012,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( + // something alloca'd above is SSA + if (static_rt) + return mark_julia_slot(result, rt, NULL, ctx.tbaa(), ctx.tbaa().tbaa_stack); +- result = ctx.builder.CreateLoad(cast<PointerType>(result->getType())->getElementType(), result); ++ result = ctx.builder.CreateLoad(sretty, result); + } + } + else { +diff --git a/src/cgutils.cpp b/src/cgutils.cpp +index e04abe8c06e0..ba692e41199f 100644 +--- a/src/cgutils.cpp ++++ b/src/cgutils.cpp +@@ -24,7 +24,7 @@ static Value *decay_derived(jl_codectx_t &ctx, Value *V) + if (cast<PointerType>(T)->getAddressSpace() == AddressSpace::Derived) + return V; + // Once llvm deletes pointer element types, we won't need it here any more either. +- Type *NewT = PointerType::get(cast<PointerType>(T)->getElementType(), AddressSpace::Derived); ++ Type *NewT = PointerType::getWithSamePointeeType(cast<PointerType>(T), AddressSpace::Derived); + return ctx.builder.CreateAddrSpaceCast(V, NewT); + } + +@@ -34,7 +34,7 @@ static Value *maybe_decay_tracked(jl_codectx_t &ctx, Value *V) + Type *T = V->getType(); + if (cast<PointerType>(T)->getAddressSpace() != AddressSpace::Tracked) + return V; +- Type *NewT = PointerType::get(cast<PointerType>(T)->getElementType(), AddressSpace::Derived); ++ Type *NewT = PointerType::getWithSamePointeeType(cast<PointerType>(T), AddressSpace::Derived); + return ctx.builder.CreateAddrSpaceCast(V, NewT); + } + +@@ -418,9 +418,7 @@ static Value *emit_bitcast(jl_codectx_t &ctx, Value *v, Type *jl_value) + if (isa<PointerType>(jl_value) && + v->getType()->getPointerAddressSpace() != jl_value->getPointerAddressSpace()) { + // Cast to the proper address space +- Type *jl_value_addr = +- PointerType::get(cast<PointerType>(jl_value)->getElementType(), +- v->getType()->getPointerAddressSpace()); ++ Type *jl_value_addr = PointerType::getWithSamePointeeType(cast<PointerType>(jl_value), v->getType()->getPointerAddressSpace()); + return ctx.builder.CreateBitCast(v, jl_value_addr); + } + else { +@@ -1943,8 +1941,10 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va + // machine size vectors this should be enough. + const DataLayout &DL = jl_Module->getDataLayout(); + auto srcty = cast<PointerType>(src->getType()); ++ //TODO unsafe nonopaque pointer + auto srcel = srcty->getElementType(); + auto dstty = cast<PointerType>(dst->getType()); ++ //TODO unsafe nonopaque pointer + auto dstel = dstty->getElementType(); + if (srcel->isArrayTy() && srcel->getArrayNumElements() == 1) { + src = ctx.builder.CreateConstInBoundsGEP2_32(srcel, src, 0, 0); +@@ -2806,7 +2806,7 @@ static Value *load_i8box(jl_codectx_t &ctx, Value *v, jl_datatype_t *ty) + auto jvar = ty == jl_int8_type ? jlboxed_int8_cache : jlboxed_uint8_cache; + GlobalVariable *gv = prepare_global_in(jl_Module, jvar); + Value *idx[] = {ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0), ctx.builder.CreateZExt(v, getInt32Ty(ctx.builder.getContext()))}; +- auto slot = ctx.builder.CreateInBoundsGEP(gv->getType()->getElementType(), gv, idx); ++ auto slot = ctx.builder.CreateInBoundsGEP(gv->getValueType(), gv, idx); + return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, slot, Align(sizeof(void*))), false, + (jl_value_t*)ty)); +@@ -3197,6 +3197,7 @@ static void emit_cpointercheck(jl_codectx_t &ctx, const jl_cgval_t &x, const std + } + + // allocation for known size object ++// returns a prjlvalue + static Value *emit_allocobj(jl_codectx_t &ctx, size_t static_size, Value *jt) + { + Value *current_task = get_current_task(ctx); +diff --git a/src/codegen_shared.h b/src/codegen_shared.h +index 181cf51cffc0..f32d81dadbba 100644 +--- a/src/codegen_shared.h ++++ b/src/codegen_shared.h +@@ -147,9 +147,7 @@ static inline llvm::Value *emit_bitcast_with_builder(llvm::IRBuilder<> &builder, + if (isa<PointerType>(jl_value) && + v->getType()->getPointerAddressSpace() != jl_value->getPointerAddressSpace()) { + // Cast to the proper address space +- Type *jl_value_addr = +- PointerType::get(cast<PointerType>(jl_value)->getElementType(), +- v->getType()->getPointerAddressSpace()); ++ Type *jl_value_addr = PointerType::getWithSamePointeeType(cast<PointerType>(jl_value), v->getType()->getPointerAddressSpace()); + return builder.CreateBitCast(v, jl_value_addr); + } + else { +diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp +index 4397992d79f4..fa02ecc8a56b 100644 +--- a/src/llvm-alloc-opt.cpp ++++ b/src/llvm-alloc-opt.cpp +@@ -658,8 +658,7 @@ void Optimizer::moveToStack(CallInst *orig_inst, size_t sz, bool has_ref) + user->replaceUsesOfWith(orig_i, replace); + } + else if (isa<AddrSpaceCastInst>(user) || isa<BitCastInst>(user)) { +- auto cast_t = PointerType::get(cast<PointerType>(user->getType())->getElementType(), +- 0); ++ auto cast_t = PointerType::getWithSamePointeeType(cast<PointerType>(user->getType()), AddressSpace::Generic); + auto replace_i = new_i; + Type *new_t = new_i->getType(); + if (cast_t != new_t) { +@@ -953,8 +952,7 @@ void Optimizer::splitOnStack(CallInst *orig_inst) + store_ty = pass.T_pjlvalue; + } + else { +- store_ty = cast<PointerType>(pass.T_pjlvalue)->getElementType() +- ->getPointerTo(cast<PointerType>(store_ty)->getAddressSpace()); ++ store_ty = PointerType::getWithSamePointeeType(pass.T_pjlvalue, cast<PointerType>(store_ty)->getAddressSpace()); + store_val = builder.CreateBitCast(store_val, store_ty); + } + if (cast<PointerType>(store_ty)->getAddressSpace() != AddressSpace::Tracked) +diff --git a/src/llvm-propagate-addrspaces.cpp b/src/llvm-propagate-addrspaces.cpp +index d28cd09f8176..8da0e108c94d 100644 +--- a/src/llvm-propagate-addrspaces.cpp ++++ b/src/llvm-propagate-addrspaces.cpp +@@ -48,7 +48,7 @@ struct PropagateJuliaAddrspacesVisitor : public InstVisitor<PropagateJuliaAddrsp + + public: + bool runOnFunction(Function &F) override; +- Value *LiftPointer(Value *V, Type *LocTy = nullptr, Instruction *InsertPt=nullptr); ++ Value *LiftPointer(Value *V, Instruction *InsertPt=nullptr); + void visitMemop(Instruction &I, Type *T, unsigned OpIndex); + void visitLoadInst(LoadInst &LI); + void visitStoreInst(StoreInst &SI); +@@ -82,7 +82,7 @@ void PropagateJuliaAddrspacesVisitor::PoisonValues(std::vector<Value *> &Worklis + } + } + +-Value *PropagateJuliaAddrspaces::LiftPointer(Value *V, Type *LocTy, Instruction *InsertPt) { ++Value *PropagateJuliaAddrspaces::LiftPointer(Value *V, Instruction *InsertPt) { + SmallVector<Value *, 4> Stack; + std::vector<Value *> Worklist; + std::set<Value *> LocalVisited; +@@ -165,7 +165,7 @@ Value *PropagateJuliaAddrspacesVisitor::LiftPointer(Value *V, Type *LocTy, Instr + Instruction *InstV = cast<Instruction>(V); + Instruction *NewV = InstV->clone(); + ToInsert.push_back(std::make_pair(NewV, InstV)); +- Type *NewRetTy = cast<PointerType>(InstV->getType())->getElementType()->getPointerTo(0); ++ Type *NewRetTy = PointerType::getWithSamePointeeType(cast<PointerType>(InstV->getType()), AddressSpace::Generic); + NewV->mutateType(NewRetTy); + LiftingMap[InstV] = NewV; + ToRevisit.push_back(NewV); +@@ -173,7 +173,7 @@ Value *PropagateJuliaAddrspacesVisitor::LiftPointer(Value *V, Type *LocTy, Instr + } + + auto CollapseCastsAndLift = [&](Value *CurrentV, Instruction *InsertPt) -> Value * { +- PointerType *TargetType = cast<PointerType>(CurrentV->getType())->getElementType()->getPointerTo(0); ++ PointerType *TargetType = PointerType::getWithSamePointeeType(cast<PointerType>(CurrentV->getType()), AddressSpace::Generic); + while (!LiftingMap.count(CurrentV)) { + if (isa<BitCastInst>(CurrentV)) + CurrentV = cast<BitCastInst>(CurrentV)->getOperand(0); +@@ -222,7 +222,7 @@ void PropagateJuliaAddrspacesVisitor::visitMemop(Instruction &I, Type *T, unsign + unsigned AS = Original->getType()->getPointerAddressSpace(); + if (!isSpecialAS(AS)) + return; +- Value *Replacement = LiftPointer(Original, T, &I); ++ Value *Replacement = LiftPointer(Original, &I); + if (!Replacement) + return; + I.setOperand(OpIndex, Replacement); +@@ -264,13 +264,13 @@ void PropagateJuliaAddrspacesVisitor::visitMemTransferInst(MemTransferInst &MTI) + return; + Value *Dest = MTI.getRawDest(); + if (isSpecialAS(DestAS)) { +- Value *Replacement = LiftPointer(Dest, cast<PointerType>(Dest->getType())->getElementType(), &MTI); ++ Value *Replacement = LiftPointer(Dest, &MTI); + if (Replacement) + Dest = Replacement; + } + Value *Src = MTI.getRawSource(); + if (isSpecialAS(SrcAS)) { +- Value *Replacement = LiftPointer(Src, cast<PointerType>(Src->getType())->getElementType(), &MTI); ++ Value *Replacement = LiftPointer(Src, &MTI); + if (Replacement) + Src = Replacement; + } +diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp +index ba45ae190e03..610268cfa983 100644 +--- a/src/llvm-remove-addrspaces.cpp ++++ b/src/llvm-remove-addrspaces.cpp +@@ -44,10 +44,17 @@ class AddrspaceRemoveTypeRemapper : public ValueMapTypeRemapper { + return DstTy; + + DstTy = SrcTy; +- if (auto Ty = dyn_cast<PointerType>(SrcTy)) +- DstTy = PointerType::get( +- remapType(Ty->getElementType()), +- ASRemapper(Ty->getAddressSpace())); ++ if (auto Ty = dyn_cast<PointerType>(SrcTy)) { ++ if (Ty->isOpaque()) { ++ DstTy = PointerType::get(Ty->getContext(), ASRemapper(Ty->getAddressSpace())); ++ } ++ else { ++ //Remove once opaque pointer transition is complete ++ DstTy = PointerType::get( ++ remapType(Ty->getElementType()), ++ ASRemapper(Ty->getAddressSpace())); ++ } ++ } + else if (auto Ty = dyn_cast<FunctionType>(SrcTy)) { + SmallVector<Type *, 4> Params; + for (unsigned Index = 0; Index < Ty->getNumParams(); ++Index) +@@ -152,10 +159,12 @@ class AddrspaceRemoveValueMaterializer : public ValueMaterializer { + // GEP const exprs need to know the type of the source. + // asserts remapType(typeof arg0) == typeof mapValue(arg0). + Constant *Src = CE->getOperand(0); +- Type *SrcTy = remapType( +- cast<PointerType>(Src->getType()->getScalarType()) +- ->getElementType()); +- DstV = CE->getWithOperands(Ops, Ty, false, SrcTy); ++ auto ptrty = cast<PointerType>(Src->getType()->getScalarType()); ++ //Remove once opaque pointer transition is complete ++ if (!ptrty->isOpaque()) { ++ Type *SrcTy = remapType(ptrty->getElementType()); ++ DstV = CE->getWithOperands(Ops, Ty, false, SrcTy); ++ } + } + else + DstV = CE->getWithOperands(Ops, Ty); +diff --git a/src/llvmcalltest.cpp b/src/llvmcalltest.cpp +index 1ce8e9fe55be..f3bd22732fd6 100644 +--- a/src/llvmcalltest.cpp ++++ b/src/llvmcalltest.cpp +@@ -31,7 +31,7 @@ DLLEXPORT const char *MakeIdentityFunction(jl_value_t* jl_AnyTy) { + PointerType *AnyTy = PointerType::get(StructType::get(Ctx), 0); + // FIXME: get AnyTy via jl_type_to_llvm(Ctx, jl_AnyTy) + +- Type *TrackedTy = PointerType::get(AnyTy->getElementType(), AddressSpace::Tracked); ++ Type *TrackedTy = PointerType::get(StructType::get(Ctx), AddressSpace::Tracked); + Module *M = new llvm::Module("shadow", Ctx); + Function *F = Function::Create( + FunctionType::get( Added: 190565c2.patch =================================================================== --- 190565c2.patch (rev 0) +++ 190565c2.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,91 @@ +From 190565c26d763be240cb3c4692559eebfffc9817 Mon Sep 17 00:00:00 2001 +From: Keno Fischer <[email protected]> +Date: Thu, 14 Apr 2022 00:53:14 -0400 +Subject: [PATCH] Some minimal LLVM15 compat (#44870) + +just a drive-by as I was trying out some commits on master +--- + src/cgutils.cpp | 4 ++-- + src/disasm.cpp | 13 ++++++++++++- + src/llvm-remove-addrspaces.cpp | 4 ++-- + 3 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/src/cgutils.cpp b/src/cgutils.cpp +index 3dff14b7be63..f5f378de772c 100644 +--- a/src/cgutils.cpp ++++ b/src/cgutils.cpp +@@ -2041,10 +2041,10 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va + const DataLayout &DL = jl_Module->getDataLayout(); + auto srcty = cast<PointerType>(src->getType()); + //TODO unsafe nonopaque pointer +- auto srcel = srcty->getElementType(); ++ auto srcel = srcty->getPointerElementType(); + auto dstty = cast<PointerType>(dst->getType()); + //TODO unsafe nonopaque pointer +- auto dstel = dstty->getElementType(); ++ auto dstel = dstty->getPointerElementType(); + if (srcel->isArrayTy() && srcel->getArrayNumElements() == 1) { + src = ctx.builder.CreateConstInBoundsGEP2_32(srcel, src, 0, 0); + srcel = srcel->getArrayElementType(); +diff --git a/src/disasm.cpp b/src/disasm.cpp +index 22926043b9fa..ebbcd03d0fc3 100644 +--- a/src/disasm.cpp ++++ b/src/disasm.cpp +@@ -108,6 +108,8 @@ + #include <llvm/Support/CodeGen.h> + #include <llvm/IR/LegacyPassManager.h> + ++#include <llvm-c/Disassembler.h> ++ + #include "julia.h" + #include "julia_internal.h" + #include "jitlayers.h" +@@ -899,7 +901,11 @@ static void jl_dump_asm_internal( + std::unique_ptr<MCCodeEmitter> CE; + std::unique_ptr<MCAsmBackend> MAB; + if (ShowEncoding) { ++#if JL_LLVM_VERSION >= 150000 ++ CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx)); ++#else + CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); ++#endif + MAB.reset(TheTarget->createMCAsmBackend(*STI, *MRI, Options)); + } + +@@ -1231,8 +1237,13 @@ jl_value_t *jl_dump_function_asm_impl(void *F, char raw_mc, const char* asm_vari + std::unique_ptr<MCAsmBackend> MAB(TM->getTarget().createMCAsmBackend( + STI, MRI, TM->Options.MCOptions)); + std::unique_ptr<MCCodeEmitter> MCE; +- if (binary) // enable MCAsmStreamer::AddEncodingComment printing ++ if (binary) { // enable MCAsmStreamer::AddEncodingComment printing ++#if JL_LLVM_VERSION >= 150000 ++ MCE.reset(TM->getTarget().createMCCodeEmitter(MII, *Context)); ++#else + MCE.reset(TM->getTarget().createMCCodeEmitter(MII, MRI, *Context)); ++#endif ++ } + auto FOut = std::make_unique<formatted_raw_ostream>(asmfile); + std::unique_ptr<MCStreamer> S(TM->getTarget().createAsmStreamer( + *Context, std::move(FOut), true, +diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp +index 5cd9a20b8cfd..a3f3cbb1fee7 100644 +--- a/src/llvm-remove-addrspaces.cpp ++++ b/src/llvm-remove-addrspaces.cpp +@@ -51,7 +51,7 @@ class AddrspaceRemoveTypeRemapper : public ValueMapTypeRemapper { + else { + //Remove once opaque pointer transition is complete + DstTy = PointerType::get( +- remapType(Ty->getElementType()), ++ remapType(Ty->getPointerElementType()), + ASRemapper(Ty->getAddressSpace())); + } + } +@@ -161,7 +161,7 @@ class AddrspaceRemoveValueMaterializer : public ValueMaterializer { + auto ptrty = cast<PointerType>(Src->getType()->getScalarType()); + //Remove once opaque pointer transition is complete + if (!ptrty->isOpaque()) { +- Type *SrcTy = remapType(ptrty->getElementType()); ++ Type *SrcTy = remapType(ptrty->getPointerElementType()); + DstV = CE->getWithOperands(Ops, Ty, false, SrcTy); + } + } Added: 23f39f83.patch =================================================================== --- 23f39f83.patch (rev 0) +++ 23f39f83.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,460 @@ +From 23f39f83b60162f124f3131a437c9f39afcdb835 Mon Sep 17 00:00:00 2001 +From: Keno Fischer <[email protected]> +Date: Fri, 10 Jun 2022 14:09:35 -0700 +Subject: [PATCH] llvm: Switch to trampoline-based jlcall annotations (#45088) + +As discussed extensively in #45057, when enabling LLVM's opaque pointer +support, we get significant miscompilations in jlcall callsites, because +calls with mismatching calling conventions are considered undefined behavior. +This implements Option D) from #45057, switching our jlcall callsites to use +a `julia.call` trampoline intrinsic instead. The lowering for this intrinsic +is essentially the same as the CC-based lowering before, except that the +callee is now of course the first argument rather than the actual callee. +Other than that, the changes are mostly mechanical. + +Fixes #45057 +--- + doc/src/devdocs/llvm.md | 10 +--- + src/cgutils.cpp | 4 +- + src/codegen.cpp | 88 +++++++++++++++++++++--------- + src/codegen_shared.h | 4 -- + src/llvm-gc-invariant-verifier.cpp | 9 ++- + src/llvm-late-gc-lowering.cpp | 30 ++++++---- + src/llvm-muladd.cpp | 2 +- + src/llvm-pass-helpers.cpp | 5 +- + src/llvm-pass-helpers.h | 2 + + test/compiler/codegen.jl | 3 +- + 10 files changed, 100 insertions(+), 57 deletions(-) + +diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md +index 840822f136004..b9890b5d7fe3e 100644 +--- a/doc/src/devdocs/llvm.md ++++ b/doc/src/devdocs/llvm.md +@@ -127,15 +127,11 @@ array. However, this would betray the SSA nature of the uses at the call site, + making optimizations (including GC root placement), significantly harder. + Instead, we emit it as follows: + ```llvm +-%bitcast = bitcast @any_unoptimized_call to %jl_value_t *(*)(%jl_value_t *, %jl_value_t *) +-call cc 37 %jl_value_t *%bitcast(%jl_value_t *%arg1, %jl_value_t *%arg2) ++call %jl_value_t *@julia.call(jl_value_t *(*)(...) @any_unoptimized_call, %jl_value_t *%arg1, %jl_value_t *%arg2) + ``` +-The special `cc 37` annotation marks the fact that this call site is really using +-the jlcall calling convention. This allows us to retain the SSA-ness of the ++This allows us to retain the SSA-ness of the + uses throughout the optimizer. GC root placement will later lower this call to +-the original C ABI. In the code the calling convention number is represented by +-the `JLCALL_F_CC` constant. In addition, there is the `JLCALL_CC` calling +-convention which functions similarly, but omits the first argument. ++the original C ABI. + + ## GC root placement + +diff --git a/src/cgutils.cpp b/src/cgutils.cpp +index cccdad7b78223..f1a051f19bda9 100644 +--- a/src/cgutils.cpp ++++ b/src/cgutils.cpp +@@ -1802,7 +1802,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, + ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type); + } + else { +- Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, JLCALL_F_CC); ++ Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, julia_call); + ret = mark_julia_type(ctx, callval, true, jl_any_type); + } + if (!jl_subtype(ret.typ, jltype)) { +@@ -3549,7 +3549,7 @@ static jl_cgval_t emit_setfield(jl_codectx_t &ctx, + rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type); + } + else { +- Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, JLCALL_F_CC); ++ Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, julia_call); + rhs = mark_julia_type(ctx, callval, true, jl_any_type); + } + if (!jl_subtype(rhs.typ, jfty)) { +diff --git a/src/codegen.cpp b/src/codegen.cpp +index c0f705c356872..753180069ecfb 100644 +--- a/src/codegen.cpp ++++ b/src/codegen.cpp +@@ -1092,6 +1092,43 @@ static const auto pointer_from_objref_func = new JuliaFunction{ + None); }, + }; + ++// julia.call represents a call with julia calling convention, it is used as ++// ++// ptr julia.call(ptr %fptr, ptr %f, ptr %arg1, ptr %arg2, ...) ++// ++// In late lowering the call will then be rewritten as ++// ++// ptr %fptr(ptr %f, ptr args, i64 nargs) ++// ++// with all the spelled out args appropriately moved into the argument stack buffer. ++// By representing it this way rather than allocating the stack buffer earlier, we ++// allow LLVM to make more aggressive optimizations on the call arguments. ++static const auto julia_call = new JuliaFunction{ ++ "julia.call", ++ [](LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), ++#ifdef JL_LLVM_OPAQUE_POINTERS ++ {PointerType::get(C, 0)}, ++#else ++ {get_func_sig(C)->getPointerTo()}, ++#endif ++ true); }, ++ nullptr ++}; ++ ++// julia.call2 is like julia.call, except that %arg1 gets passed as a register ++// argument at the end of the argument list. ++static const auto julia_call2 = new JuliaFunction{ ++ "julia.call2", ++ [](LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), ++#ifdef JL_LLVM_OPAQUE_POINTERS ++ {PointerType::get(C, 0)}, ++#else ++ {get_func_sig(C)->getPointerTo()}, ++#endif ++ true); }, ++ nullptr ++}; ++ + static const auto jltuple_func = new JuliaFunction{XSTR(jl_f_tuple), get_func_sig, get_func_attrs}; + static const auto &builtin_func_map() { + static std::map<jl_fptr_args_t, JuliaFunction*> builtins = { +@@ -1442,9 +1479,9 @@ static Value *get_last_age_field(jl_codectx_t &ctx); + static Value *get_current_signal_page(jl_codectx_t &ctx); + static void CreateTrap(IRBuilder<> &irbuilder, bool create_new_block = true); + static CallInst *emit_jlcall(jl_codectx_t &ctx, Function *theFptr, Value *theF, +- const jl_cgval_t *args, size_t nargs, CallingConv::ID cc); ++ const jl_cgval_t *args, size_t nargs, JuliaFunction *trampoline); + static CallInst *emit_jlcall(jl_codectx_t &ctx, JuliaFunction *theFptr, Value *theF, +- const jl_cgval_t *args, size_t nargs, CallingConv::ID cc); ++ const jl_cgval_t *args, size_t nargs, JuliaFunction *trampoline); + static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2, + Value *nullcheck1 = nullptr, Value *nullcheck2 = nullptr); + static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t nargs, const jl_cgval_t *argv, bool is_promotable=false); +@@ -3729,33 +3766,30 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, + + // Returns ctx.types().T_prjlvalue + static CallInst *emit_jlcall(jl_codectx_t &ctx, Function *theFptr, Value *theF, +- const jl_cgval_t *argv, size_t nargs, CallingConv::ID cc) ++ const jl_cgval_t *argv, size_t nargs, JuliaFunction *trampoline) + { ++ Function *TheTrampoline = prepare_call(trampoline); + // emit arguments + SmallVector<Value*, 3> theArgs; +- SmallVector<Type*, 3> argsT; +- if (theF) { ++ theArgs.push_back(ctx.builder.CreateBitCast(theFptr, ++ TheTrampoline->getFunctionType()->getParamType(0))); ++ if (theF) + theArgs.push_back(theF); +- argsT.push_back(ctx.types().T_prjlvalue); +- } + for (size_t i = 0; i < nargs; i++) { + Value *arg = boxed(ctx, argv[i]); + theArgs.push_back(arg); +- argsT.push_back(ctx.types().T_prjlvalue); + } +- FunctionType *FTy = FunctionType::get(ctx.types().T_prjlvalue, argsT, false); +- CallInst *result = ctx.builder.CreateCall(FTy, +- ctx.builder.CreateBitCast(theFptr, FTy->getPointerTo()), ++ CallInst *result = ctx.builder.CreateCall(TheTrampoline->getFunctionType(), ++ TheTrampoline, + theArgs); + addRetAttr(result, Attribute::NonNull); +- result->setCallingConv(cc); + return result; + } + // Returns ctx.types().T_prjlvalue + static CallInst *emit_jlcall(jl_codectx_t &ctx, JuliaFunction *theFptr, Value *theF, +- const jl_cgval_t *argv, size_t nargs, CallingConv::ID cc) ++ const jl_cgval_t *argv, size_t nargs, JuliaFunction *trampoline) + { +- return emit_jlcall(ctx, prepare_call(theFptr), theF, argv, nargs, cc); ++ return emit_jlcall(ctx, prepare_call(theFptr), theF, argv, nargs, trampoline); + } + + +@@ -3882,7 +3916,7 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, jl_value_t *jlretty + jl_Module->getOrInsertFunction(specFunctionObject, ctx.types().T_jlfunc).getCallee()); + addRetAttr(theFptr, Attribute::NonNull); + theFptr->addFnAttr(Attribute::get(ctx.builder.getContext(), "thunk")); +- Value *ret = emit_jlcall(ctx, theFptr, nullptr, argv, nargs, JLCALL_F_CC); ++ Value *ret = emit_jlcall(ctx, theFptr, nullptr, argv, nargs, julia_call); + return update_julia_type(ctx, mark_julia_type(ctx, ret, true, jlretty), inferred_retty); + } + +@@ -3979,7 +4013,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const + } + } + if (!handled) { +- Value *r = emit_jlcall(ctx, jlinvoke_func, boxed(ctx, lival), argv, nargs, JLCALL_F2_CC); ++ Value *r = emit_jlcall(ctx, jlinvoke_func, boxed(ctx, lival), argv, nargs, julia_call2); + result = mark_julia_type(ctx, r, true, rt); + } + if (result.typ == jl_bottom_type) +@@ -4008,7 +4042,7 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_ + return ret; + auto it = builtin_func_map.find(jl_f_modifyfield_addr); + assert(it != builtin_func_map.end()); +- Value *oldnew = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, JLCALL_F_CC); ++ Value *oldnew = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, julia_call); + return mark_julia_type(ctx, oldnew, true, rt); + } + if (f.constant && jl_typeis(f.constant, jl_intrinsic_type)) { +@@ -4018,7 +4052,7 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_ + } + + // emit function and arguments +- Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, nargs, JLCALL_F_CC); ++ Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, nargs, julia_call); + return mark_julia_type(ctx, callval, true, rt); + } + +@@ -4063,13 +4097,13 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt, bo + // special case for known builtin not handled by emit_builtin_call + auto it = builtin_func_map.find(jl_get_builtin_fptr(f.constant)); + if (it != builtin_func_map.end()) { +- Value *ret = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, JLCALL_F_CC); ++ Value *ret = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, julia_call); + return mark_julia_type(ctx, ret, true, rt); + } + } + + // emit function and arguments +- Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, generic_argv, n_generic_args, JLCALL_F_CC); ++ Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, generic_argv, n_generic_args, julia_call); + return mark_julia_type(ctx, callval, true, rt); + } + +@@ -5087,7 +5121,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_ + res.promotion_ssa = ssaidx_0based; + return res; + } +- Value *val = emit_jlcall(ctx, jlnew_func, nullptr, argv, nargs, JLCALL_F_CC); ++ Value *val = emit_jlcall(ctx, jlnew_func, nullptr, argv, nargs, julia_call); + // temporarily mark as `Any`, expecting `emit_ssaval_assign` to update + // it to the inferred type. + return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type); +@@ -5177,7 +5211,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_ + } + + return mark_julia_type(ctx, +- emit_jlcall(ctx, jl_new_opaque_closure_jlcall_func, Constant::getNullValue(ctx.types().T_prjlvalue), argv.data(), nargs, JLCALL_F_CC), ++ emit_jlcall(ctx, jl_new_opaque_closure_jlcall_func, Constant::getNullValue(ctx.types().T_prjlvalue), argv.data(), nargs, julia_call), + true, jl_any_type); + } + else if (head == jl_exc_sym) { +@@ -5414,7 +5448,7 @@ static void emit_cfunc_invalidate( + } + } + assert(AI == gf_thunk->arg_end()); +- Value *gf_ret = emit_jlcall(ctx, target, nullptr, myargs, nargs, JLCALL_F_CC); ++ Value *gf_ret = emit_jlcall(ctx, target, nullptr, myargs, nargs, julia_call); + jl_cgval_t gf_retbox = mark_julia_type(ctx, gf_ret, true, jl_any_type); + if (cc != jl_returninfo_t::Boxed) { + emit_typecheck(ctx, gf_retbox, rettype, "cfunction"); +@@ -5834,11 +5868,11 @@ static Function* gen_cfun_wrapper( + // for jlcall, we need to pass the function object even if it is a ghost. + Value *theF = boxed(ctx, inputargs[0]); + assert(theF); +- ret_jlcall = emit_jlcall(ctx, theFptr, theF, &inputargs[1], nargs, JLCALL_F_CC); ++ ret_jlcall = emit_jlcall(ctx, theFptr, theF, &inputargs[1], nargs, julia_call); + ctx.builder.CreateBr(b_after); + ctx.builder.SetInsertPoint(b_generic); + } +- Value *ret = emit_jlcall(ctx, jlapplygeneric_func, NULL, inputargs, nargs + 1, JLCALL_F_CC); ++ Value *ret = emit_jlcall(ctx, jlapplygeneric_func, NULL, inputargs, nargs + 1, julia_call); + if (age_ok) { + ctx.builder.CreateBr(b_after); + ctx.builder.SetInsertPoint(b_after); +@@ -7213,7 +7247,7 @@ static jl_llvm_functions_t + } + else { + restTuple = emit_jlcall(ctx, jltuple_func, Constant::getNullValue(ctx.types().T_prjlvalue), +- vargs, ctx.nvargs, JLCALL_F_CC); ++ vargs, ctx.nvargs, julia_call); + jl_cgval_t tuple = mark_julia_type(ctx, restTuple, true, vi.value.typ); + emit_varinfo_assign(ctx, vi, tuple); + } +@@ -8371,6 +8405,8 @@ static void init_jit_functions(void) + add_named_global(gc_preserve_end_func, (void*)NULL); + add_named_global(pointer_from_objref_func, (void*)NULL); + add_named_global(except_enter_func, (void*)NULL); ++ add_named_global(julia_call, (void*)NULL); ++ add_named_global(julia_call2, (void*)NULL); + + #ifdef _OS_WINDOWS_ + #if defined(_CPU_X86_64_) +diff --git a/src/codegen_shared.h b/src/codegen_shared.h +index e66f970270304..e4d90c38f667b 100644 +--- a/src/codegen_shared.h ++++ b/src/codegen_shared.h +@@ -80,10 +80,6 @@ namespace JuliaType { + } + } + +-// JLCALL with API arguments ([extra], arg0, arg1, arg2, ...) has the following ABI calling conventions defined: +-#define JLCALL_F_CC (CallingConv::ID)37 // (jl_value_t *arg0, jl_value_t **argv, uint32_t nargv) +-#define JLCALL_F2_CC (CallingConv::ID)38 // (jl_value_t *arg0, jl_value_t **argv, uint32_t nargv, jl_value_t *extra) +- + // return how many Tracked pointers are in T (count > 0), + // and if there is anything else in T (all == false) + struct CountTrackedPointers { +diff --git a/src/llvm-gc-invariant-verifier.cpp b/src/llvm-gc-invariant-verifier.cpp +index 0c6c7e27f50cf..6f45a39ad6b76 100644 +--- a/src/llvm-gc-invariant-verifier.cpp ++++ b/src/llvm-gc-invariant-verifier.cpp +@@ -160,12 +160,15 @@ void GCInvariantVerifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { + } + + void GCInvariantVerifier::visitCallInst(CallInst &CI) { +- CallingConv::ID CC = CI.getCallingConv(); +- if (CC == JLCALL_F_CC || CC == JLCALL_F2_CC) { ++ Function *Callee = CI.getCalledFunction(); ++ if (Callee && (Callee->getName() == "julia.call" || ++ Callee->getName() == "julia.call2")) { ++ bool First = true; + for (Value *Arg : CI.args()) { + Type *Ty = Arg->getType(); +- Check(Ty->isPointerTy() && cast<PointerType>(Ty)->getAddressSpace() == AddressSpace::Tracked, ++ Check(Ty->isPointerTy() && cast<PointerType>(Ty)->getAddressSpace() == (First ? 0 : AddressSpace::Tracked), + "Invalid derived pointer in jlcall", &CI); ++ First = false; + } + } + } +diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp +index 335d0803b8638..74b06e461ae9c 100644 +--- a/src/llvm-late-gc-lowering.cpp ++++ b/src/llvm-late-gc-lowering.cpp +@@ -2285,7 +2285,6 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { + ++it; + continue; + } +- CallingConv::ID CC = CI->getCallingConv(); + Value *callee = CI->getCalledOperand(); + if (callee && (callee == gc_flush_func || callee == gc_preserve_begin_func + || callee == gc_preserve_end_func)) { +@@ -2389,20 +2388,22 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { + ChangesMade = true; + ++it; + continue; +- } else if (CC == JLCALL_F_CC || +- CC == JLCALL_F2_CC) { ++ } else if ((call_func && callee == call_func) || ++ (call2_func && callee == call2_func)) { + assert(T_prjlvalue); + size_t nargs = CI->arg_size(); +- size_t nframeargs = nargs; +- if (CC == JLCALL_F_CC) ++ size_t nframeargs = nargs-1; ++ if (callee == call_func) + nframeargs -= 1; +- else if (CC == JLCALL_F2_CC) ++ else if (callee == call2_func) + nframeargs -= 2; + SmallVector<Value*, 4> ReplacementArgs; + auto arg_it = CI->arg_begin(); + assert(arg_it != CI->arg_end()); ++ Value *new_callee = *(arg_it++); ++ assert(arg_it != CI->arg_end()); + ReplacementArgs.push_back(*(arg_it++)); +- if (CC != JLCALL_F_CC) { ++ if (callee == call2_func) { + assert(arg_it != CI->arg_end()); + ReplacementArgs.push_back(*(arg_it++)); + } +@@ -2410,7 +2411,11 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { + int slot = 0; + IRBuilder<> Builder (CI); + for (; arg_it != CI->arg_end(); ++arg_it) { +- Builder.CreateAlignedStore(*arg_it, ++ // Julia emits IR with proper pointer types here, but because ++ // the julia.call signature is varargs, the optimizer is allowed ++ // to rewrite pointee types. It'll go away with opaque pointer ++ // types anyway. ++ Builder.CreateAlignedStore(Builder.CreateBitCast(*arg_it, T_prjlvalue), + Builder.CreateInBoundsGEP(T_prjlvalue, Frame, ConstantInt::get(T_int32, slot++)), + Align(sizeof(void*))); + } +@@ -2418,24 +2423,25 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { + (llvm::Value*)ConstantPointerNull::get(T_pprjlvalue) : + (llvm::Value*)Frame); + ReplacementArgs.push_back(ConstantInt::get(T_int32, nframeargs)); +- if (CC == JLCALL_F2_CC) { ++ if (callee == call2_func) { + // move trailing arg to the end now + Value *front = ReplacementArgs.front(); + ReplacementArgs.erase(ReplacementArgs.begin()); + ReplacementArgs.push_back(front); + } + FunctionType *FTy; +- if (CC == JLCALL_F_CC) // jl_fptr_args ++ if (callee == call_func) // jl_fptr_args + FTy = FunctionType::get(T_prjlvalue, {T_prjlvalue, T_pprjlvalue, T_int32}, false); +- else // CC == JLCALL_F2_CC // jl_invoke ++ else // callee == call2_func // jl_invoke + FTy = FunctionType::get(T_prjlvalue, {T_prjlvalue, T_pprjlvalue, T_int32, T_prjlvalue}, false); +- Value *newFptr = Builder.CreateBitCast(callee, FTy->getPointerTo()); ++ Value *newFptr = Builder.CreateBitCast(new_callee, FTy->getPointerTo()); + CallInst *NewCall = CallInst::Create(FTy, newFptr, ReplacementArgs, "", CI); + NewCall->setTailCallKind(CI->getTailCallKind()); + auto old_attrs = CI->getAttributes(); + NewCall->setAttributes(AttributeList::get(CI->getContext(), + getFnAttrs(old_attrs), + getRetAttrs(old_attrs), {})); ++ NewCall->takeName(CI); + NewCall->copyMetadata(*CI); + CI->replaceAllUsesWith(NewCall); + UpdatePtrNumbering(CI, NewCall, S); +diff --git a/src/llvm-pass-helpers.cpp b/src/llvm-pass-helpers.cpp +index d176773c1bf5f..f0c0c6ee77b44 100644 +--- a/src/llvm-pass-helpers.cpp ++++ b/src/llvm-pass-helpers.cpp +@@ -27,7 +27,8 @@ JuliaPassContext::JuliaPassContext() + pgcstack_getter(nullptr), gc_flush_func(nullptr), + gc_preserve_begin_func(nullptr), gc_preserve_end_func(nullptr), + pointer_from_objref_func(nullptr), alloc_obj_func(nullptr), +- typeof_func(nullptr), write_barrier_func(nullptr), module(nullptr) ++ typeof_func(nullptr), write_barrier_func(nullptr), call_func(nullptr), ++ call2_func(nullptr), module(nullptr) + { + } + +@@ -51,6 +52,8 @@ void JuliaPassContext::initFunctions(Module &M) + write_barrier_func = M.getFunction("julia.write_barrier"); + write_barrier_binding_func = M.getFunction("julia.write_barrier_binding"); + alloc_obj_func = M.getFunction("julia.gc_alloc_obj"); ++ call_func = M.getFunction("julia.call"); ++ call2_func = M.getFunction("julia.call2"); + } + + void JuliaPassContext::initAll(Module &M) +diff --git a/src/llvm-pass-helpers.h b/src/llvm-pass-helpers.h +index 75399de5c9f60..64d5dc00e2c5b 100644 +--- a/src/llvm-pass-helpers.h ++++ b/src/llvm-pass-helpers.h +@@ -58,6 +58,8 @@ struct JuliaPassContext { + llvm::Function *alloc_obj_func; + llvm::Function *typeof_func; + llvm::Function *write_barrier_func; ++ llvm::Function *call_func; ++ llvm::Function *call2_func; + + // Creates a pass context. Type and function pointers + // are set to `nullptr`. Metadata nodes are initialized. +diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl +index bf52d1705bd00..97ecda14efde0 100644 +--- a/test/compiler/codegen.jl ++++ b/test/compiler/codegen.jl +@@ -496,8 +496,9 @@ function f37262(x) + end + @testset "#37262" begin + str = "store volatile { i8, {}*, {}*, {}*, {}* } zeroinitializer, { i8, {}*, {}*, {}*, {}* }* %phic" ++ str_opaque = "store volatile { i8, ptr, ptr, ptr, ptr } zeroinitializer, ptr %phic" + llvmstr = get_llvm(f37262, (Bool,), false, false, false) +- @test contains(llvmstr, str) || llvmstr ++ @test (contains(llvmstr, str) || contains(llvmstr, str_opaque)) || llvmstr + @test f37262(Base.inferencebarrier(true)) === nothing + end + Added: 2ef4aba7.patch =================================================================== --- 2ef4aba7.patch (rev 0) +++ 2ef4aba7.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,233 @@ +From 2ef4aba78644e970b5e57d33956c459698bf41f0 Mon Sep 17 00:00:00 2001 +From: pchintalapudi <[email protected]> +Date: Sat, 17 Sep 2022 01:47:13 -0400 +Subject: [PATCH] Changes to support LLVM15 compilation (#46788) + +--- + src/aotcompile.cpp | 7 +++++-- + src/codegen.cpp | 4 ++-- + src/debug-registry.h | 1 + + src/debuginfo.cpp | 12 +++++------- + src/disasm.cpp | 20 ++++++++++++++------ + src/jitlayers.cpp | 4 +--- + src/llvm-alloc-opt.cpp | 2 +- + src/llvm-cpufeatures.cpp | 1 - + src/llvm-final-gc-lowering.cpp | 2 +- + src/llvm-late-gc-lowering.cpp | 3 ++- + src/llvm-propagate-addrspaces.cpp | 3 +-- + src/llvm-remove-addrspaces.cpp | 3 +-- + src/pipeline.cpp | 8 ++++++-- + 13 files changed, 40 insertions(+), 30 deletions(-) + +diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp +index 9ba46687081d..98777ddd175a 100644 +--- a/src/aotcompile.cpp ++++ b/src/aotcompile.cpp +@@ -34,6 +34,7 @@ + #include <llvm/Transforms/IPO/AlwaysInliner.h> + #include <llvm/Transforms/InstCombine/InstCombine.h> + #include <llvm/Transforms/Scalar/InstSimplifyPass.h> ++#include <llvm/Transforms/Scalar/SimpleLoopUnswitch.h> + #include <llvm/Transforms/Utils/SimplifyCFGOptions.h> + #include <llvm/Transforms/Utils/ModuleUtils.h> + #include <llvm/Passes/PassBuilder.h> +@@ -59,8 +60,6 @@ + + using namespace llvm; + +-#include "julia.h" +-#include "julia_internal.h" + #include "jitlayers.h" + #include "julia_assert.h" + +@@ -814,7 +813,11 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, + PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "loopinfo" as LLVM parallel loop + PM->add(createLICMPass()); + PM->add(createJuliaLICMPass()); ++#if JL_LLVM_VERSION >= 150000 ++ PM->add(createSimpleLoopUnswitchLegacyPass()); ++#else + PM->add(createLoopUnswitchPass()); ++#endif + PM->add(createLICMPass()); + PM->add(createJuliaLICMPass()); + PM->add(createInductiveRangeCheckEliminationPass()); // Must come before indvars +diff --git a/src/codegen.cpp b/src/codegen.cpp +index 0346393ea67c..e76eb9e511af 100644 +--- a/src/codegen.cpp ++++ b/src/codegen.cpp +@@ -155,8 +155,6 @@ typedef Instruction TerminatorInst; + #define NOMINMAX + #endif + +-#include "julia.h" +-#include "julia_internal.h" + #include "jitlayers.h" + #include "codegen_shared.h" + #include "processor.h" +@@ -8543,7 +8541,9 @@ extern "C" void jl_init_llvm(void) + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); ++#if JL_LLVM_VERSION < 150000 + initializeCoroutines(Registry); ++#endif + initializeScalarOpts(Registry); + initializeVectorization(Registry); + initializeAnalysis(Registry); +diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp +index eba6ea793b71..fe5614100f9e 100644 +--- a/src/debuginfo.cpp ++++ b/src/debuginfo.cpp +@@ -20,10 +20,13 @@ + #include <llvm/Object/COFF.h> + #include <llvm/Object/ELFObjectFile.h> + ++#ifdef _OS_DARWIN_ ++#include <CoreFoundation/CoreFoundation.h> ++#endif ++ + using namespace llvm; + +-#include "julia.h" +-#include "julia_internal.h" ++#include "jitlayers.h" + #include "debuginfo.h" + #if defined(_OS_LINUX_) + # include <link.h> +@@ -41,8 +41,6 @@ using namespace llvm; + #include <CoreFoundation/CoreFoundation.h> + #endif + +-#include "jitlayers.h" +- + static JITDebugInfoRegistry &getJITDebugRegistry() JL_NOTSAFEPOINT { + return jl_ExecutionEngine->getDebugInfoRegistry(); + } +diff --git a/src/disasm.cpp b/src/disasm.cpp +index 69692da4c4b1..cfc030f649fd 100644 +--- a/src/disasm.cpp ++++ b/src/disasm.cpp +@@ -111,8 +111,6 @@ + + #include <llvm-c/Disassembler.h> + +-#include "julia.h" +-#include "julia_internal.h" + #include "jitlayers.h" + #include "processor.h" + +@@ -796,7 +794,13 @@ static const char *SymbolLookup(void *DisInfo, uint64_t ReferenceValue, uint64_t + return NULL; + } + +-static int OpInfoLookup(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Size, ++static int OpInfoLookup(void *DisInfo, uint64_t PC, ++ uint64_t Offset, ++#if JL_LLVM_VERSION < 150000 ++ uint64_t Size, ++#else ++ uint64_t OpSize, uint64_t InstSize, ++#endif + int TagType, void *TagBuf) + { + SymbolTable *SymTab = (SymbolTable*)DisInfo; +@@ -1050,10 +1054,14 @@ static void jl_dump_asm_internal( + MCInst Inst; + MCDisassembler::DecodeStatus S; + FuncMCView view = memoryObject.slice(Index); ++#if JL_LLVM_VERSION < 150000 ++#define getCommentOS() GetCommentOS() ++#endif + S = DisAsm->getInstruction(Inst, insSize, view, 0, +- /*CStream*/ pass != 0 ? Streamer->GetCommentOS() : nulls()); +- if (pass != 0 && Streamer->GetCommentOS().tell() > 0) +- Streamer->GetCommentOS() << '\n'; ++ /*CStream*/ pass != 0 ? Streamer->getCommentOS () : nulls()); ++ if (pass != 0 && Streamer->getCommentOS ().tell() > 0) ++ Streamer->getCommentOS () << '\n'; ++#undef GetCommentOS + switch (S) { + case MCDisassembler::Fail: + if (insSize == 0) // skip illegible bytes +diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp +index 78803e15e0dd..a08f92836bdb 100644 +--- a/src/jitlayers.cpp ++++ b/src/jitlayers.cpp +@@ -36,8 +36,6 @@ + + using namespace llvm; + +-#include "julia.h" +-#include "julia_internal.h" + #include "codegen_shared.h" + #include "jitlayers.h" + #include "julia_assert.h" +diff --git a/src/llvm-cpufeatures.cpp b/src/llvm-cpufeatures.cpp +index 1c21ddba49be..6211d284bdd2 100644 +--- a/src/llvm-cpufeatures.cpp ++++ b/src/llvm-cpufeatures.cpp +@@ -26,7 +26,7 @@ + #include <llvm/Target/TargetMachine.h> + #include <llvm/Support/Debug.h> + +-#include "julia.h" ++#include "jitlayers.h" + + #define DEBUG_TYPE "cpufeatures" + +diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp +index 1f5bd34373c2..e7e9fe2f4f26 100644 +--- a/src/llvm-final-gc-lowering.cpp ++++ b/src/llvm-final-gc-lowering.cpp +@@ -107,7 +107,7 @@ Value *FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) + ConstantInt::get(Type::getInt32Ty(F.getContext()), sizeof(jl_value_t*) * (nRoots + 2)), // len + ConstantInt::get(Type::getInt1Ty(F.getContext()), 0)}; // volatile + CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); +- cast<MemSetInst>(zeroing)->setDestAlignment(16); ++ cast<MemSetInst>(zeroing)->setDestAlignment(Align(16)); + zeroing->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); + zeroing->insertAfter(tempSlot_i8); + +diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp +index 99d25d81a866..2441cf0ada10 100644 +--- a/src/llvm-late-gc-lowering.cpp ++++ b/src/llvm-late-gc-lowering.cpp +@@ -2614,7 +2614,8 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector<int> &Colors, State + unsigned AllocaSlot = 2; // first two words are metadata + auto replace_alloca = [this, gcframe, &AllocaSlot, T_int32](AllocaInst *&AI) { + // Pick a slot for the alloca. +- unsigned align = AI->getAlignment() / sizeof(void*); // TODO: use DataLayout pointer size ++ AI->getAlign(); ++ unsigned align = AI->getAlign().value() / sizeof(void*); // TODO: use DataLayout pointer size + assert(align <= 16 / sizeof(void*) && "Alignment exceeds llvm-final-gc-lowering abilities"); + if (align > 1) + AllocaSlot = LLT_ALIGN(AllocaSlot, align); +diff --git a/src/llvm-propagate-addrspaces.cpp b/src/llvm-propagate-addrspaces.cpp +index 97ae9d0555a8..e2d390a5e439 100644 +--- a/src/llvm-propagate-addrspaces.cpp ++++ b/src/llvm-propagate-addrspaces.cpp +@@ -22,8 +22,7 @@ + #include <llvm/Pass.h> + #include <llvm/Support/Debug.h> + +-#include "codegen_shared.h" +-#include "julia.h" ++#include "codegen_shared.h" + + #define DEBUG_TYPE "propagate_julia_addrspaces" + +diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp +index a3f3cbb1fee7..814e31ec2252 100644 +--- a/src/llvm-remove-addrspaces.cpp ++++ b/src/llvm-remove-addrspaces.cpp +@@ -12,8 +12,7 @@ + #include <llvm/Transforms/Utils/Cloning.h> + #include <llvm/Transforms/Utils/ValueMapper.h> + +-#include "codegen_shared.h" +-#include "julia.h" ++#include "codegen_shared.h" + + #define DEBUG_TYPE "remove_addrspaces" + Added: 3423639d.patch =================================================================== --- 3423639d.patch (rev 0) +++ 3423639d.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,21 @@ +From 3423639d000f0e9ef9d01f4b91742dc4acf8d270 Mon Sep 17 00:00:00 2001 +From: Keno Fischer <[email protected]> +Date: Mon, 25 Apr 2022 22:49:30 -0400 +Subject: [PATCH] Header compat for LLVM15 (#45089) + +--- + src/disasm.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/disasm.cpp b/src/disasm.cpp +index fa2e3e819a0b..4d21f49e4af2 100644 +--- a/src/disasm.cpp ++++ b/src/disasm.cpp +@@ -60,6 +60,7 @@ + // for outputting disassembly + #include <llvm/ADT/Triple.h> + #include <llvm/AsmParser/Parser.h> ++#include <llvm/Analysis/TargetTransformInfo.h> + #include <llvm/BinaryFormat/COFF.h> + #include <llvm/BinaryFormat/MachO.h> + #include <llvm/DebugInfo/DIContext.h> Added: 68adc00e.patch =================================================================== --- 68adc00e.patch (rev 0) +++ 68adc00e.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,55 @@ +From 68adc00eb162c6932e1e2ba3cde9cb3b12bd8f3b Mon Sep 17 00:00:00 2001 +From: Keno Fischer <[email protected]> +Date: Wed, 20 Apr 2022 22:02:49 -0400 +Subject: [PATCH] Enable opaque pointers for LLVM master (#45012) + +Essentially a rebase of #44334 to current master. I would like to work on +some IR canonicalization improvements, but it doesn't make much sense +to that without opaque pointers, since canonical forms will change. + +This bootstraps fine on LLVM master, though there are test failures +both with and without this change. I think we'll just have to address +those as part of the regular upgrade cycle as usual (though we should +probably do LLVM 14 first to catch any 13->14 regressions). +--- + src/cgutils.cpp | 3 +++ + src/jitlayers.cpp | 8 +++++++- + src/llvm-version.h | 4 ++++ + 3 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/src/cgutils.cpp b/src/cgutils.cpp +index f5f378de772c..6f346b32728b 100644 +--- a/src/cgutils.cpp ++++ b/src/cgutils.cpp +@@ -2035,6 +2035,8 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va + // If the types are small and simple, use load and store directly. + // Going through memcpy can cause LLVM (e.g. SROA) to create bitcasts between float and int + // that interferes with other optimizations. ++#ifndef JL_LLVM_OPAQUE_POINTERS ++ // TODO: Restore this for opaque pointers? Needs extra type information from the caller. + if (sz <= 64) { + // The size limit is arbitrary but since we mainly care about floating points and + // machine size vectors this should be enough. +@@ -2073,6 +2075,7 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va + return; + } + } ++#endif + // the memcpy intrinsic does not allow to specify different alias tags + // for the load part (x.tbaa) and the store part (ctx.tbaa().tbaa_stack). + // since the tbaa lattice has to be a tree we have unfortunately +diff --git a/src/llvm-version.h b/src/llvm-version.h +index 6d79abdf271f..4e15e787b7de 100644 +--- a/src/llvm-version.h ++++ b/src/llvm-version.h +@@ -13,6 +13,10 @@ + #error Only LLVM versions >= 12.0.0 are supported by Julia + #endif + ++#if JL_LLVM_VERSION >= 150000 ++#define JL_LLVM_OPAQUE_POINTERS 1 ++#endif ++ + #ifdef __cplusplus + #if defined(__GNUC__) && (__GNUC__ >= 9) + // Added in GCC 9, this warning is annoying Added: 700c69b1.patch =================================================================== --- 700c69b1.patch (rev 0) +++ 700c69b1.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,22 @@ +From 700c69b194721b58043494083cc6227dfc16378c Mon Sep 17 00:00:00 2001 +From: Valentin Churavy <[email protected]> +Date: Fri, 18 Feb 2022 14:42:27 -0500 +Subject: [PATCH] fix deprecated AlignedLoad + +--- + src/codegen.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/codegen.cpp b/src/codegen.cpp +index 83946391e40c8..1e5118559b50e 100644 +--- a/src/codegen.cpp ++++ b/src/codegen.cpp +@@ -4912,7 +4912,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval) + jl_cgval_t jlcall_ptr = mark_julia_type(ctx, F, false, jl_voidpointer_type); + jl_cgval_t world_age = mark_julia_type(ctx, + tbaa_decorate(ctx.tbaa().tbaa_gcframe, +- ctx.builder.CreateAlignedLoad(ctx.world_age_field, Align(sizeof(size_t)))), ++ ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ctx.world_age_field, Align(sizeof(size_t)))), + false, + jl_long_type); + jl_cgval_t fptr(ctx.builder.getContext()); Added: 7b2d1e08.patch =================================================================== --- 7b2d1e08.patch (rev 0) +++ 7b2d1e08.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,264 @@ +From 7b2d1e0851d5b2e63441139b94208e58278bc97b Mon Sep 17 00:00:00 2001 +From: Prem Chintalapudi <[email protected]> +Date: Wed, 23 Feb 2022 13:48:30 -0500 +Subject: [PATCH] Remove uses of getPointerElementType + +--- + src/ccall.cpp | 3 ++- + src/codegen.cpp | 49 ++++++++++++++++++++++------------- + src/codegen_shared.h | 17 ++++++++++-- + src/llvm-late-gc-lowering.cpp | 12 ++++----- + src/llvmcalltest.cpp | 4 +-- + 5 files changed, 55 insertions(+), 30 deletions(-) + +diff --git a/src/ccall.cpp b/src/ccall.cpp +index 797a89ebf9d76..04d8b5525cd30 100644 +--- a/src/ccall.cpp ++++ b/src/ccall.cpp +@@ -218,8 +218,9 @@ static GlobalVariable *emit_plt_thunk( + SmallVector<Value*, 16> args; + for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg) + args.push_back(&*arg); ++ assert(cast<PointerType>(ptr->getType())->isOpaqueOrPointeeTypeMatches(functype)); + CallInst *ret = irbuilder.CreateCall( +- cast<FunctionType>(ptr->getType()->getPointerElementType()), ++ functype, + ptr, ArrayRef<Value*>(args)); + ret->setAttributes(attrs); + if (cc != CallingConv::C) +diff --git a/src/codegen.cpp b/src/codegen.cpp +index 1e5118559b50e..82e3bf1ac796a 100644 +--- a/src/codegen.cpp ++++ b/src/codegen.cpp +@@ -1436,7 +1436,7 @@ static Value *emit_inttoptr(jl_codectx_t &ctx, Value *v, Type *ty) + auto ptr = I->getOperand(0); + if (ty->getPointerAddressSpace() == ptr->getType()->getPointerAddressSpace()) + return ctx.builder.CreateBitCast(ptr, ty); +- else if (ty->getPointerElementType() == ptr->getType()->getPointerElementType()) ++ else if (cast<PointerType>(ty)->hasSameElementTypeAs(cast<PointerType>(ptr->getType()))) + return ctx.builder.CreateAddrSpaceCast(ptr, ty); + } + return ctx.builder.CreateIntToPtr(v, ty); +@@ -3564,7 +3564,8 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_method_instance_ + case jl_returninfo_t::Ghosts: + break; + case jl_returninfo_t::SRet: +- result = emit_static_alloca(ctx, cft->getParamType(0)->getPointerElementType()); ++ result = emit_static_alloca(ctx, getAttributeAtIndex(returninfo.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType()); ++ assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0)))); + argvals[idx] = result; + idx++; + break; +@@ -5123,6 +5124,14 @@ static Function *emit_tojlinvoke(jl_code_instance_t *codeinst, Module *M, jl_cod + return f; + } + ++static Type *get_returnroots_type(jl_codectx_t &ctx, unsigned rootcount) { ++ return ArrayType::get(ctx.types().T_prjlvalue, rootcount); ++} ++ ++static Type *get_unionbytes_type(LLVMContext &C, unsigned unionbytes) { ++ return ArrayType::get(getInt8Ty(C), unionbytes); ++} ++ + static void emit_cfunc_invalidate( + Function *gf_thunk, jl_returninfo_t::CallingConv cc, unsigned return_roots, + jl_value_t *calltype, jl_value_t *rettype, +@@ -5195,7 +5204,8 @@ static void emit_cfunc_invalidate( + case jl_returninfo_t::SRet: { + if (return_roots) { + Value *root1 = gf_thunk->arg_begin() + 1; // root1 has type [n x {}*]* +- root1 = ctx.builder.CreateConstInBoundsGEP2_32(root1->getType()->getPointerElementType(), root1, 0, 0); ++ assert(cast<PointerType>(root1->getType())->isOpaqueOrPointeeTypeMatches(get_returnroots_type(ctx, return_roots))); ++ root1 = ctx.builder.CreateConstInBoundsGEP2_32(get_returnroots_type(ctx, return_roots), root1, 0, 0); + ctx.builder.CreateStore(gf_ret, root1); + } + emit_memcpy(ctx, &*gf_thunk->arg_begin(), nullptr, gf_ret, nullptr, jl_datatype_size(rettype), julia_alignment(rettype)); +@@ -5617,12 +5627,18 @@ static Function* gen_cfun_wrapper( + result = emit_bitcast(ctx, sretPtr, cft->getParamType(0)); + } + else { +- result = emit_static_alloca(ctx, cft->getParamType(0)->getPointerElementType()); ++ if (jlfunc_sret) { ++ result = emit_static_alloca(ctx, getAttributeAtIndex(returninfo.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType()); ++ assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0)))); ++ } else { ++ result = emit_static_alloca(ctx, get_unionbytes_type(ctx.builder.getContext(), returninfo.union_bytes)); ++ assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0)))); ++ } + } + args.push_back(result); + } + if (returninfo.return_roots) { +- AllocaInst *return_roots = emit_static_alloca(ctx, ArrayType::get(ctx.types().T_prjlvalue, returninfo.return_roots)); ++ AllocaInst *return_roots = emit_static_alloca(ctx, get_returnroots_type(ctx, returninfo.return_roots)); + args.push_back(return_roots); + } + for (size_t i = 0; i < nargs + 1; i++) { +@@ -5670,8 +5686,9 @@ static Function* gen_cfun_wrapper( + emit_cfunc_invalidate(gf_thunk, returninfo.cc, returninfo.return_roots, lam->specTypes, codeinst->rettype, nargs + 1, ctx.emission_context); + theFptr = ctx.builder.CreateSelect(age_ok, theFptr, gf_thunk); + } ++ assert(cast<PointerType>(theFptr->getType())->isOpaqueOrPointeeTypeMatches(returninfo.decl->getFunctionType())); + CallInst *call = ctx.builder.CreateCall( +- cast<FunctionType>(theFptr->getType()->getPointerElementType()), ++ cast<FunctionType>(returninfo.decl->getFunctionType()), + theFptr, ArrayRef<Value*>(args)); + call->setAttributes(returninfo.decl->getAttributes()); + switch (returninfo.cc) { +@@ -6028,7 +6045,8 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret + case jl_returninfo_t::Ghosts: + break; + case jl_returninfo_t::SRet: +- result = ctx.builder.CreateAlloca(ftype->getParamType(0)->getPointerElementType()); ++ assert(cast<PointerType>(ftype->getParamType(0))->isOpaqueOrPointeeTypeMatches(getAttributeAtIndex(f.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType())); ++ result = ctx.builder.CreateAlloca(getAttributeAtIndex(f.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType()); + args[idx] = result; + idx++; + break; +@@ -6174,13 +6192,8 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, String + if (props.cc == jl_returninfo_t::SRet) { + assert(srt); + unsigned argno = 1; +-#if JL_LLVM_VERSION < 120000 +- attributes = attributes.addAttribute(ctx.builder.getContext(), argno, Attribute::StructRet); +- (void)srt; // silence unused variable error +-#else + Attribute sret = Attribute::getWithStructRetType(ctx.builder.getContext(), srt); + attributes = addAttributeAtIndex(attributes, ctx.builder.getContext(), argno, sret); +-#endif + attributes = addAttributeAtIndex(attributes, ctx.builder.getContext(), argno, Attribute::NoAlias); + attributes = addAttributeAtIndex(attributes, ctx.builder.getContext(), argno, Attribute::NoCapture); + } +@@ -6191,7 +6204,7 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, String + } + + if (props.return_roots) { +- fsig.push_back(ArrayType::get(ctx.types().T_prjlvalue, props.return_roots)->getPointerTo(0)); ++ fsig.push_back(get_returnroots_type(ctx, props.return_roots)->getPointerTo(0)); + unsigned argno = fsig.size(); + attributes = addAttributeAtIndex(attributes, ctx.builder.getContext(), argno, Attribute::NoAlias); + attributes = addAttributeAtIndex(attributes, ctx.builder.getContext(), argno, Attribute::NoCapture); +@@ -6241,13 +6254,13 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, String + return props; + } + +-static void emit_sret_roots(jl_codectx_t &ctx, bool isptr, Value *Src, Type *T, Value *Shadow, unsigned count) ++static void emit_sret_roots(jl_codectx_t &ctx, bool isptr, Value *Src, Type *T, Value *Shadow, Type *ShadowT, unsigned count) + { + if (isptr) + Src = maybe_decay_tracked(ctx, Src); +- if (isptr && Src->getType()->getPointerElementType() != T) ++ if (isptr && !cast<PointerType>(Src->getType())->isOpaqueOrPointeeTypeMatches(T)) + Src = ctx.builder.CreateBitCast(Src, T->getPointerTo(Src->getType()->getPointerAddressSpace())); +- unsigned emitted = TrackWithShadow(Src, T, isptr, Shadow, ctx.builder); ++ unsigned emitted = TrackWithShadow(Src, T, isptr, Shadow, ShadowT, ctx.builder); //This comes from Late-GC-Lowering?? + assert(emitted == count); (void)emitted; (void)count; + } + +@@ -7313,7 +7326,7 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t> + if (retvalinfo.ispointer()) { + if (returninfo.return_roots) { + Type *store_ty = julia_type_to_llvm(ctx, retvalinfo.typ); +- emit_sret_roots(ctx, true, data_pointer(ctx, retvalinfo), store_ty, f->arg_begin() + 1, returninfo.return_roots); ++ emit_sret_roots(ctx, true, data_pointer(ctx, retvalinfo), store_ty, f->arg_begin() + 1, get_returnroots_type(ctx, returninfo.return_roots), returninfo.return_roots); + } + if (returninfo.cc == jl_returninfo_t::SRet) { + assert(jl_is_concrete_type(jlrettype)); +@@ -7330,7 +7343,7 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t> + Value *Val = retvalinfo.V; + if (returninfo.return_roots) { + assert(julia_type_to_llvm(ctx, retvalinfo.typ) == store_ty); +- emit_sret_roots(ctx, false, Val, store_ty, f->arg_begin() + 1, returninfo.return_roots); ++ emit_sret_roots(ctx, false, Val, store_ty, f->arg_begin() + 1, get_returnroots_type(ctx, returninfo.return_roots), returninfo.return_roots); + } + if (dest_ty != sret->getType()) + sret = emit_bitcast(ctx, sret, dest_ty); +diff --git a/src/codegen_shared.h b/src/codegen_shared.h +index f32d81dadbba8..bbcc862e254ee 100644 +--- a/src/codegen_shared.h ++++ b/src/codegen_shared.h +@@ -63,8 +63,12 @@ namespace JuliaType { + return llvm::FunctionType::get(T_prjlvalue, ftargs, false); + } + ++ static inline auto get_voidfunc_ty(llvm::LLVMContext &C) { ++ return llvm::FunctionType::get(llvm::Type::getVoidTy(C), /*isVarArg*/false); ++ } ++ + static inline auto get_pvoidfunc_ty(llvm::LLVMContext &C) { +- return llvm::FunctionType::get(llvm::Type::getVoidTy(C), /*isVarArg*/false)->getPointerTo(); ++ return get_voidfunc_ty(C)->getPointerTo(); + } + } + +@@ -81,7 +85,7 @@ struct CountTrackedPointers { + CountTrackedPointers(llvm::Type *T); + }; + +-unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::IRBuilder<> &irbuilder); ++unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::Type *DTy, llvm::IRBuilder<> &irbuilder); + std::vector<llvm::Value*> ExtractTrackedValues(llvm::Value *Src, llvm::Type *STy, bool isptr, llvm::IRBuilder<> &irbuilder, llvm::ArrayRef<unsigned> perm_offsets={}); + + static inline void llvm_dump(llvm::Value *v) +@@ -298,4 +302,13 @@ inline bool hasAttributesAtIndex(const AttributeList &L, unsigned Index) + #endif + } + ++inline Attribute getAttributeAtIndex(const AttributeList &L, unsigned Index, Attribute::AttrKind Kind) ++{ ++#if JL_LLVM_VERSION >= 140000 ++ return L.getAttributeAtIndex(Index, Kind); ++#else ++ return L.getAttribute(Index, Kind); ++#endif ++} ++ + } +diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp +index a972ad4691247..253598761df87 100644 +--- a/src/llvm-late-gc-lowering.cpp ++++ b/src/llvm-late-gc-lowering.cpp +@@ -1473,8 +1473,8 @@ State LateLowerGCFrame::LocalScan(Function &F) { + MaybeNoteDef(S, BBS, CI, BBS.Safepoints); + } + if (CI->hasStructRetAttr()) { +- // TODO: get ElT from SRet attribute +- Type *ElT = (CI->arg_begin()[0])->getType()->getPointerElementType(); ++ Type *ElT = getAttributeAtIndex(CI->getAttributes(), 1, Attribute::StructRet).getValueAsType(); ++ assert(cast<PointerType>(CI->getArgOperand(0)->getType())->isOpaqueOrPointeeTypeMatches(getAttributeAtIndex(CI->getAttributes(), 1, Attribute::StructRet).getValueAsType())); + auto tracked = CountTrackedPointers(ElT); + if (tracked.count) { + AllocaInst *SRet = dyn_cast<AllocaInst>((CI->arg_begin()[0])->stripInBoundsOffsets()); +@@ -1788,12 +1788,12 @@ std::vector<Value*> ExtractTrackedValues(Value *Src, Type *STy, bool isptr, IRBu + return Ptrs; + } + +-unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, IRBuilder<> &irbuilder) { ++unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, Type *DTy, IRBuilder<> &irbuilder) { + auto Ptrs = ExtractTrackedValues(Src, STy, isptr, irbuilder); + for (unsigned i = 0; i < Ptrs.size(); ++i) { +- Value *Elem = Ptrs[i]; +- Type *ET = Dst->getType()->getPointerElementType(); // Dst has type `[n x {}*]*` +- Value *Slot = irbuilder.CreateConstInBoundsGEP2_32(ET, Dst, 0, i); ++ Value *Elem = Ptrs[i];// Dst has type `[n x {}*]*` ++ Value *Slot = irbuilder.CreateConstInBoundsGEP2_32(DTy, Dst, 0, i); ++ assert(cast<PointerType>(Dst->getType())->isOpaqueOrPointeeTypeMatches(DTy)); + StoreInst *shadowStore = irbuilder.CreateAlignedStore(Elem, Slot, Align(sizeof(void*))); + shadowStore->setOrdering(AtomicOrdering::NotAtomic); + // TODO: shadowStore->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); +diff --git a/src/llvmcalltest.cpp b/src/llvmcalltest.cpp +index f3bd22732fd67..b225111520c39 100644 +--- a/src/llvmcalltest.cpp ++++ b/src/llvmcalltest.cpp +@@ -28,9 +28,7 @@ extern "C" { + + DLLEXPORT const char *MakeIdentityFunction(jl_value_t* jl_AnyTy) { + LLVMContext Ctx; +- PointerType *AnyTy = PointerType::get(StructType::get(Ctx), 0); +- // FIXME: get AnyTy via jl_type_to_llvm(Ctx, jl_AnyTy) +- ++ // FIXME: get TrackedTy via jl_type_to_llvm(Ctx, jl_AnyTy) + Type *TrackedTy = PointerType::get(StructType::get(Ctx), AddressSpace::Tracked); + Module *M = new llvm::Module("shadow", Ctx); + Function *F = Function::Create( Added: LLVM-14.patch =================================================================== --- LLVM-14.patch (rev 0) +++ LLVM-14.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,13 @@ +diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl +index d70cca9c48..1d72853845 100644 +--- a/base/binaryplatforms.jl ++++ b/base/binaryplatforms.jl +@@ -903,7 +903,7 @@ function detect_cxxstring_abi() + end + + function open_libllvm(f::Function) +- for lib_name in ("libLLVM-13jl", "libLLVM", "LLVM", "libLLVMSupport") ++ for lib_name in ("libLLVM-13jl", "libLLVM", "LLVM", "libLLVMSupport", "libLLVM-14") + hdl = Libdl.dlopen_e(lib_name) + if hdl != C_NULL + try Modified: PKGBUILD =================================================================== --- PKGBUILD 2023-01-07 13:39:57 UTC (rev 1381672) +++ PKGBUILD 2023-01-07 14:01:32 UTC (rev 1381673) @@ -9,36 +9,56 @@ pkgname=julia epoch=2 pkgver=1.8.4 -pkgrel=1 +pkgrel=2 arch=(x86_64) pkgdesc='High-level, high-performance, dynamic programming language' url='https://julialang.org/' license=(MIT) depends=(cblas fftw hicolor-icon-theme libgit2 libunwind libutf8proc openblas - suitesparse mbedtls openlibm pcre2 llvm-libs p7zip libblastrampoline) -makedepends=(cmake gcc-fortran python llvm patchelf libwhich) + suitesparse mbedtls openlibm pcre2 llvm14-libs p7zip libblastrampoline) +makedepends=(cmake gcc-fortran python llvm14 patchelf libwhich) optdepends=('gnuplot: If using the Gaston Package from julia') replaces=(julia-docs) source=(https://github.com/JuliaLang/julia/releases/download/v$pkgver/$pkgname-$pkgver-full.tar.gz{,.asc} ed9851b0.patch 074d761f.patch - julia-llvm-14.patch + 700c69b1.patch + 7b2d1e08.patch + 0db596e6.patch + 190565c2.patch + 68adc00e.patch + 3423639d.patch + 23f39f83.patch + 2ef4aba7.patch + julia-llvm-15.patch + LLVM-14.patch julia-libunwind-1.6.patch julia-system-cblas.patch julia-hardcoded-libs.patch julia-suitesparse-version-mismatch.patch - system-gcc-libs-symlink.patch) + system-gcc-libs-symlink.patch + julia-mpfr-4.2.patch) backup=(etc/julia/startup.jl) sha256sums=('1cd032262c5c42048a7819bccd684e843bbb8f66cf9ff56c315881ea431f0033' 'SKIP' 'ce0de27461197ade425cacdd3a642a6b2579e27c7ecc4a457e2b1bde2d76492a' '5d4093de84f836e16ec7f83736494e82804ab2fa37bc5594a5b99b1708dce322' - '0d9e21126820a20083e0251c61129134166cc1c7b6637fbda1d3e6ee7614cce0' + '8cdc46dd0840eac8ff625c0be867f01f18bd73e7ad4991abb52d46d46daac6a5' + 'f89796cb4c51501fbb5ad667815054f9a4500a9a47fa8dfe497cbe452894e3df' + '513a48a4a954cbbb7684d2dac1aa287d08dc613b785958406fd9d12ee348f865' + 'aa3b0b03410101bd70293c4012a7bc213afae206dd237172c85477d6125f08a4' + 'c0f504a53be19984fc8dc065057872ad2a98bc5e3801636d0cbdca713fbbf9de' + '2e736b5a042fb5448ed8622d14f23e9b1c1bb90d003fe511e6d5c45e074780ab' + '0b2e7262d9de2c8436409696030b01402d5c2dc5996b1a0cfee91c0b025ee0a9' + 'f11bad320938e2f7567890d5c165ecb1a62c1ac6d2c9c27fa058a4d0d142875b' + '6a3a482ace2d9cba7c4d86443738a0aba47016c6f530ba8d924acb0be1a86548' + '2de225ce6636a333f0a5f3a7bf61679e02f586c33ad0ab75961b022dfcdc77c1' 'cea321f7e16381dd795ee20d7bd5eda64f9b453c01d13e960962eb2723907e24' '65f24275edb8357ded3c53fd8a10c3d1ed13fa3d34a3869df0c04da10dba6c9d' - '929a52a5503b6d1a21774c170ece0981cb7da1c1e7a5b7a2892cfb1251689b55' + 'dd8896da27f691005c3294539fa229823a0ce33802b34287beae8709bbbe535d' '52c481d691940bbc4714d54cfde20fb1973350ba4a4c2386941a32fc007fdd85' - '87fa75d54d00261d041dfc1040efdea1060356bf7afdbfa0c099f67b9fc9f787') + '87fa75d54d00261d041dfc1040efdea1060356bf7afdbfa0c099f67b9fc9f787' + 'a47b2e110438082c101392b36d944ee8c40e6113231b88d1ba63b1c1b61b5eaa') validpgpkeys=('3673DF529D9049477F76B37566E3C7DC03D6E495') # Julia (Binary signing key) <[email protected]> options=(!lto) @@ -48,7 +68,17 @@ # Fixes for LLVM 14 patch -p1 -i ../ed9851b0.patch patch -p1 -i ../074d761f.patch - patch -p1 -i ../julia-llvm-14.patch + patch -p1 -i ../700c69b1.patch + patch -p1 -i ../LLVM-14.patch +# Fixes for LLVM 15 - builds, but many tests fail +# patch -p1 -i ../0db596e6.patch +# patch -p1 -i ../7b2d1e08.patch +# patch -p1 -i ../190565c2.patch +# patch -p1 -i ../68adc00e.patch +# patch -p1 -i ../3423639d.patch +# patch -p1 -i ../23f39f83.patch +# patch -p1 -i ../2ef4aba7.patch +# patch -p1 -i ../julia-llvm-15.patch # libunwind 1.6 compatibility patch -p1 -i ../julia-libunwind-1.6.patch # Add and use option to build with system cblas @@ -57,6 +87,8 @@ patch -p1 -i ../julia-hardcoded-libs.patch # Fix symlinking system gcc libraries patch -p1 -i ../system-gcc-libs-symlink.patch +# Fix tests with MPFR 4.2 + patch -p1 -i ../julia-mpfr-4.2.patch # Fix test failures due to using system blas sed -e 's|0.22314355f0 + 3.1415927f0im|0.22314355f0 - 3.1415927f0im|' -i stdlib/LinearAlgebra/test/lu.jl sed -e 's|\$Int|Int32|' -i stdlib/LinearAlgebra/test/lu.jl @@ -103,11 +135,12 @@ USE_SYSTEM_ZLIB=1 \ USE_SYSTEM_P7ZIP=1 \ USE_SYSTEM_OPENLIBM=1 \ + LLVM_CONFIG=llvm-config-14 \ MARCH=x86-64" build() { cd $pkgname-$pkgver - make release VERBOSE=1 JLDFLAGS=${LDFLAGS} $_buildopts + make release VERBOSE=1 JLDFLAGS=${LDFLAGS} $_buildopts -j1 } check() { Modified: julia-hardcoded-libs.patch =================================================================== --- julia-hardcoded-libs.patch 2023-01-07 13:39:57 UTC (rev 1381672) +++ julia-hardcoded-libs.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -24,7 +24,7 @@ const libLLVM = "@rpath/libLLVM.dylib" else - const libLLVM = "libLLVM-13jl.so" -+ const libLLVM = "libLLVM.so" ++ const libLLVM = "libLLVM-14.so" end function __init__() Deleted: julia-llvm-14.patch =================================================================== --- julia-llvm-14.patch 2023-01-07 13:39:57 UTC (rev 1381672) +++ julia-llvm-14.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -1,14 +0,0 @@ -diff --git a/src/codegen.cpp b/src/codegen.cpp -index ba933b60e554d..18e95fc169c8d 100644 ---- a/src/codegen.cpp -+++ b/src/codegen.cpp -@@ -4659,7 +4659,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval) - jl_cgval_t jlcall_ptr = mark_julia_type(ctx, F, false, jl_voidpointer_type); - jl_cgval_t world_age = mark_julia_type(ctx, - tbaa_decorate(ctx.tbaa().tbaa_gcframe, -- ctx.builder.CreateAlignedLoad(ctx.world_age_field, Align(sizeof(size_t)))), -+ ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ctx.world_age_field, Align(sizeof(size_t)))), - false, - jl_long_type); - jl_cgval_t fptr(ctx.builder.getContext()); - Added: julia-llvm-15.patch =================================================================== --- julia-llvm-15.patch (rev 0) +++ julia-llvm-15.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,31 @@ +diff --git a/src/jitlayers.h b/src/jitlayers.h +index c4a89f882bea..54a76630330f 100644 +--- a/src/jitlayers.h ++++ b/src/jitlayers.h +@@ -13,8 +13,14 @@ + #include <llvm/ExecutionEngine/Orc/IRTransformLayer.h> + #include <llvm/ExecutionEngine/JITEventListener.h> + ++#include <llvm/Passes/PassBuilder.h> ++#include <llvm/Passes/PassPlugin.h> ++#include <llvm/Passes/StandardInstrumentations.h> ++ + #include <llvm/Target/TargetMachine.h> + #include "julia_assert.h" ++#include "julia.h" ++#include "platform.h" + #include "debug-registry.h" + + // As of LLVM 13, there are two runtime JIT linker implementations, the older +diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp +index 5d7b86f067..7ca8767cc2 100644 +--- a/src/llvm-simdloop.cpp ++++ b/src/llvm-simdloop.cpp +@@ -20,6 +20,7 @@ + #include <llvm-c/Core.h> + #include <llvm-c/Types.h> + ++#include <llvm/Analysis/LoopInfo.h> + #include <llvm/Analysis/LoopPass.h> + #include <llvm/IR/LegacyPassManager.h> + #include <llvm/IR/Instructions.h> Added: julia-mpfr-4.2.patch =================================================================== --- julia-mpfr-4.2.patch (rev 0) +++ julia-mpfr-4.2.patch 2023-01-07 14:01:32 UTC (rev 1381673) @@ -0,0 +1,22 @@ +From 1a7fa99aac7373d7f1d4355b46656cdf898a1353 Mon Sep 17 00:00:00 2001 +From: Simon Byrne <[email protected]> +Date: Fri, 6 Jan 2023 17:42:59 -0800 +Subject: [PATCH] fix printing + +--- + base/mpfr.jl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/mpfr.jl b/base/mpfr.jl +index 45a518776989..69b6d104c065 100644 +--- a/base/mpfr.jl ++++ b/base/mpfr.jl +@@ -1080,7 +1080,7 @@ function _string(x::BigFloat, fmt::String)::String + isfinite(x) || return string(Float64(x)) + _prettify_bigfloat(string_mpfr(x, fmt)) + end +-_string(x::BigFloat) = _string(x, "%.Re") ++_string(x::BigFloat) = _string(x, "%Re") + _string(x::BigFloat, k::Integer) = _string(x, "%.$(k)Re") + + string(b::BigFloat) = _string(b)
