#include "llvm/CodeGen/Passes.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLowering.h"
STATISTIC(NumSpilled, "Number of registers live across unwind edges");
namespace {
- class VISIBILITY_HIDDEN SjLjEHPass : public FunctionPass {
+ class SjLjEHPass : public FunctionPass {
const TargetLowering *TLI;
Constant *FrameAddrFn;
Constant *LSDAAddrFn;
Value *PersonalityFn;
- Constant *Selector32Fn;
- Constant *Selector64Fn;
+ Constant *SelectorFn;
Constant *ExceptionFn;
Value *CallSite;
private:
void markInvokeCallSite(InvokeInst *II, unsigned InvokeNo,
- Value *CallSite);
+ Value *CallSite,
+ SwitchInst *CatchSwitch);
void splitLiveRangesLiveAcrossInvokes(SmallVector<InvokeInst*,16> &Invokes);
bool insertSjLjEHSupport(Function &F);
};
// Build the function context structure.
// builtin_setjmp uses a five word jbuf
const Type *VoidPtrTy =
- PointerType::getUnqual(Type::getInt8Ty(M.getContext()));
+ Type::getInt8PtrTy(M.getContext());
const Type *Int32Ty = Type::getInt32Ty(M.getContext());
FunctionContextTy =
StructType::get(M.getContext(),
FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress);
BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp);
LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda);
- Selector32Fn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector_i32);
- Selector64Fn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector_i64);
+ SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector);
ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception);
PersonalityFn = 0;
/// markInvokeCallSite - Insert code to mark the call_site for this invoke
void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo,
- Value *CallSite) {
+ Value *CallSite,
+ SwitchInst *CatchSwitch) {
ConstantInt *CallSiteNoC= ConstantInt::get(Type::getInt32Ty(II->getContext()),
InvokeNo);
+ // The runtime comes back to the dispatcher with the call_site - 1 in
+ // the context. Odd, but there it is.
+ ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()),
+ InvokeNo - 1);
// If the unwind edge has phi nodes, split the edge.
if (isa<PHINode>(II->getUnwindDest()->begin())) {
// location afterward.
new StoreInst(CallSiteNoC, CallSite, true, II); // volatile
+ // Add a switch case to our unwind block.
+ CatchSwitch->addCase(SwitchValC, II->getUnwindDest());
// We still want this to look like an invoke so we emit the LSDA properly
// FIXME: ??? Or will this cause strangeness with mis-matched IDs like
// when it was in the front end?
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
if (CallInst *CI = dyn_cast<CallInst>(I)) {
- if (CI->getCalledFunction() == Selector32Fn ||
- CI->getCalledFunction() == Selector64Fn) {
+ if (CI->getCalledFunction() == SelectorFn) {
if (!PersonalityFn) PersonalityFn = CI->getOperand(2);
EH_Selectors.push_back(CI);
} else if (CI->getCalledFunction() == ExceptionFn) {
if (!Invokes.empty()) {
// We have invokes, so we need to add register/unregister calls to get
// this function onto the global unwind stack.
+ //
+ // First thing we need to do is scan the whole function for values that are
+ // live across unwind edges. Each value that is live across an unwind edge
+ // we spill into a stack location, guaranteeing that there is nothing live
+ // across the unwind edge. This process also splits all critical edges
+ // coming out of invoke's.
+ splitLiveRangesLiveAcrossInvokes(Invokes);
BasicBlock *EntryBB = F.begin();
// Create an alloca for the incoming jump buffer ptr and the new jump buffer
// the instruction hasn't already been removed.
if (!I->getParent()) continue;
Value *Val = new LoadInst(ExceptionAddr, "exception", true, I);
- Type *Ty = PointerType::getUnqual(Type::getInt8Ty(F.getContext()));
+ const Type *Ty = Type::getInt8PtrTy(F.getContext());
Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I);
I->replaceAllUsesWith(Val);
// Call the setjmp instrinsic. It fills in the rest of the jmpbuf
Value *SetjmpArg =
CastInst::Create(Instruction::BitCast, FieldPtr,
- Type::getInt8Ty(F.getContext())->getPointerTo(), "",
- EntryBB->getTerminator());
+ Type::getInt8PtrTy(F.getContext()), "",
+ EntryBB->getTerminator());
Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg,
"dispatch",
EntryBB->getTerminator());
ContBlock->getTerminator());
Register->setDoesNotThrow();
- // At this point, we are all set up. Update the invoke instructions
+ // At this point, we are all set up, update the invoke instructions
// to mark their call_site values, and fill in the dispatch switch
// accordingly.
- DenseMap<BasicBlock*,unsigned> PadSites;
- unsigned NextCallSiteValue = 1;
- for (SmallVector<InvokeInst*,16>::iterator I = Invokes.begin(),
- E = Invokes.end(); I < E; ++I) {
- unsigned CallSiteValue;
- BasicBlock *LandingPad = (*I)->getSuccessor(1);
- // landing pads can be shared. If we see a landing pad again, we
- // want to make sure to use the same call site index so the dispatch
- // will go to the right place.
- CallSiteValue = PadSites[LandingPad];
- if (!CallSiteValue) {
- CallSiteValue = NextCallSiteValue++;
- PadSites[LandingPad] = CallSiteValue;
- // Add a switch case to our unwind block. The runtime comes back
- // to the dispatcher with the call_site - 1 in the context. Odd,
- // but there it is.
- ConstantInt *SwitchValC =
- ConstantInt::get(Type::getInt32Ty((*I)->getContext()),
- CallSiteValue - 1);
- DispatchSwitch->addCase(SwitchValC, (*I)->getUnwindDest());
- }
- markInvokeCallSite(*I, CallSiteValue, CallSite);
- }
+ for (unsigned i = 0, e = Invokes.size(); i != e; ++i)
+ markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch);
// The front end has likely added calls to _Unwind_Resume. We need
// to find those calls and mark the call_site as -1 immediately prior.
Unwinds[i]->eraseFromParent();
}
- // Scan the whole function for values that are live across unwind edges.
- // Each value that is live across an unwind edge we spill into a stack
- // location, guaranteeing that there is nothing live across the unwind
- // edge. This process also splits all critical edges coming out of
- // invoke's.
- splitLiveRangesLiveAcrossInvokes(Invokes);
-
// Finally, for any returns from this function, if this function contains an
// invoke, add a call to unregister the function context.
for (unsigned i = 0, e = Returns.size(); i != e; ++i)