//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
const TargetLowering *TLI;
public:
- LowerInvoke(const TargetLowering *tli = NULL) : TLI(tli) { }
+ static char ID; // Pass identification, replacement for typeid
+ explicit LowerInvoke(const TargetLowering *tli = NULL)
+ : FunctionPass((intptr_t)&ID), TLI(tli) { }
bool doInitialization(Module &M);
bool runOnFunction(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- // This is a cluster of orthogonal Transforms
+ // This is a cluster of orthogonal Transforms
AU.addPreservedID(PromoteMemoryToRegisterID);
- AU.addPreservedID(LowerSelectID);
AU.addPreservedID(LowerSwitchID);
AU.addPreservedID(LowerAllocationsID);
}
bool insertExpensiveEHSupport(Function &F);
};
+ char LowerInvoke::ID = 0;
RegisterPass<LowerInvoke>
X("lowerinvoke", "Lower invoke and unwind, for unwindless code generators");
}
// doInitialization - Make sure that there is a prototype for abort in the
// current module.
bool LowerInvoke::doInitialization(Module &M) {
- const Type *VoidPtrTy = PointerType::get(Type::Int8Ty);
+ const Type *VoidPtrTy = PointerType::getUnqual(Type::Int8Ty);
AbortMessage = 0;
if (ExpensiveEHSupport) {
// Insert a type for the linked list of jump buffers.
std::vector<const Type*> Elements;
Elements.push_back(JmpBufTy);
OpaqueType *OT = OpaqueType::get();
- Elements.push_back(PointerType::get(OT));
+ Elements.push_back(PointerType::getUnqual(OT));
PATypeHolder JBLType(StructType::get(Elements));
OT->refineAbstractTypeTo(JBLType.get()); // Complete the cycle.
JBLinkTy = JBLType.get();
M.addTypeName("llvm.sjljeh.jmpbufty", JBLinkTy);
}
- const Type *PtrJBList = PointerType::get(JBLinkTy);
+ const Type *PtrJBList = PointerType::getUnqual(JBLinkTy);
// Now that we've done that, insert the jmpbuf list head global, unless it
// already exists.
"llvm.sjljeh.jblist", &M);
}
SetJmpFn = M.getOrInsertFunction("llvm.setjmp", Type::Int32Ty,
- PointerType::get(JmpBufTy), (Type *)0);
+ PointerType::getUnqual(JmpBufTy),
+ (Type *)0);
LongJmpFn = M.getOrInsertFunction("llvm.longjmp", Type::VoidTy,
- PointerType::get(JmpBufTy),
+ PointerType::getUnqual(JmpBufTy),
Type::Int32Ty, (Type *)0);
}
// We need the 'write' and 'abort' functions for both models.
AbortFn = M.getOrInsertFunction("abort", Type::VoidTy, (Type *)0);
+#if 0 // "write" is Unix-specific.. code is going away soon anyway.
WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::Int32Ty,
VoidPtrTy, Type::Int32Ty, (Type *)0);
+#else
+ WriteFn = 0;
+#endif
return true;
}
GlobalValue::InternalLinkage,
Msg, "abortmsg", M);
std::vector<Constant*> GEPIdx(2, Constant::getNullValue(Type::Int32Ty));
- AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, GEPIdx);
+ AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2);
} else {
// The abort message for cheap EH support tells the user that EH is not
// enabled.
GlobalValue::InternalLinkage,
Msg, "abortmsg", M);
std::vector<Constant*> GEPIdx(2, Constant::getNullValue(Type::Int32Ty));
- AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, GEPIdx);
+ AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2);
}
}
void LowerInvoke::writeAbortMessage(Instruction *IB) {
+#if 0
if (AbortMessage == 0)
createAbortMessage(IB->getParent()->getParent()->getParent());
// These are the arguments we WANT...
- std::vector<Value*> Args;
- Args.push_back(ConstantInt::get(Type::Int32Ty, 2));
- Args.push_back(AbortMessage);
- Args.push_back(ConstantInt::get(Type::Int32Ty, AbortMessageLength));
- (new CallInst(WriteFn, Args, "", IB))->setTailCall();
+ Value* Args[3];
+ Args[0] = ConstantInt::get(Type::Int32Ty, 2);
+ Args[1] = AbortMessage;
+ Args[2] = ConstantInt::get(Type::Int32Ty, AbortMessageLength);
+ (new CallInst(WriteFn, Args, 3, "", IB))->setTailCall();
+#endif
}
bool LowerInvoke::insertCheapEHSupport(Function &F) {
bool Changed = false;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
+ std::vector<Value*> CallArgs(II->op_begin()+3, II->op_end());
// Insert a normal call instruction...
CallInst *NewCall = new CallInst(II->getCalledValue(),
- std::vector<Value*>(II->op_begin()+3,
- II->op_end()), "", II);
+ CallArgs.begin(), CallArgs.end(), "",II);
NewCall->takeName(II);
NewCall->setCallingConv(II->getCallingConv());
+ NewCall->setParamAttrs(II->getParamAttrs());
II->replaceAllUsesWith(NewCall);
// Insert an unconditional branch to the normal destination.
writeAbortMessage(UI);
// Insert a call to abort()
- (new CallInst(AbortFn, std::vector<Value*>(), "", UI))->setTailCall();
+ (new CallInst(AbortFn, "", UI))->setTailCall();
// Insert a return instruction. This really should be a "barrier", as it
// is unreachable.
SwitchInst *CatchSwitch) {
ConstantInt *InvokeNoC = ConstantInt::get(Type::Int32Ty, InvokeNo);
+ // If the unwind edge has phi nodes, split the edge.
+ if (isa<PHINode>(II->getUnwindDest()->begin())) {
+ SplitCriticalEdge(II, 1, this);
+
+ // If there are any phi nodes left, they must have a single predecessor.
+ while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) {
+ PN->replaceAllUsesWith(PN->getIncomingValue(0));
+ PN->eraseFromParent();
+ }
+ }
+
// Insert a store of the invoke num before the invoke and store zero into the
// location afterward.
new StoreInst(InvokeNoC, InvokeNum, true, II); // volatile
CatchSwitch->addCase(InvokeNoC, II->getUnwindDest());
// Insert a normal call instruction.
+ std::vector<Value*> CallArgs(II->op_begin()+3, II->op_end());
CallInst *NewCall = new CallInst(II->getCalledValue(),
- std::vector<Value*>(II->op_begin()+3,
- II->op_end()), "",
+ CallArgs.begin(), CallArgs.end(), "",
II);
NewCall->takeName(II);
NewCall->setCallingConv(II->getCallingConv());
+ NewCall->setParamAttrs(II->getParamAttrs());
II->replaceAllUsesWith(NewCall);
// Replace the invoke with an uncond branch.
std::vector<Value*> Idx;
Idx.push_back(Constant::getNullValue(Type::Int32Ty));
Idx.push_back(ConstantInt::get(Type::Int32Ty, 1));
- OldJmpBufPtr = new GetElementPtrInst(JmpBuf, Idx, "OldBuf",
- EntryBB->getTerminator());
+ OldJmpBufPtr = new GetElementPtrInst(JmpBuf, Idx.begin(), Idx.end(),
+ "OldBuf", EntryBB->getTerminator());
// Copy the JBListHead to the alloca.
Value *OldBuf = new LoadInst(JBListHead, "oldjmpbufptr", true,
"setjmp.cont");
Idx[1] = ConstantInt::get(Type::Int32Ty, 0);
- Value *JmpBufPtr = new GetElementPtrInst(JmpBuf, Idx, "TheJmpBuf",
+ Value *JmpBufPtr = new GetElementPtrInst(JmpBuf, Idx.begin(), Idx.end(),
+ "TheJmpBuf",
EntryBB->getTerminator());
Value *SJRet = new CallInst(SetJmpFn, JmpBufPtr, "sjret",
EntryBB->getTerminator());
std::vector<Value*> Idx;
Idx.push_back(Constant::getNullValue(Type::Int32Ty));
Idx.push_back(ConstantInt::get(Type::Int32Ty, 0));
- Idx[0] = new GetElementPtrInst(BufPtr, Idx, "JmpBuf", UnwindBlock);
+ Idx[0] = new GetElementPtrInst(BufPtr, Idx.begin(), Idx.end(), "JmpBuf",
+ UnwindBlock);
Idx[1] = ConstantInt::get(Type::Int32Ty, 1);
- new CallInst(LongJmpFn, Idx, "", UnwindBlock);
+ new CallInst(LongJmpFn, Idx.begin(), Idx.end(), "", UnwindBlock);
new UnreachableInst(UnwindBlock);
// Set up the term block ("throw without a catch").
writeAbortMessage(TermBlock->getTerminator());
// Insert a call to abort()
- (new CallInst(AbortFn, std::vector<Value*>(), "",
+ (new CallInst(AbortFn, "",
TermBlock->getTerminator()))->setTailCall();