diff options
author | Jim Grosbach <grosbach@apple.com> | 2010-06-01 18:04:09 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2010-06-01 18:04:09 +0000 |
commit | dc58b25ebc4d6b79f36db09a0b718ca957a610eb (patch) | |
tree | ba951854bdb57ac67dfb704780ee4005d6d75517 /lib/CodeGen/SjLjEHPrepare.cpp | |
parent | 601f9d6c03d23725a3bdc9e62d738f30bf94f9be (diff) | |
download | external_llvm-dc58b25ebc4d6b79f36db09a0b718ca957a610eb.zip external_llvm-dc58b25ebc4d6b79f36db09a0b718ca957a610eb.tar.gz external_llvm-dc58b25ebc4d6b79f36db09a0b718ca957a610eb.tar.bz2 |
When processing function arguments when splitting live ranges across invokes,
handle structs passed by value via an extract/insert pair, as a bitcast
won't work on a struct. rdar://7742824
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105280 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SjLjEHPrepare.cpp')
-rw-r--r-- | lib/CodeGen/SjLjEHPrepare.cpp | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp index ce50568..e94d4d3 100644 --- a/lib/CodeGen/SjLjEHPrepare.cpp +++ b/lib/CodeGen/SjLjEHPrepare.cpp @@ -202,16 +202,33 @@ splitLiveRangesLiveAcrossInvokes(SmallVector<InvokeInst*,16> &Invokes) { ++AfterAllocaInsertPt; for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { - // This is always a no-op cast because we're casting AI to AI->getType() so - // src and destination types are identical. BitCast is the only possibility. - CastInst *NC = new BitCastInst( - AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); - AI->replaceAllUsesWith(NC); - // Normally its is forbidden to replace a CastInst's operand because it - // could cause the opcode to reflect an illegal conversion. However, we're - // replacing it here with the same value it was constructed with to simply - // make NC its user. - NC->setOperand(0, AI); + const Type *Ty = AI->getType(); + // StructType can't be cast, but is a legal argument type, so we have + // to handle them differently. We use an extract/insert pair as a + // lightweight method to achieve the same goal. + if (isa<StructType>(Ty)) { + Instruction *EI = ExtractValueInst::Create(AI, 0, "", AfterAllocaInsertPt); + Instruction *NI = InsertValueInst::Create(AI, EI, 0); + NI->insertAfter(EI); + AI->replaceAllUsesWith(NI); + // Set the struct operand of the instructions back to the AllocaInst. + EI->setOperand(0, AI); + NI->setOperand(0, AI); + } else { + // This is always a no-op cast because we're casting AI to AI->getType() + // so src and destination types are identical. BitCast is the only + // possibility. + CastInst *NC = new BitCastInst( + AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); + AI->replaceAllUsesWith(NC); + // Set the operand of the cast instruction back to the AllocaInst. + // Normally it's forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, + // we're replacing it here with the same value it was constructed with. + // We do this because the above replaceAllUsesWith() clobbered the + // operand, but we want this one to remain. + NC->setOperand(0, AI); + } } // Finally, scan the code looking for instructions with bad live ranges. |