mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Fix DeleteDeadVarargs not to crash on functions referenced by BlockAddresses
This pass was assuming that if hasAddressTaken() returns false for a function, the function's only uses are call sites. That's not true because there can be references by BlockAddresses too. Fix the pass to handle this case. Fix BlockAddress::replaceUsesOfWithOnConstant() to allow a function's type to be changed by RAUW'ing the function with a bitcast of the recreated function. Patch by Mark Seaborn. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183933 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6585b388cb
commit
c06e5cf2e3
@ -1389,7 +1389,7 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
|
|||||||
BasicBlock *NewBB = getBasicBlock();
|
BasicBlock *NewBB = getBasicBlock();
|
||||||
|
|
||||||
if (U == &Op<0>())
|
if (U == &Op<0>())
|
||||||
NewF = cast<Function>(To);
|
NewF = cast<Function>(To->stripPointerCasts());
|
||||||
else
|
else
|
||||||
NewBB = cast<BasicBlock>(To);
|
NewBB = cast<BasicBlock>(To);
|
||||||
|
|
||||||
|
@ -263,8 +263,10 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
|
|||||||
// to pass in a smaller number of arguments into the new function.
|
// to pass in a smaller number of arguments into the new function.
|
||||||
//
|
//
|
||||||
std::vector<Value*> Args;
|
std::vector<Value*> Args;
|
||||||
while (!Fn.use_empty()) {
|
for (Value::use_iterator I = Fn.use_begin(), E = Fn.use_end(); I != E; ) {
|
||||||
CallSite CS(Fn.use_back());
|
CallSite CS(*I++);
|
||||||
|
if (!CS)
|
||||||
|
continue;
|
||||||
Instruction *Call = CS.getInstruction();
|
Instruction *Call = CS.getInstruction();
|
||||||
|
|
||||||
// Pass all the same arguments.
|
// Pass all the same arguments.
|
||||||
@ -330,6 +332,11 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
|
|||||||
if (DI != FunctionDIs.end())
|
if (DI != FunctionDIs.end())
|
||||||
DI->second.replaceFunction(NF);
|
DI->second.replaceFunction(NF);
|
||||||
|
|
||||||
|
// Fix up any BlockAddresses that refer to the function.
|
||||||
|
Fn.replaceAllUsesWith(ConstantExpr::getBitCast(NF, Fn.getType()));
|
||||||
|
// Delete the bitcast that we just created, so that NF does not
|
||||||
|
// appear to be address-taken.
|
||||||
|
NF->removeDeadConstantUsers();
|
||||||
// Finally, nuke the old function.
|
// Finally, nuke the old function.
|
||||||
Fn.eraseFromParent();
|
Fn.eraseFromParent();
|
||||||
return true;
|
return true;
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
; RUN: opt %s -deadargelim -S | FileCheck %s
|
||||||
|
|
||||||
|
|
||||||
|
@block_addr = global i8* blockaddress(@varargs_func, %l1)
|
||||||
|
; CHECK: @block_addr = global i8* blockaddress(@varargs_func, %l1)
|
||||||
|
|
||||||
|
|
||||||
|
; This function is referenced by a "blockaddress" constant but it is
|
||||||
|
; not address-taken, so the pass should be able to remove its unused
|
||||||
|
; varargs.
|
||||||
|
|
||||||
|
define internal i32 @varargs_func(i8* %addr, ...) {
|
||||||
|
indirectbr i8* %addr, [ label %l1, label %l2 ]
|
||||||
|
l1:
|
||||||
|
ret i32 1
|
||||||
|
l2:
|
||||||
|
ret i32 2
|
||||||
|
}
|
||||||
|
; CHECK: define internal i32 @varargs_func(i8* %addr) {
|
||||||
|
|
||||||
|
define i32 @caller(i8* %addr) {
|
||||||
|
%r = call i32 (i8*, ...)* @varargs_func(i8* %addr)
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
; CHECK: %r = call i32 @varargs_func(i8* %addr)
|
Loading…
Reference in New Issue
Block a user