teak-llvm/clang/lib/CodeGen/CGTemporaries.cpp
John McCall bd30929e4d Validated by nightly-test runs on x86 and x86-64 darwin, including after
self-host.  Hopefully these results hold up on different platforms.  

I tried to keep the GNU ObjC runtime happy, but it's hard for me to test.
Reimplement how clang generates IR for exceptions.  Instead of creating new
invoke destinations which sequentially chain to the previous destination,
push a more semantic representation of *why* we need the cleanup/catch/filter
behavior, then collect that information into a single landing pad upon request.

Also reorganizes how normal cleanups (i.e. cleanups triggered by non-exceptional
control flow) are generated, since it's actually fairly closely tied in with
the former.  Remove the need to track which cleanup scope a block is associated
with.

Document a lot of previously poorly-understood (by me, at least) behavior.

The new framework implements the Horrible Hack (tm), which requires every
landing pad to have a catch-all so that inlining will work.  Clang no longer
requires the Horrible Hack just to make exceptions flow correctly within
a function, however.  The HH is an unfortunate requirement of LLVM's EH IR.

llvm-svn: 107631
2010-07-06 01:34:17 +00:00

99 lines
3.3 KiB
C++

//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of temporaries
//
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
using namespace clang;
using namespace CodeGen;
static void EmitTemporaryCleanup(CodeGenFunction &CGF,
const CXXTemporary *Temporary,
llvm::Value *Addr,
llvm::Value *CondPtr) {
llvm::BasicBlock *CondEnd = 0;
// If this is a conditional temporary, we need to check the condition
// boolean and only call the destructor if it's true.
if (CondPtr) {
llvm::BasicBlock *CondBlock = CGF.createBasicBlock("temp.cond-dtor.call");
CondEnd = CGF.createBasicBlock("temp.cond-dtor.cont");
llvm::Value *Cond = CGF.Builder.CreateLoad(CondPtr);
CGF.Builder.CreateCondBr(Cond, CondBlock, CondEnd);
CGF.EmitBlock(CondBlock);
}
CGF.EmitCXXDestructorCall(Temporary->getDestructor(),
Dtor_Complete, /*ForVirtualBase=*/false,
Addr);
if (CondPtr) {
// Reset the condition to false.
CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()),
CondPtr);
CGF.EmitBlock(CondEnd);
}
}
/// Emits all the code to cause the given temporary to be cleaned up.
void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
llvm::Value *Ptr) {
llvm::AllocaInst *CondPtr = 0;
// Check if temporaries need to be conditional. If so, we'll create a
// condition boolean, initialize it to 0 and
if (ConditionalBranchLevel != 0) {
CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
// Initialize it to false. This initialization takes place right after
// the alloca insert point.
InitTempAlloca(CondPtr, llvm::ConstantInt::getFalse(VMContext));
// Now set it to true.
Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
}
CleanupBlock Cleanup(*this, NormalCleanup);
EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr);
if (Exceptions) {
Cleanup.beginEHCleanup();
EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr);
}
}
RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool IsAggLocVolatile,
bool IsInitializer) {
RValue RV;
{
RunCleanupsScope Scope(*this);
RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
/*IgnoreResult=*/false, IsInitializer);
}
return RV;
}
LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
const CXXExprWithTemporaries *E) {
LValue LV;
{
RunCleanupsScope Scope(*this);
LV = EmitLValue(E->getSubExpr());
}
return LV;
}