forked from OSchip/llvm-project
parent
daa3d6bb50
commit
aff69af918
|
@ -581,22 +581,39 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
||||||
|
|
||||||
if (const ConstantArrayType *Array =
|
if (const ConstantArrayType *Array =
|
||||||
getContext().getAsConstantArrayType(Ty)) {
|
getContext().getAsConstantArrayType(Ty)) {
|
||||||
DelayedCleanupBlock Scope(*this);
|
{
|
||||||
QualType BaseElementTy = getContext().getBaseElementType(Array);
|
DelayedCleanupBlock Scope(*this);
|
||||||
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
|
QualType BaseElementTy = getContext().getBaseElementType(Array);
|
||||||
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
|
||||||
llvm::Value *BaseAddrPtr =
|
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
||||||
Builder.CreateBitCast(DeclPtr, BasePtr);
|
llvm::Value *BaseAddrPtr =
|
||||||
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
|
Builder.CreateBitCast(DeclPtr, BasePtr);
|
||||||
|
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
|
||||||
|
|
||||||
// Make sure to jump to the exit block.
|
// Make sure to jump to the exit block.
|
||||||
EmitBranch(Scope.getCleanupExitBlock());
|
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 {
|
} 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.
|
// Make sure to jump to the exit block.
|
||||||
EmitBranch(Scope.getCleanupExitBlock());
|
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);
|
llvm::Constant* F = CGM.GetAddrOfFunction(FD);
|
||||||
assert(F && "Could not find function!");
|
assert(F && "Could not find function!");
|
||||||
|
|
||||||
DelayedCleanupBlock scope(*this);
|
|
||||||
|
|
||||||
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
|
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
|
||||||
|
|
||||||
// In some cases, the type of the function argument will be different from
|
// 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.
|
// To fix this we insert a bitcast here.
|
||||||
QualType ArgTy = Info.arg_begin()->type;
|
QualType ArgTy = Info.arg_begin()->type;
|
||||||
DeclPtr = Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy));
|
{
|
||||||
|
DelayedCleanupBlock scope(*this);
|
||||||
|
|
||||||
CallArgList Args;
|
CallArgList Args;
|
||||||
Args.push_back(std::make_pair(RValue::get(DeclPtr),
|
Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
|
||||||
getContext().getPointerType(D.getType())));
|
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) {
|
if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
|
||||||
DelayedCleanupBlock scope(*this);
|
{
|
||||||
llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
DelayedCleanupBlock scope(*this);
|
||||||
V = Builder.CreateLoad(V);
|
llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
||||||
BuildBlockRelease(V);
|
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);
|
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 =
|
const CXXDestructorDecl *Dtor =
|
||||||
ClassDecl->getDestructor(getContext());
|
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) {
|
ConditionalBranchLevel(0) {
|
||||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||||
LLVMPointerWidth = Target.getPointerWidth(0);
|
LLVMPointerWidth = Target.getPointerWidth(0);
|
||||||
|
Exceptions = getContext().getLangOptions().Exceptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTContext &CodeGenFunction::getContext() const {
|
ASTContext &CodeGenFunction::getContext() const {
|
||||||
|
@ -625,9 +626,10 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
|
||||||
|
|
||||||
void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
||||||
llvm::BasicBlock *CleanupExitBlock,
|
llvm::BasicBlock *CleanupExitBlock,
|
||||||
|
llvm::BasicBlock *PreviousInvokeDest,
|
||||||
bool EHOnly) {
|
bool EHOnly) {
|
||||||
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock,
|
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock,
|
||||||
EHOnly));
|
PreviousInvokeDest, EHOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
|
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
|
||||||
|
@ -651,6 +653,8 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
|
||||||
|
|
||||||
bool EHOnly = CE.EHOnly;
|
bool EHOnly = CE.EHOnly;
|
||||||
|
|
||||||
|
setInvokeDest(CE.PreviousInvokeDest);
|
||||||
|
|
||||||
CleanupEntries.pop_back();
|
CleanupEntries.pop_back();
|
||||||
|
|
||||||
// Check if any branch fixups pointed to the scope we just popped. If so,
|
// Check if any branch fixups pointed to the scope we just popped. If so,
|
||||||
|
|
|
@ -107,6 +107,7 @@ public:
|
||||||
const llvm::Type *LLVMIntTy;
|
const llvm::Type *LLVMIntTy;
|
||||||
uint32_t LLVMPointerWidth;
|
uint32_t LLVMPointerWidth;
|
||||||
|
|
||||||
|
bool Exceptions;
|
||||||
public:
|
public:
|
||||||
/// ObjCEHValueStack - Stack of Objective-C exception values, used for
|
/// ObjCEHValueStack - Stack of Objective-C exception values, used for
|
||||||
/// rethrows.
|
/// rethrows.
|
||||||
|
@ -115,8 +116,12 @@ public:
|
||||||
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
|
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
|
||||||
/// passed in block as the cleanup block.
|
/// passed in block as the cleanup block.
|
||||||
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
|
||||||
llvm::BasicBlock *CleanupExitBlock = 0,
|
llvm::BasicBlock *CleanupExitBlock,
|
||||||
|
llvm::BasicBlock *PreviousInvokeDest,
|
||||||
bool EHOnly = false);
|
bool EHOnly = false);
|
||||||
|
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock) {
|
||||||
|
PushCleanupBlock(CleanupEntryBlock, 0, getInvokeDest(), false);
|
||||||
|
}
|
||||||
|
|
||||||
/// CleanupBlockInfo - A struct representing a popped cleanup block.
|
/// CleanupBlockInfo - A struct representing a popped cleanup block.
|
||||||
struct CleanupBlockInfo {
|
struct CleanupBlockInfo {
|
||||||
|
@ -139,9 +144,35 @@ public:
|
||||||
: CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb), EHOnly(ehonly) {}
|
: 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
|
/// 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
|
/// 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();
|
CleanupBlockInfo PopCleanupBlock();
|
||||||
|
|
||||||
/// DelayedCleanupBlock - RAII object that will create a cleanup block and set
|
/// DelayedCleanupBlock - RAII object that will create a cleanup block and set
|
||||||
|
@ -152,13 +183,15 @@ public:
|
||||||
llvm::BasicBlock *CurBB;
|
llvm::BasicBlock *CurBB;
|
||||||
llvm::BasicBlock *CleanupEntryBB;
|
llvm::BasicBlock *CleanupEntryBB;
|
||||||
llvm::BasicBlock *CleanupExitBB;
|
llvm::BasicBlock *CleanupExitBB;
|
||||||
|
llvm::BasicBlock *CurInvokeDest;
|
||||||
bool EHOnly;
|
bool EHOnly;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DelayedCleanupBlock(CodeGenFunction &cgf, bool ehonly = false)
|
DelayedCleanupBlock(CodeGenFunction &cgf, bool ehonly = false)
|
||||||
: CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
|
: CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
|
||||||
CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0),
|
CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0),
|
||||||
EHOnly(ehonly) {
|
CurInvokeDest(CGF.getInvokeDest()),
|
||||||
|
EHOnly(ehonly) {
|
||||||
CGF.Builder.SetInsertPoint(CleanupEntryBB);
|
CGF.Builder.SetInsertPoint(CleanupEntryBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +202,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
~DelayedCleanupBlock() {
|
~DelayedCleanupBlock() {
|
||||||
CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, EHOnly);
|
CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, CurInvokeDest,
|
||||||
|
EHOnly);
|
||||||
// FIXME: This is silly, move this into the builder.
|
// FIXME: This is silly, move this into the builder.
|
||||||
if (CurBB)
|
if (CurBB)
|
||||||
CGF.Builder.SetInsertPoint(CurBB);
|
CGF.Builder.SetInsertPoint(CurBB);
|
||||||
|
@ -316,13 +350,20 @@ private:
|
||||||
/// inserted into the current function yet.
|
/// inserted into the current function yet.
|
||||||
std::vector<llvm::BranchInst *> BranchFixups;
|
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.
|
/// EHOnly - Perform this only on the exceptional edge, not the main edge.
|
||||||
bool EHOnly;
|
bool EHOnly;
|
||||||
|
|
||||||
explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
|
explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
|
||||||
llvm::BasicBlock *CleanupExitBlock, bool ehonly)
|
llvm::BasicBlock *CleanupExitBlock,
|
||||||
: CleanupEntryBlock(CleanupEntryBlock),
|
llvm::BasicBlock *PreviousInvokeDest,
|
||||||
|
bool ehonly)
|
||||||
|
: CleanupEntryBlock(CleanupEntryBlock),
|
||||||
CleanupExitBlock(CleanupExitBlock),
|
CleanupExitBlock(CleanupExitBlock),
|
||||||
|
PreviousInvokeDest(PreviousInvokeDest),
|
||||||
EHOnly(ehonly) {}
|
EHOnly(ehonly) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue