From 5958d91c4a6ed46657f9dbc33342fc1e9aacaf37 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 744d29629b0ca..105c8f9048f3b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5180,7 +5180,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 02d005108459e..01f0f4f651aa8 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"