From 4cd54af6c10b214be6876a4656cb185e810b20df Mon Sep 17 00:00:00 2001 From: Troels Nielsen Date: Sun, 8 Aug 2021 13:15:46 +0200 Subject: [PATCH] Parameter attributes on Cfunction closures sticks When CFunction closures are created an extra argument is added to the function signature for holding the closure. Make sure that the parameter attributes on already existing parameters are not shifted when adding that parameter. --- src/codegen.cpp | 14 ++++++++++++++ test/ccall.jl | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) 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"