aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SjLjEHPrepare.cpp
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2010-06-01 18:04:09 +0000
committerJim Grosbach <grosbach@apple.com>2010-06-01 18:04:09 +0000
commitdc58b25ebc4d6b79f36db09a0b718ca957a610eb (patch)
treeba951854bdb57ac67dfb704780ee4005d6d75517 /lib/CodeGen/SjLjEHPrepare.cpp
parent601f9d6c03d23725a3bdc9e62d738f30bf94f9be (diff)
downloadexternal_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.cpp37
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.