From d1305128dc3c0c27489a161ac66119d6f0ee8bfe 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 | 17 +++++++++++++++++ test/ccall.jl | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index d05080ee4216e9..73d2a28fa37f15 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5170,7 +5170,24 @@ 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. + // AttributeList has function attributes and return value + // attributes before the parameter attributes. + if (attributes.getNumAttrSets() > static_cast(2 + sig.sret)) { + AttrBuilder toShift; + // Skip past function and return and sret attributes to the first real parameter + for (auto it = attributes.index_begin() + 2 + 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"