forked from OSchip/llvm-project
parent
daa3d6bb50
commit
aff69af918
|
@ -581,22 +581,39 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
|
||||
if (const ConstantArrayType *Array =
|
||||
getContext().getAsConstantArrayType(Ty)) {
|
||||
DelayedCleanupBlock Scope(*this);
|
||||
QualType BaseElementTy = getContext().getBaseElementType(Array);
|
||||
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
|
||||
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
||||
llvm::Value *BaseAddrPtr =
|
||||
Builder.CreateBitCast(DeclPtr, BasePtr);
|
||||
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
|
||||
{
|
||||
DelayedCleanupBlock Scope(*this);
|
||||
QualType BaseElementTy = getContext().getBaseElementType(Array);
|
||||
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
|
||||
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
||||
llvm::Value *BaseAddrPtr =
|
||||
Builder.CreateBitCast(DeclPtr, BasePtr);
|
||||
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
|
||||
|
||||
// Make sure to jump to the exit block.
|
||||
EmitBranch(Scope.getCleanupExitBlock());
|
||||
// Make sure to jump to the exit block.
|
||||
EmitBranch(Scope.getCleanupExitBlock());
|
||||
}
|
||||
if (Exceptions) {
|
||||
EHCleanupBlock Cleanup(*this);
|
||||
QualType BaseElementTy = getContext().getBaseElementType(Array);
|
||||
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
|
||||
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
||||
llvm::Value *BaseAddrPtr =
|
||||
Builder.CreateBitCast(DeclPtr, BasePtr);
|
||||
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
|
||||
}
|
||||
} else {
|
||||
DelayedCleanupBlock Scope(*this);
|
||||
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
|
||||
{
|
||||
DelayedCleanupBlock Scope(*this);
|
||||
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
|
||||
|
||||
// Make sure to jump to the exit block.
|
||||
EmitBranch(Scope.getCleanupExitBlock());
|
||||
// Make sure to jump to the exit block.
|
||||
EmitBranch(Scope.getCleanupExitBlock());
|
||||
}
|
||||
if (Exceptions) {
|
||||
EHCleanupBlock Cleanup(*this);
|
||||
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -608,8 +625,6 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
llvm::Constant* F = CGM.GetAddrOfFunction(FD);
|
||||
assert(F && "Could not find function!");
|
||||
|
||||
DelayedCleanupBlock scope(*this);
|
||||
|
||||
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
|
||||
|
||||
// In some cases, the type of the function argument will be different from
|
||||
|
@ -619,20 +634,40 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
//
|
||||
// To fix this we insert a bitcast here.
|
||||
QualType ArgTy = Info.arg_begin()->type;
|
||||
DeclPtr = Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy));
|
||||
{
|
||||
DelayedCleanupBlock scope(*this);
|
||||
|
||||
CallArgList Args;
|
||||
Args.push_back(std::make_pair(RValue::get(DeclPtr),
|
||||
getContext().getPointerType(D.getType())));
|
||||
CallArgList Args;
|
||||
Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
|
||||
ConvertType(ArgTy))),
|
||||
getContext().getPointerType(D.getType())));
|
||||
EmitCall(Info, F, Args);
|
||||
}
|
||||
if (Exceptions) {
|
||||
EHCleanupBlock Cleanup(*this);
|
||||
|
||||
EmitCall(Info, F, Args);
|
||||
CallArgList Args;
|
||||
Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
|
||||
ConvertType(ArgTy))),
|
||||
getContext().getPointerType(D.getType())));
|
||||
EmitCall(Info, F, Args);
|
||||
}
|
||||
}
|
||||
|
||||
if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
|
||||
DelayedCleanupBlock scope(*this);
|
||||
llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
||||
V = Builder.CreateLoad(V);
|
||||
BuildBlockRelease(V);
|
||||
{
|
||||
DelayedCleanupBlock scope(*this);
|
||||
llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
||||
V = Builder.CreateLoad(V);
|
||||
BuildBlockRelease(V);
|
||||
}
|
||||
// FIXME: Turn this on and audit the codegen
|
||||
if (0 && Exceptions) {
|
||||
EHCleanupBlock Cleanup(*this);
|
||||
llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
||||
V = Builder.CreateLoad(V);
|
||||
BuildBlockRelease(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -650,3 +650,55 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
|
|||
|
||||
EmitBlock(FinallyEnd);
|
||||
}
|
||||
|
||||
CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() {
|
||||
llvm::BasicBlock *Cont1 = CGF.createBasicBlock("cont");
|
||||
CGF.EmitBranch(Cont1);
|
||||
CGF.setInvokeDest(PreviousInvokeDest);
|
||||
|
||||
|
||||
CGF.EmitBlock(CleanupHandler);
|
||||
|
||||
llvm::Constant *Personality =
|
||||
CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
|
||||
(CGF.VMContext),
|
||||
true),
|
||||
"__gxx_personality_v0");
|
||||
Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty);
|
||||
llvm::Value *llvm_eh_exception =
|
||||
CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
|
||||
llvm::Value *llvm_eh_selector =
|
||||
CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
|
||||
|
||||
llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
|
||||
const llvm::IntegerType *Int8Ty;
|
||||
const llvm::PointerType *PtrToInt8Ty;
|
||||
Int8Ty = llvm::Type::getInt8Ty(CGF.VMContext);
|
||||
// C string type. Used in lots of places.
|
||||
PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
|
||||
llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
|
||||
llvm::SmallVector<llvm::Value*, 8> Args;
|
||||
Args.clear();
|
||||
Args.push_back(Exc);
|
||||
Args.push_back(Personality);
|
||||
Args.push_back(Null);
|
||||
CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
|
||||
|
||||
CGF.EmitBlock(CleanupEntryBB);
|
||||
|
||||
CGF.EmitBlock(Cont1);
|
||||
|
||||
if (CGF.getInvokeDest()) {
|
||||
llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
|
||||
CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont,
|
||||
CGF.getInvokeDest(), Exc);
|
||||
CGF.EmitBlock(Cont);
|
||||
} else
|
||||
CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc);
|
||||
|
||||
CGF.Builder.CreateUnreachable();
|
||||
|
||||
CGF.EmitBlock(Cont);
|
||||
if (CGF.Exceptions)
|
||||
CGF.setInvokeDest(CleanupHandler);
|
||||
}
|
||||
|
|
|
@ -137,8 +137,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
|||
const CXXDestructorDecl *Dtor =
|
||||
ClassDecl->getDestructor(getContext());
|
||||
|
||||
DelayedCleanupBlock scope(*this);
|
||||
EmitCXXDestructorCall(Dtor, Dtor_Complete, Val.getAggregateAddr());
|
||||
{
|
||||
DelayedCleanupBlock scope(*this);
|
||||
EmitCXXDestructorCall(Dtor, Dtor_Complete,
|
||||
Val.getAggregateAddr());
|
||||
}
|
||||
if (Exceptions) {
|
||||
EHCleanupBlock Cleanup(*this);
|
||||
EmitCXXDestructorCall(Dtor, Dtor_Complete,
|
||||
Val.getAggregateAddr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
|||
ConditionalBranchLevel(0) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
LLVMPointerWidth = Target.getPointerWidth(0);
|
||||
Exceptions = getContext().getLangOptions().Exceptions;
|
||||
}
|
||||
|
||||
ASTContext &CodeGenFunction::getContext() const {
|
||||
|
@ -625,9 +626,10 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
|
|||
|
||||
void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
||||
llvm::BasicBlock *CleanupExitBlock,
|
||||
llvm::BasicBlock *PreviousInvokeDest,
|
||||
bool EHOnly) {
|
||||
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock,
|
||||
EHOnly));
|
||||
PreviousInvokeDest, EHOnly));
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
|
||||
|
@ -651,6 +653,8 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
|
|||
|
||||
bool EHOnly = CE.EHOnly;
|
||||
|
||||
setInvokeDest(CE.PreviousInvokeDest);
|
||||
|
||||
CleanupEntries.pop_back();
|
||||
|
||||
// Check if any branch fixups pointed to the scope we just popped. If so,
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
const llvm::Type *LLVMIntTy;
|
||||
uint32_t LLVMPointerWidth;
|
||||
|
||||
bool Exceptions;
|
||||
public:
|
||||
/// ObjCEHValueStack - Stack of Objective-C exception values, used for
|
||||
/// rethrows.
|
||||
|
@ -115,8 +116,12 @@ public:
|
|||
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
|
||||
/// passed in block as the cleanup block.
|
||||
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
||||
llvm::BasicBlock *CleanupExitBlock = 0,
|
||||
llvm::BasicBlock *CleanupExitBlock,
|
||||
llvm::BasicBlock *PreviousInvokeDest,
|
||||
bool EHOnly = false);
|
||||
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock) {
|
||||
PushCleanupBlock(CleanupEntryBlock, 0, getInvokeDest(), false);
|
||||
}
|
||||
|
||||
/// CleanupBlockInfo - A struct representing a popped cleanup block.
|
||||
struct CleanupBlockInfo {
|
||||
|
@ -139,9 +144,35 @@ public:
|
|||
: CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb), EHOnly(ehonly) {}
|
||||
};
|
||||
|
||||
/// EHCleanupBlock - RAII object that will create a cleanup block for the
|
||||
/// exceptional edge and set the insert point to that block. When destroyed,
|
||||
/// it creates the cleanup edge and sets the insert point to the previous
|
||||
/// block.
|
||||
class EHCleanupBlock {
|
||||
CodeGenFunction& CGF;
|
||||
llvm::BasicBlock *Cont;
|
||||
llvm::BasicBlock *CleanupHandler;
|
||||
llvm::BasicBlock *CleanupEntryBB;
|
||||
llvm::BasicBlock *PreviousInvokeDest;
|
||||
public:
|
||||
EHCleanupBlock(CodeGenFunction &cgf)
|
||||
: CGF(cgf), Cont(CGF.createBasicBlock("cont")),
|
||||
CleanupHandler(CGF.createBasicBlock("ehcleanup")),
|
||||
CleanupEntryBB(CGF.createBasicBlock("ehcleanup.rest")),
|
||||
PreviousInvokeDest(CGF.getInvokeDest()) {
|
||||
CGF.EmitBranch(Cont);
|
||||
CGF.Builder.SetInsertPoint(CleanupEntryBB);
|
||||
|
||||
// FIXME: set up terminate handler here
|
||||
// CGF.setInvokeDest(TerminateHandler);
|
||||
}
|
||||
~EHCleanupBlock();
|
||||
};
|
||||
|
||||
/// PopCleanupBlock - Will pop the cleanup entry on the stack, process all
|
||||
/// branch fixups and return a block info struct with the switch block and end
|
||||
/// block.
|
||||
/// block. This will also reset the invoke handler to the previous value
|
||||
/// from when the cleanup block was created.
|
||||
CleanupBlockInfo PopCleanupBlock();
|
||||
|
||||
/// DelayedCleanupBlock - RAII object that will create a cleanup block and set
|
||||
|
@ -152,13 +183,15 @@ public:
|
|||
llvm::BasicBlock *CurBB;
|
||||
llvm::BasicBlock *CleanupEntryBB;
|
||||
llvm::BasicBlock *CleanupExitBB;
|
||||
llvm::BasicBlock *CurInvokeDest;
|
||||
bool EHOnly;
|
||||
|
||||
public:
|
||||
DelayedCleanupBlock(CodeGenFunction &cgf, bool ehonly = false)
|
||||
: CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
|
||||
CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0),
|
||||
EHOnly(ehonly) {
|
||||
CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0),
|
||||
CurInvokeDest(CGF.getInvokeDest()),
|
||||
EHOnly(ehonly) {
|
||||
CGF.Builder.SetInsertPoint(CleanupEntryBB);
|
||||
}
|
||||
|
||||
|
@ -169,7 +202,8 @@ public:
|
|||
}
|
||||
|
||||
~DelayedCleanupBlock() {
|
||||
CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, EHOnly);
|
||||
CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, CurInvokeDest,
|
||||
EHOnly);
|
||||
// FIXME: This is silly, move this into the builder.
|
||||
if (CurBB)
|
||||
CGF.Builder.SetInsertPoint(CurBB);
|
||||
|
@ -316,13 +350,20 @@ private:
|
|||
/// inserted into the current function yet.
|
||||
std::vector<llvm::BranchInst *> BranchFixups;
|
||||
|
||||
/// PreviousInvokeDest - The invoke handler from the start of the cleanup
|
||||
/// region.
|
||||
llvm::BasicBlock *PreviousInvokeDest;
|
||||
|
||||
/// EHOnly - Perform this only on the exceptional edge, not the main edge.
|
||||
bool EHOnly;
|
||||
|
||||
explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
|
||||
llvm::BasicBlock *CleanupExitBlock, bool ehonly)
|
||||
: CleanupEntryBlock(CleanupEntryBlock),
|
||||
llvm::BasicBlock *CleanupExitBlock,
|
||||
llvm::BasicBlock *PreviousInvokeDest,
|
||||
bool ehonly)
|
||||
: CleanupEntryBlock(CleanupEntryBlock),
|
||||
CleanupExitBlock(CleanupExitBlock),
|
||||
PreviousInvokeDest(PreviousInvokeDest),
|
||||
EHOnly(ehonly) {}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue