mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-16 14:31:59 +00:00
Fix arg promotion to propagate the correct attrs on the calls to
promoted functions. This is important for varargs calls in particular. Thanks to duncan for providing a great testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46108 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
644340a9bd
commit
ab04e13a1f
@ -404,9 +404,9 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
ParamAttrsVector ParamAttrsVec;
|
||||
const ParamAttrsList *PAL = F->getParamAttrs();
|
||||
|
||||
unsigned index = 1;
|
||||
unsigned ArgIndex = 1;
|
||||
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
|
||||
++I, ++index) {
|
||||
++I, ++ArgIndex) {
|
||||
if (ByValArgsToTransform.count(I)) {
|
||||
// Just add all the struct element types.
|
||||
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
|
||||
@ -416,7 +416,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
++NumByValArgsPromoted;
|
||||
} else if (!ArgsToPromote.count(I)) {
|
||||
Params.push_back(I->getType());
|
||||
if (unsigned attrs = PAL ? PAL->getParamAttrs(index) : 0)
|
||||
if (unsigned attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
|
||||
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), attrs));
|
||||
} else if (I->use_empty()) {
|
||||
++NumArgumentsDead;
|
||||
@ -454,10 +454,6 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
|
||||
const Type *RetTy = FTy->getReturnType();
|
||||
|
||||
// Recompute the parameter attributes list based on the new arguments for
|
||||
// the function.
|
||||
PAL = ParamAttrsList::get(ParamAttrsVec);
|
||||
|
||||
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
|
||||
// have zero fixed arguments.
|
||||
bool ExtraArgHack = false;
|
||||
@ -472,7 +468,12 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
// Create the new function body and insert it into the module...
|
||||
Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
|
||||
NF->setCallingConv(F->getCallingConv());
|
||||
NF->setParamAttrs(PAL);
|
||||
|
||||
// Recompute the parameter attributes list based on the new arguments for
|
||||
// the function.
|
||||
NF->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
|
||||
ParamAttrsVec.clear(); PAL = 0;
|
||||
|
||||
if (F->hasCollector())
|
||||
NF->setCollector(F->getCollector());
|
||||
F->getParent()->getFunctionList().insert(F, NF);
|
||||
@ -484,18 +485,24 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
// Loop over all of the callers of the function, transforming the call sites
|
||||
// to pass in the loaded pointers.
|
||||
//
|
||||
std::vector<Value*> Args;
|
||||
SmallVector<Value*, 16> Args;
|
||||
while (!F->use_empty()) {
|
||||
CallSite CS = CallSite::get(F->use_back());
|
||||
Instruction *Call = CS.getInstruction();
|
||||
|
||||
PAL = CS.getParamAttrs();
|
||||
|
||||
// Loop over the operands, inserting GEP and loads in the caller as
|
||||
// appropriate.
|
||||
CallSite::arg_iterator AI = CS.arg_begin();
|
||||
ArgIndex = 1;
|
||||
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
|
||||
I != E; ++I, ++AI)
|
||||
I != E; ++I, ++AI, ++ArgIndex)
|
||||
if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
|
||||
Args.push_back(*AI); // Unmodified argument
|
||||
|
||||
if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
|
||||
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
|
||||
|
||||
} else if (ByValArgsToTransform.count(I)) {
|
||||
// Emit a GEP and load for each element of the struct.
|
||||
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
|
||||
@ -530,23 +537,27 @@ Function *ArgPromotion::DoPromotion(Function *F,
|
||||
Args.push_back(Constant::getNullValue(Type::Int32Ty));
|
||||
|
||||
// Push any varargs arguments on the list
|
||||
for (; AI != CS.arg_end(); ++AI)
|
||||
for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
|
||||
Args.push_back(*AI);
|
||||
if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
|
||||
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
|
||||
}
|
||||
|
||||
Instruction *New;
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
|
||||
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
|
||||
Args.begin(), Args.end(), "", Call);
|
||||
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
|
||||
cast<InvokeInst>(New)->setParamAttrs(PAL);
|
||||
cast<InvokeInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
|
||||
} else {
|
||||
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
|
||||
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
|
||||
cast<CallInst>(New)->setParamAttrs(PAL);
|
||||
cast<CallInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
|
||||
if (cast<CallInst>(Call)->isTailCall())
|
||||
cast<CallInst>(New)->setTailCall();
|
||||
}
|
||||
Args.clear();
|
||||
ParamAttrsVec.clear();
|
||||
|
||||
// Update the alias analysis implementation to know that we are replacing
|
||||
// the old call with a new one.
|
||||
|
25
test/Transforms/ArgumentPromotion/attrs.ll
Normal file
25
test/Transforms/ArgumentPromotion/attrs.ll
Normal file
@ -0,0 +1,25 @@
|
||||
; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep zeroext
|
||||
|
||||
%struct.ss = type { i32, i64 }
|
||||
|
||||
define internal void @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind {
|
||||
entry:
|
||||
%tmp = getelementptr %struct.ss* %b, i32 0, i32 0
|
||||
%tmp1 = load i32* %tmp, align 4
|
||||
%tmp2 = add i32 %tmp1, 1
|
||||
store i32 %tmp2, i32* %tmp, align 4
|
||||
|
||||
store i32 0, i32* %X
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @test(i32* %X) {
|
||||
entry:
|
||||
%S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
|
||||
%tmp1 = getelementptr %struct.ss* %S, i32 0, i32 0 ; <i32*> [#uses=1]
|
||||
store i32 1, i32* %tmp1, align 8
|
||||
%tmp4 = getelementptr %struct.ss* %S, i32 0, i32 1 ; <i64*> [#uses=1]
|
||||
store i64 2, i64* %tmp4, align 4
|
||||
call void @f( %struct.ss* byval %S, i32* byval %X, i32 zeroext 0)
|
||||
ret i32 0
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user