Skip to content

Commit 535d59b

Browse files
troelsLilithHafner
authored andcommitted
codegen: parameter attributes on CFunction closures sticks (JuliaLang#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.
1 parent 780e54b commit 535d59b

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
@@ -5180,9 +5180,48 @@ static Function* gen_cfun_wrapper(
51805180
// add nest parameter (pointer to jl_value_t* data array) after sret arg
51815181
assert(closure_types);
51825182
std::vector<Type*> fargt_sig(sig.fargt_sig);
5183+
51835184
fargt_sig.insert(fargt_sig.begin() + sig.sret, T_pprjlvalue);
5185+
5186+
// Shift LLVM attributes for parameters one to the right, as
5187+
// we are adding the extra nest parameter after sret arg.
5188+
std::vector<std::pair<unsigned, AttributeSet>> newAttributes;
5189+
newAttributes.reserve(attributes.getNumAttrSets() + 1);
5190+
auto it = attributes.index_begin();
5191+
5192+
// Skip past FunctionIndex
5193+
if (it == AttributeList::AttrIndex::FunctionIndex) {
5194+
++it;
5195+
}
5196+
5197+
// Move past ReturnValue and parameter return value
5198+
for (;it < AttributeList::AttrIndex::FirstArgIndex + sig.sret; ++it) {
5199+
if (attributes.hasAttributes(it)) {
5200+
newAttributes.emplace_back(it, attributes.getAttributes(it));
5201+
}
5202+
}
5203+
5204+
// Add the new nest attribute
5205+
AttrBuilder attrBuilder;
5206+
attrBuilder.addAttribute(Attribute::Nest);
5207+
newAttributes.emplace_back(it, AttributeSet::get(jl_LLVMContext, attrBuilder));
5208+
5209+
// Shift forward the rest of the attributes
5210+
for(;it < attributes.index_end(); ++it) {
5211+
if (attributes.hasAttributes(it)) {
5212+
newAttributes.emplace_back(it + 1, attributes.getAttributes(it));
5213+
}
5214+
}
5215+
5216+
// Remember to add back FunctionIndex
5217+
if (attributes.hasAttributes(AttributeList::AttrIndex::FunctionIndex)) {
5218+
newAttributes.emplace_back(AttributeList::AttrIndex::FunctionIndex,
5219+
attributes.getAttributes(AttributeList::AttrIndex::FunctionIndex));
5220+
}
5221+
5222+
// Create the new AttributeList
5223+
attributes = AttributeList::get(jl_LLVMContext, newAttributes);
51845224
functype = FunctionType::get(sig.sret ? T_void : sig.prt, fargt_sig, /*isVa*/false);
5185-
attributes = attributes.addAttribute(jl_LLVMContext, 1 + sig.sret, Attribute::Nest);
51865225
}
51875226
else {
51885227
functype = sig.functype();

test/ccall.jl

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

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

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

0 commit comments

Comments
 (0)