diff --git a/src/codegen.cpp b/src/codegen.cpp index ba583799e1c975..a4ec1e32eef732 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5169,7 +5169,21 @@ static Function* gen_cfun_wrapper( // add nest parameter (pointer to jl_value_t* data array) after sret arg assert(closure_types); std::vector fargt_sig(sig.fargt_sig); + fargt_sig.insert(fargt_sig.begin() + sig.sret, T_pprjlvalue); + // Shift LLVM attributes for parameters one to the right, as we are adding the extra nest parameter + // after sret arg. + if (attributes.getNumAttrSets() > static_cast(1 + sig.sret)) { + AttrBuilder toShift; + for (auto it = attributes.index_begin() + 1 + sig.sret; it != attributes.index_end(); ++it) { + AttrBuilder toShiftTemp(attributes.getAttributes(it)); + attributes = attributes.removeAttributes(jl_LLVMContext, it); + attributes = attributes.addAttributes(jl_LLVMContext, it, toShift); + toShift = std::move(toShiftTemp); + } + attributes = attributes.addAttributes(jl_LLVMContext, attributes.index_end(), toShift); + } + functype = FunctionType::get(sig.sret ? T_void : sig.prt, fargt_sig, /*isVa*/false); attributes = attributes.addAttribute(jl_LLVMContext, 1 + sig.sret, Attribute::Nest); } diff --git a/test/ccall.jl b/test/ccall.jl index 02d005108459e7..01f0f4f651aa8a 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -982,6 +982,26 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64), end end + +#issue 40164 +@testset "llvm parameter attributes on cfunction closures" begin + struct Struct40164 + x::Cdouble + y::Cdouble + z::Cdouble + end + + function test_40164() + ret = Struct40164[] + f = x::Struct40164 -> (push!(ret, x); nothing) + f_c = @cfunction($f, Cvoid, (Struct40164,)) + ccall(f_c.ptr, Ptr{Cvoid}, (Struct40164,), Struct40164(0, 1, 2)) + ret + end + + @test test_40164() == [Struct40164(0, 1, 2)] +end + else @test_broken "cfunction: no support for closures on this platform"