forked from OSchip/llvm-project
[InlineFunction] Preserve attributes when forwarding VarArgs.
Reviewers: rnk, efriedma Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D41555 llvm-svn: 321942
This commit is contained in:
parent
0b93cd7351
commit
de10e6e064
|
@ -1811,9 +1811,12 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
|||
}
|
||||
|
||||
SmallVector<Value*,4> VarArgsToForward;
|
||||
SmallVector<AttributeSet, 4> VarArgsAttrs;
|
||||
for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
|
||||
i < CS.getNumArgOperands(); i++)
|
||||
i < CS.getNumArgOperands(); i++) {
|
||||
VarArgsToForward.push_back(CS.getArgOperand(i));
|
||||
VarArgsAttrs.push_back(CS.getAttributes().getParamAttributes(i));
|
||||
}
|
||||
|
||||
bool InlinedMustTailCalls = false, InlinedDeoptimizeCalls = false;
|
||||
if (InlinedFunctionInfo.ContainsCalls) {
|
||||
|
@ -1835,15 +1838,31 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
|||
((ForwardVarArgsTo &&
|
||||
CI->getCalledFunction() == ForwardVarArgsTo) ||
|
||||
CI->isMustTailCall())) {
|
||||
// Collect attributes for non-vararg parameters.
|
||||
AttributeList Attrs = CI->getAttributes();
|
||||
SmallVector<AttributeSet, 8> ArgAttrs;
|
||||
if (!Attrs.isEmpty()) {
|
||||
for (unsigned ArgNo = 0;
|
||||
ArgNo < CI->getFunctionType()->getNumParams(); ++ArgNo)
|
||||
ArgAttrs.push_back(Attrs.getParamAttributes(ArgNo));
|
||||
}
|
||||
|
||||
// Add VarArg attributes.
|
||||
ArgAttrs.append(VarArgsAttrs.begin(), VarArgsAttrs.end());
|
||||
Attrs = AttributeList::get(CI->getContext(), Attrs.getFnAttributes(),
|
||||
Attrs.getRetAttributes(), ArgAttrs);
|
||||
// Add VarArgs to existing parameters.
|
||||
SmallVector<Value *, 6> Params(CI->arg_operands());
|
||||
Params.append(VarArgsToForward.begin(), VarArgsToForward.end());
|
||||
CallInst *Call =
|
||||
CallInst *NewCI =
|
||||
CallInst::Create(CI->getCalledFunction() ? CI->getCalledFunction()
|
||||
: CI->getCalledValue(),
|
||||
Params, "", CI);
|
||||
Call->setDebugLoc(CI->getDebugLoc());
|
||||
CI->replaceAllUsesWith(Call);
|
||||
NewCI->setDebugLoc(CI->getDebugLoc());
|
||||
NewCI->setAttributes(Attrs);
|
||||
CI->replaceAllUsesWith(NewCI);
|
||||
CI->eraseFromParent();
|
||||
CI = NewCI;
|
||||
}
|
||||
|
||||
if (Function *F = CI->getCalledFunction())
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
; RUN: opt < %s -passes='cgscc(inline,function(instcombine))' -S | FileCheck %s
|
||||
|
||||
declare void @ext_method(i8*, i32)
|
||||
declare void @vararg_fn(i8*, ...)
|
||||
declare signext i16 @vararg_fn(...) #0
|
||||
|
||||
define linkonce_odr void @thunk(i8* %this, ...) {
|
||||
%this_adj = getelementptr i8, i8* %this, i32 4
|
||||
musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj, ...)
|
||||
musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj, ...)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -15,21 +15,31 @@ define void @thunk_caller(i8* %p) {
|
|||
ret void
|
||||
}
|
||||
; CHECK-LABEL: define void @thunk_caller(i8* %p)
|
||||
; CHECK: call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj.i, i32 42)
|
||||
; CHECK: call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj.i, i32 42)
|
||||
|
||||
define void @test_callee_2(i8* %this, ...) {
|
||||
%this_adj = getelementptr i8, i8* %this, i32 4
|
||||
musttail call void (i8*, ...) @vararg_fn(i8* %this_adj, ...)
|
||||
define signext i16 @test_callee_2(...) {
|
||||
%res = musttail call signext i16 (...) @vararg_fn(...) #0
|
||||
ret i16 %res
|
||||
}
|
||||
|
||||
define void @test_caller_2(i8* %p, i8* %q, i16 %r) {
|
||||
call signext i16 (...) @test_callee_2(i8* %p, i8* byval %q, i16 signext %r)
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: define void @test_caller_2
|
||||
; CHECK: call signext i16 (...) @vararg_fn(i8* %p, i8* byval %q, i16 signext %r) [[FN_ATTRS:#[0-9]+]]
|
||||
|
||||
define void @test_callee_3(i8* %p, ...) {
|
||||
call signext i16 (...) @vararg_fn()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_caller_2(i8* %p) {
|
||||
call void (i8*, ...) @test_callee_2(i8* %p)
|
||||
define void @test_caller_3(i8* %p, i8* %q) {
|
||||
call void (i8*, ...) @test_callee_3(i8* nonnull %p, i8* %q)
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: define void @test_caller_2(i8* %p)
|
||||
; CHECK: call void (i8*, ...) @vararg_fn(i8* %this_adj.i)
|
||||
|
||||
; CHECK-LABEL: define void @test_caller_3
|
||||
; CHECK: call signext i16 (...) @vararg_fn()
|
||||
|
||||
define internal i32 @varg_accessed(...) {
|
||||
entry:
|
||||
|
@ -50,3 +60,6 @@ define i32 @call_vargs() {
|
|||
|
||||
declare void @llvm.va_start(i8*)
|
||||
declare void @llvm.va_end(i8*)
|
||||
|
||||
; CHECK: attributes [[FN_ATTRS]] = { "foo"="bar" }
|
||||
attributes #0 = { "foo"="bar" }
|
||||
|
|
Loading…
Reference in New Issue