//===--- CGCleanup.cpp - Bookkeeping and code emission for cleanups -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code dealing with the IR generation for cleanups
// and related information.
//
// A "cleanup" is a piece of code which needs to be executed whenever
// control transfers out of a particular scope. This can be
// conditionalized to occur only on exceptional control flow, only on
// normal control flow, or both.
//
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
#include "CGCleanup.h"
using namespace clang;
using namespace CodeGen;
bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) {
if (rv.isScalar())
return DominatingLLVMValue::needsSaving(rv.getScalarVal());
if (rv.isAggregate())
return DominatingLLVMValue::needsSaving(rv.getAggregateAddr());
return true;
}
DominatingValue<RValue>::saved_type
DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
if (rv.isScalar()) {
llvm::Value *V = rv.getScalarVal();
// These automatically dominate and don't need to be saved.
if (!DominatingLLVMValue::needsSaving(V))
return saved_type(V, ScalarLiteral);
// Everything else needs an alloca.
llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
CGF.Builder.CreateStore(V, addr);
return saved_type(addr, ScalarAddress);
}
if (rv.isComplex()) {
CodeGenFunction::ComplexPairTy V = rv.getComplexVal();
llvm::Type *ComplexTy =
llvm::StructType::get(V.first->getType(), V.second->getType(),
(void*) 0);
llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0));
CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1));
return saved_type(addr, ComplexAddress);
}
assert(rv.isAggregate());
llvm::Value *V = rv.getAggregateAddr(); // TODO: volatile?
if (!DominatingLLVMValue::needsSaving(V))
return saved_type(V, AggregateLiteral);
llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
CGF.Builder.CreateStore(V, addr);
return saved_type(addr, AggregateAddress);
}
/// Given a saved r-value produced by SaveRValue, perform the code
/// necessary to restore it to usability at the current insertion
/// point.
RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
switch (K) {
case ScalarLiteral:
return RValue::get(Value);
case ScalarAddress:
return RValue::get(CGF.Builder.CreateLoad(Value));
case AggregateLiteral:
return RValue::getAggregate(Value);
case AggregateAddress:
return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
case ComplexAddress: {
llvm::Value *real =
CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 0));
llvm::Value *imag =
CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 1));
return RValue::getComplex(real, imag);
}
}
llvm_unreachable("bad saved r-value kind");
}
/// Push an entry of the given size onto this protected-scope stack.
char *EHScopeStack::allocate(size_t Size) {
if (!StartOfBuffer) {
unsigned Capacity = 1024;
while (Capacity < Size) Capacity