diff --git a/src/codegen.cpp b/src/codegen.cpp index 73d2a28fa37f1..2ebe38d8c8258 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5172,24 +5172,41 @@ static Function* gen_cfun_wrapper( 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); + std::vector> newAttributes; + newAttributes.reserve(attributes.getNumAttrSets() + 1); + auto it = attributes.index_begin(); + + // Skip past non-parameter attributes (and perhaps parameter return) + // Beware that function index is ~0U, so can't just replace with < + for (;it != attributes.index_end(); ++it) { + if (it != AttributeList::AttrIndex::FunctionIndex && + it >= AttributeList::AttrIndex::FirstArgIndex + sig.sret) { + break; } - attributes = attributes.addAttributes(jl_LLVMContext, attributes.index_end(), toShift); + newAttributes.push_back(std::make_pair(it, attributes.getAttributes(it))); + } + + // Skip ahead to first parameter (where we may already be, but aren't necessarily) + it = AttributeList::AttrIndex::FirstArgIndex + sig.sret; + + // Add the new nest attribute + AttrBuilder attrBuilder; + attrBuilder.addAttribute(Attribute::Nest); + AttributeSet set(AttributeSet::get(jl_LLVMContext, attrBuilder)); + newAttributes.push_back(std::make_pair(it, set)); + + // Shift forward the rest of the attributes + // We are now past the magic numbers, so < is ok here. + for(;it < attributes.index_end(); ++it) { + newAttributes.push_back(std::make_pair(it + 1, attributes.getAttributes(it))); } + // Create the new AttributeList + attributes = AttributeList::get(jl_LLVMContext, newAttributes); functype = FunctionType::get(sig.sret ? T_void : sig.prt, fargt_sig, /*isVa*/false); - attributes = attributes.addAttribute(jl_LLVMContext, 1 + sig.sret, Attribute::Nest); } else { functype = sig.functype();