mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-24 22:08:57 -04:00

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
99 lines
3.3 KiB
C++
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;
|
|
}
|