Skip to content

Commit 390450d

Browse files
troelsKristofferC
authored andcommitted
codegen: parameter attributes on CFunction closures sticks (#41827)
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. (cherry picked from commit 08f3422)
1 parent 2a59c4b commit 390450d

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/codegen.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4826,9 +4826,48 @@ static Function* gen_cfun_wrapper(
48264826
// add nest parameter (pointer to jl_value_t* data array) after sret arg
48274827
assert(closure_types);
48284828
std::vector<Type*> fargt_sig(sig.fargt_sig);
4829+
48294830
fargt_sig.insert(fargt_sig.begin() + sig.sret, T_pprjlvalue);
4831+
4832+
// Shift LLVM attributes for parameters one to the right, as
4833+
// we are adding the extra nest parameter after sret arg.
4834+
std::vector<std::pair<unsigned, AttributeSet>> newAttributes;
4835+
newAttributes.reserve(attributes.getNumAttrSets() + 1);
4836+
auto it = attributes.index_begin();
4837+
4838+
// Skip past FunctionIndex
4839+
if (it == AttributeList::AttrIndex::FunctionIndex) {
4840+
++it;
4841+
}
4842+
4843+
// Move past ReturnValue and parameter return value
4844+
for (;it < AttributeList::AttrIndex::FirstArgIndex + sig.sret; ++it) {
4845+
if (attributes.hasAttributes(it)) {
4846+
newAttributes.emplace_back(it, attributes.getAttributes(it));
4847+
}
4848+
}
4849+
4850+
// Add the new nest attribute
4851+
AttrBuilder attrBuilder;
4852+
attrBuilder.addAttribute(Attribute::Nest);
4853+
newAttributes.emplace_back(it, AttributeSet::get(jl_LLVMContext, attrBuilder));
4854+
4855+
// Shift forward the rest of the attributes
4856+
for(;it < attributes.index_end(); ++it) {
4857+
if (attributes.hasAttributes(it)) {
4858+
newAttributes.emplace_back(it + 1, attributes.getAttributes(it));
4859+
}
4860+
}
4861+
4862+
// Remember to add back FunctionIndex
4863+
if (attributes.hasAttributes(AttributeList::AttrIndex::FunctionIndex)) {
4864+
newAttributes.emplace_back(AttributeList::AttrIndex::FunctionIndex,
4865+
attributes.getAttributes(AttributeList::AttrIndex::FunctionIndex));
4866+
}
4867+
4868+
// Create the new AttributeList
4869+
attributes = AttributeList::get(jl_LLVMContext, newAttributes);
48304870
functype = FunctionType::get(sig.sret ? T_void : sig.prt, fargt_sig, /*isVa*/false);
4831-
attributes = attributes.addAttribute(jl_LLVMContext, 1 + sig.sret, Attribute::Nest);
48324871
}
48334872
else {
48344873
functype = sig.functype();

test/ccall.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,26 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64),
979979
end
980980
end
981981

982+
983+
#issue 40164
984+
@testset "llvm parameter attributes on cfunction closures" begin
985+
struct Struct40164
986+
x::Cdouble
987+
y::Cdouble
988+
z::Cdouble
989+
end
990+
991+
function test_40164()
992+
ret = Struct40164[]
993+
f = x::Struct40164 -> (push!(ret, x); nothing)
994+
f_c = @cfunction($f, Cvoid, (Struct40164,))
995+
ccall(f_c.ptr, Ptr{Cvoid}, (Struct40164,), Struct40164(0, 1, 2))
996+
ret
997+
end
998+
999+
@test test_40164() == [Struct40164(0, 1, 2)]
1000+
end
1001+
9821002
else
9831003

9841004
@test_broken "cfunction: no support for closures on this platform"

0 commit comments

Comments
 (0)