//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sjljehprepare"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/IRBuilder.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include <set>
using namespace llvm;
namespace {
class SjLjEHPrepare : public FunctionPass {
const TargetLowering *TLI;
-
Type *FunctionContextTy;
Constant *RegisterFn;
Constant *UnregisterFn;
public:
static char ID; // Pass identification, replacement for typeid
explicit SjLjEHPrepare(const TargetLowering *tli = NULL)
- : FunctionPass(ID), TLI(tli) {}
+ : FunctionPass(ID), TLI(tli) { }
bool doInitialization(Module &M);
bool runOnFunction(Function &F);
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- FunctionPass::getAnalysisUsage(AU);
- }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {}
const char *getPassName() const {
return "SJLJ Exception Handling preparation";
}
Builder.CreateStore(CallSiteNoC, CallSite, true/*volatile*/);
}
-/// markBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until
+/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until
/// we reach blocks we've already seen.
-static void markBlocksLiveIn(BasicBlock *BB, Instruction *Inst,
- SmallPtrSet<BasicBlock*, 64> &LiveBBs,
- SmallPtrSet<BasicBlock*, 4> &InvokesCrossed,
- bool &FoundDef) {
- if (!LiveBBs.insert(BB)) return; // Already been here.
- if (BB == Inst->getParent()) {
- FoundDef = true;
- return;
- }
+static void MarkBlocksLiveIn(BasicBlock *BB,
+ SmallPtrSet<BasicBlock*, 64> &LiveBBs) {
+ if (!LiveBBs.insert(BB)) return; // already been here.
- for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
- BasicBlock *Pred = *PI;
- if (BB->isLandingPad() && BB != Inst->getParent()) {
- InvokesCrossed.insert(Pred);
- continue;
- }
- markBlocksLiveIn(Pred, Inst, LiveBBs, InvokesCrossed, FoundDef);
- }
+ for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+ MarkBlocksLiveIn(*PI, LiveBBs);
}
/// substituteLPadValues - Substitute the values returned by the landingpad
// that needs to be restored on all exits from the function. This is an alloca
// because the value needs to be added to the global context list.
unsigned Align =
- TLI->getTargetData()->getPrefTypeAlignment(FunctionContextTy);
+ TLI->getDataLayout()->getPrefTypeAlignment(FunctionContextTy);
FuncCtx =
new AllocaInst(FunctionContextTy, 0, Align, "fn_context", EntryBB->begin());
// Fill in the function context structure.
- Type *Int32Ty = Type::getInt32Ty(F.getContext());
- Value *Zero = ConstantInt::get(Int32Ty, 0);
- Value *One = ConstantInt::get(Int32Ty, 1);
- Value *Two = ConstantInt::get(Int32Ty, 2);
- Value *Three = ConstantInt::get(Int32Ty, 3);
- Value *Four = ConstantInt::get(Int32Ty, 4);
-
- Value *Idxs[2] = { Zero, 0 };
-
for (unsigned I = 0, E = LPads.size(); I != E; ++I) {
LandingPadInst *LPI = LPads[I];
IRBuilder<> Builder(LPI->getParent()->getFirstInsertionPt());
// Reference the __data field.
- Idxs[1] = Two;
- Value *FCData = Builder.CreateGEP(FuncCtx, Idxs, "__data");
+ Value *FCData = Builder.CreateConstGEP2_32(FuncCtx, 0, 2, "__data");
// The exception values come back in context->__data[0].
- Idxs[1] = Zero;
- Value *ExceptionAddr = Builder.CreateGEP(FCData, Idxs, "exception_gep");
+ Value *ExceptionAddr = Builder.CreateConstGEP2_32(FCData, 0, 0,
+ "exception_gep");
Value *ExnVal = Builder.CreateLoad(ExceptionAddr, true, "exn_val");
- ExnVal = Builder.CreateIntToPtr(ExnVal, Type::getInt8PtrTy(F.getContext()));
+ ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getInt8PtrTy());
- Idxs[1] = One;
- Value *SelectorAddr = Builder.CreateGEP(FCData, Idxs, "exn_selector_gep");
+ Value *SelectorAddr = Builder.CreateConstGEP2_32(FCData, 0, 1,
+ "exn_selector_gep");
Value *SelVal = Builder.CreateLoad(SelectorAddr, true, "exn_selector_val");
substituteLPadValues(LPI, ExnVal, SelVal);
}
// Personality function
- Idxs[1] = Three;
+ IRBuilder<> Builder(EntryBB->getTerminator());
if (!PersonalityFn)
PersonalityFn = LPads[0]->getPersonalityFn();
- Value *PersonalityFieldPtr =
- GetElementPtrInst::Create(FuncCtx, Idxs, "pers_fn_gep",
- EntryBB->getTerminator());
- new StoreInst(PersonalityFn, PersonalityFieldPtr, true,
- EntryBB->getTerminator());
+ Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 3,
+ "pers_fn_gep");
+ Builder.CreateStore(PersonalityFn, PersonalityFieldPtr, /*isVolatile=*/true);
// LSDA address
- Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr",
- EntryBB->getTerminator());
- Idxs[1] = Four;
- Value *LSDAFieldPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "lsda_gep",
- EntryBB->getTerminator());
- new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator());
+ Value *LSDA = Builder.CreateCall(LSDAAddrFn, "lsda_addr");
+ Value *LSDAFieldPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 4, "lsda_gep");
+ Builder.CreateStore(LSDA, LSDAFieldPtr, /*isVolatile=*/true);
return FuncCtx;
}
/// edge and spill them.
void SjLjEHPrepare::lowerAcrossUnwindEdges(Function &F,
ArrayRef<InvokeInst*> Invokes) {
- SmallVector<std::pair<Instruction*, Instruction*>, 32> ReloadUsers;
- DenseMap<std::pair<Instruction*, Instruction*>, AllocaInst*> AllocaMap;
-
// Finally, scan the code looking for instructions with bad live ranges.
for (Function::iterator
BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) {
}
// Find all of the blocks that this value is live in.
- std::map<Instruction*, SmallPtrSet<BasicBlock*, 4> > InvokesCrossed;
- std::map<Instruction*, SmallPtrSet<BasicBlock*, 64> > LiveBBs;
- bool FoundDef = false;
+ SmallPtrSet<BasicBlock*, 64> LiveBBs;
+ LiveBBs.insert(Inst->getParent());
while (!Users.empty()) {
- Instruction *U = Users.pop_back_val();
+ Instruction *U = Users.back();
+ Users.pop_back();
- if (PHINode *PN = dyn_cast<PHINode>(U)) {
+ if (!isa<PHINode>(U)) {
+ MarkBlocksLiveIn(U->getParent(), LiveBBs);
+ } else {
// Uses for a PHI node occur in their predecessor block.
+ PHINode *PN = cast<PHINode>(U);
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (PN->getIncomingValue(i) == Inst)
- markBlocksLiveIn(PN->getIncomingBlock(i), Inst, LiveBBs[U],
- InvokesCrossed[U], FoundDef);
- } else {
- markBlocksLiveIn(U->getParent(), Inst, LiveBBs[U],
- InvokesCrossed[U], FoundDef);
+ MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs);
}
}
- // If we hit the definition, resort to the dump-this-value-everywhere
- // method.
- if (FoundDef) {
- // Now that we know all of the blocks that this thing is live in, see if
- // it includes any of the unwind locations.
- bool NeedsSpill = false;
- for (unsigned i = 0, e = Invokes.size(); i != e; ++i) {
- BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest();
- if (UnwindBlock == BB) continue;
-
- for (std::map<Instruction*, SmallPtrSet<BasicBlock*, 64> >::iterator
- MI = LiveBBs.begin(), ME = LiveBBs.end(); MI != ME; ++MI) {
- if (MI->second.count(UnwindBlock)) {
- DEBUG({
- dbgs() << "SJLJ Spill: " << *Inst << " around "
- << UnwindBlock->getName() << "\n";
- });
- NeedsSpill = true;
- break;
- }
- }
-
- // If we decided we need a spill, do it.
- if (NeedsSpill) {
- DemoteRegToStack(*Inst, true);
- ++NumSpilled;
- }
+ // Now that we know all of the blocks that this thing is live in, see if
+ // it includes any of the unwind locations.
+ bool NeedsSpill = false;
+ for (unsigned i = 0, e = Invokes.size(); i != e; ++i) {
+ BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest();
+ if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) {
+ DEBUG(dbgs() << "SJLJ Spill: " << *Inst << " around "
+ << UnwindBlock->getName() << "\n");
+ NeedsSpill = true;
+ break;
}
-
- // We don't need this map anymore.
- InvokesCrossed.clear();
}
- // Go through the invokes the value crosses and insert a spill right
- // before the invoke.
- for (std::map<Instruction*, SmallPtrSet<BasicBlock*, 4> >::iterator
- MI = InvokesCrossed.begin(), ME = InvokesCrossed.end();
- MI != ME; ++MI) {
- Instruction *User = MI->first;
- SmallPtrSet<BasicBlock*, 4> &Crossings = MI->second;
- if (Crossings.empty()) continue;
-
- ReloadUsers.push_back(std::make_pair(Inst, User));
-
- AllocaInst *&Slot = AllocaMap[std::make_pair(Inst, User)];
- if (!Slot)
- Slot = new AllocaInst(Inst->getType(), 0,
- Inst->getName() + ".reg2mem",
- F.getEntryBlock().begin());
-
- for (SmallPtrSet<BasicBlock*, 4>::iterator
- CI = Crossings.begin(), CE = Crossings.end(); CI != CE; ++CI) {
- new StoreInst(Inst, Slot, (*CI)->getTerminator());
- ++NumSpilled;
- }
+ // If we decided we need a spill, do it.
+ // FIXME: Spilling this way is overkill, as it forces all uses of
+ // the value to be reloaded from the stack slot, even those that aren't
+ // in the unwind blocks. We should be more selective.
+ if (NeedsSpill) {
+ DemoteRegToStack(*Inst, true);
+ ++NumSpilled;
}
}
}
- // Now go through the instructions which were spilled and replace their uses
- // after a crossed invoke with a reload instruction.
- for (SmallVectorImpl<std::pair<Instruction*, Instruction*> >::iterator
- I = ReloadUsers.begin(), E = ReloadUsers.end(); I != E; ++I) {
- Instruction *User = I->second;
- AllocaInst *Slot = AllocaMap[*I];
- assert(Slot && "A spill slot hasn't been allocated yet!");
-
- if (PHINode *PN = dyn_cast<PHINode>(User)) {
- // If this is a PHI node, we can't insert a load of the value before the
- // use. Instead insert the load in the predecessor block corresponding to
- // the incoming value.
- //
- // Note that if there are multiple edges from a basic block to this PHI
- // node that we cannot have multiple loads. The problem is that the
- // resulting PHI node will have multiple values (from each load) coming in
- // from the same block, which is illegal SSA form. For this reason, we
- // keep track of and reuse loads we insert.
- DenseMap<BasicBlock*, Value*> Loads;
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
- if (PN->getIncomingValue(i) == I->first) {
- Value *&V = Loads[PN->getIncomingBlock(i)];
- if (V == 0)
- // Insert the load into the predecessor block
- V = new LoadInst(Slot, I->first->getName() + ".reload", true,
- PN->getIncomingBlock(i)->getTerminator());
-
- PN->setIncomingValue(i, V);
- }
- } else {
- LoadInst *Reload = new LoadInst(Slot, Slot->getName() + ".reload", User);
- User->replaceUsesOfWith(I->first, Reload);
- }
- }
-
// Go through the landing pads and remove any PHIs there.
for (unsigned i = 0, e = Invokes.size(); i != e; ++i) {
BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest();
Value *FuncCtx =
setupFunctionContext(F, makeArrayRef(LPads.begin(), LPads.end()));
BasicBlock *EntryBB = F.begin();
- Type *Int32Ty = Type::getInt32Ty(F.getContext());
-
- Value *Idxs[2] = {
- ConstantInt::get(Int32Ty, 0), 0
- };
+ IRBuilder<> Builder(EntryBB->getTerminator());
// Get a reference to the jump buffer.
- Idxs[1] = ConstantInt::get(Int32Ty, 5);
- Value *JBufPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "jbuf_gep",
- EntryBB->getTerminator());
+ Value *JBufPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 5, "jbuf_gep");
// Save the frame pointer.
- Idxs[1] = ConstantInt::get(Int32Ty, 0);
- Value *FramePtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep",
- EntryBB->getTerminator());
+ Value *FramePtr = Builder.CreateConstGEP2_32(JBufPtr, 0, 0, "jbuf_fp_gep");
- Value *Val = CallInst::Create(FrameAddrFn,
- ConstantInt::get(Int32Ty, 0),
- "fp",
- EntryBB->getTerminator());
- new StoreInst(Val, FramePtr, true, EntryBB->getTerminator());
+ Value *Val = Builder.CreateCall(FrameAddrFn, Builder.getInt32(0), "fp");
+ Builder.CreateStore(Val, FramePtr, /*isVolatile=*/true);
// Save the stack pointer.
- Idxs[1] = ConstantInt::get(Int32Ty, 2);
- Value *StackPtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep",
- EntryBB->getTerminator());
+ Value *StackPtr = Builder.CreateConstGEP2_32(JBufPtr, 0, 2, "jbuf_sp_gep");
- Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator());
- new StoreInst(Val, StackPtr, true, EntryBB->getTerminator());
+ Val = Builder.CreateCall(StackAddrFn, "sp");
+ Builder.CreateStore(Val, StackPtr, /*isVolatile=*/true);
// Call the setjmp instrinsic. It fills in the rest of the jmpbuf.
- Value *SetjmpArg = CastInst::Create(Instruction::BitCast, JBufPtr,
- Type::getInt8PtrTy(F.getContext()), "",
- EntryBB->getTerminator());
- CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "", EntryBB->getTerminator());
+ Value *SetjmpArg = Builder.CreateBitCast(JBufPtr, Builder.getInt8PtrTy());
+ Builder.CreateCall(BuiltinSetjmpFn, SetjmpArg);
// Store a pointer to the function context so that the back-end will know
// where to look for it.
- Value *FuncCtxArg = CastInst::Create(Instruction::BitCast, FuncCtx,
- Type::getInt8PtrTy(F.getContext()), "",
- EntryBB->getTerminator());
- CallInst::Create(FuncCtxFn, FuncCtxArg, "", EntryBB->getTerminator());
+ Value *FuncCtxArg = Builder.CreateBitCast(FuncCtx, Builder.getInt8PtrTy());
+ Builder.CreateCall(FuncCtxFn, FuncCtxArg);
// At this point, we are all set up, update the invoke instructions to mark
// their call_site values.
bool SjLjEHPrepare::runOnFunction(Function &F) {
bool Res = setupEntryBlockAndCallSites(F);
- DEBUG({
- if (verifyFunction(F))
- report_fatal_error("verifyFunction failed!");
- });
return Res;
}