#ifndef CLANG_CODEGEN_CODEGENFUNCTION_H
#define CLANG_CODEGEN_CODEGENFUNCTION_H
#include "clang/AST/Type.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/CharUnits.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/Debug.h"
#include "CodeGenModule.h"
#include "CGBuilder.h"
#include "CGDebugInfo.h"
#include "CGValue.h"
namespace llvm {
class BasicBlock;
class LLVMContext;
class MDNode;
class Module;
class SwitchInst;
class Twine;
class Value;
class CallSite;
}
namespace clang {
class ASTContext;
class BlockDecl;
class CXXDestructorDecl;
class CXXForRangeStmt;
class CXXTryStmt;
class Decl;
class LabelDecl;
class EnumConstantDecl;
class FunctionDecl;
class FunctionProtoType;
class LabelStmt;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCIvarDecl;
class ObjCMethodDecl;
class ObjCImplementationDecl;
class ObjCPropertyImplDecl;
class TargetInfo;
class TargetCodeGenInfo;
class VarDecl;
class ObjCForCollectionStmt;
class ObjCAtTryStmt;
class ObjCAtThrowStmt;
class ObjCAtSynchronizedStmt;
class ObjCAutoreleasePoolStmt;
namespace CodeGen {
class CodeGenTypes;
class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
class CGCXXABI;
class BlockFlags;
class BlockFieldFlags;
struct BranchFixup {
llvm::BasicBlock *OptimisticBranchBlock;
llvm::BasicBlock *Destination;
unsigned DestinationIndex;
llvm::BranchInst *InitialBranch;
};
template <class T> struct InvariantValue {
typedef T type;
typedef T saved_type;
static bool needsSaving(type value) { return false; }
static saved_type save(CodeGenFunction &CGF, type value) { return value; }
static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
};
template <class T> struct DominatingValue : InvariantValue<T> {};
template <class T, bool mightBeInstruction =
llvm::is_base_of<llvm::Value, T>::value &&
!llvm::is_base_of<llvm::Constant, T>::value &&
!llvm::is_base_of<llvm::BasicBlock, T>::value>
struct DominatingPointer;
template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
enum CleanupKind {
EHCleanup = 0x1,
NormalCleanup = 0x2,
NormalAndEHCleanup = EHCleanup | NormalCleanup,
InactiveCleanup = 0x4,
InactiveEHCleanup = EHCleanup | InactiveCleanup,
InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
};
class EHScopeStack {
public:
class stable_iterator {
friend class EHScopeStack;
ptrdiff_t Size;
stable_iterator(ptrdiff_t Size) : Size(Size) {}
public:
static stable_iterator invalid() { return stable_iterator(-1); }
stable_iterator() : Size(-1) {}
bool isValid() const { return Size >= 0; }
bool encloses(stable_iterator I) const { return Size <= I.Size; }
bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
friend bool operator==(stable_iterator A, stable_iterator B) {
return A.Size == B.Size;
}
friend bool operator!=(stable_iterator A, stable_iterator B) {
return A.Size != B.Size;
}
};
class Cleanup {
virtual void anchor();
public:
class Flags {
enum {
F_IsForEH = 0x1,
F_IsNormalCleanupKind = 0x2,
F_IsEHCleanupKind = 0x4
};
unsigned flags;
public:
Flags() : flags(0) {}
bool isForEHCleanup() const { return flags & F_IsForEH; }
bool isForNormalCleanup() const { return !isForEHCleanup(); }
void setIsForEHCleanup() { flags |= F_IsForEH; }
bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
};
virtual ~Cleanup() {}
virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
};
template <class T, class A0>
class ConditionalCleanup1 : public Cleanup {
typedef typename DominatingValue<A0>::saved_type A0_saved;
A0_saved a0_saved;
void Emit(CodeGenFunction &CGF, Flags flags) {
A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
T(a0).Emit(CGF, flags);
}
public:
ConditionalCleanup1(A0_saved a0)
: a0_saved(a0) {}
};
template <class T, class A0, class A1>
class ConditionalCleanup2 : public Cleanup {
typedef typename DominatingValue<A0>::saved_type A0_saved;
typedef typename DominatingValue<A1>::saved_type A1_saved;
A0_saved a0_saved;
A1_saved a1_saved;
void Emit(CodeGenFunction &CGF, Flags flags) {
A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
T(a0, a1).Emit(CGF, flags);
}
public:
ConditionalCleanup2(A0_saved a0, A1_saved a1)
: a0_saved(a0), a1_saved(a1) {}
};
template <class T, class A0, class A1, class A2>
class ConditionalCleanup3 : public Cleanup {
typedef typename DominatingValue<A0>::saved_type A0_saved;
typedef typename DominatingValue<A1>::saved_type A1_saved;
typedef typename DominatingValue<A2>::saved_type A2_saved;
A0_saved a0_saved;
A1_saved a1_saved;
A2_saved a2_saved;
void Emit(CodeGenFunction &CGF, Flags flags) {
A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
T(a0, a1, a2).Emit(CGF, flags);
}
public:
ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
: a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
};
template <class T, class A0, class A1, class A2, class A3>
class ConditionalCleanup4 : public Cleanup {
typedef typename DominatingValue<A0>::saved_type A0_saved;
typedef typename DominatingValue<A1>::saved_type A1_saved;
typedef typename DominatingValue<A2>::saved_type A2_saved;
typedef typename DominatingValue<A3>::saved_type A3_saved;
A0_saved a0_saved;
A1_saved a1_saved;
A2_saved a2_saved;
A3_saved a3_saved;
void Emit(CodeGenFunction &CGF, Flags flags) {
A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
T(a0, a1, a2, a3).Emit(CGF, flags);
}
public:
ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
: a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
};
private:
char *StartOfBuffer;
char *EndOfBuffer;
char *StartOfData;
stable_iterator InnermostNormalCleanup;
stable_iterator InnermostEHScope;
SmallVector<BranchFixup, 8> BranchFixups;
char *allocate(size_t Size);
void *pushCleanup(CleanupKind K, size_t DataSize);
public:
EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
InnermostNormalCleanup(stable_end()),
InnermostEHScope(stable_end()) {}
~EHScopeStack() { delete[] StartOfBuffer; }
template <class T>
void pushCleanup(CleanupKind Kind) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T();
(void) Obj;
}
template <class T, class A0>
void pushCleanup(CleanupKind Kind, A0 a0) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T(a0);
(void) Obj;
}
template <class T, class A0, class A1>
void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T(a0, a1);
(void) Obj;
}
template <class T, class A0, class A1, class A2>
void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T(a0, a1, a2);
(void) Obj;
}
template <class T, class A0, class A1, class A2, class A3>
void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
(void) Obj;
}
template <class T, class A0, class A1, class A2, class A3, class A4>
void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
(void) Obj;
}
template <class T, class A0, class A1, class A2>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
return new (Buffer) T(N, a0, a1, a2);
}
void popCleanup();
class EHCatchScope *pushCatch(unsigned NumHandlers);
void popCatch();
class EHFilterScope *pushFilter(unsigned NumFilters);
void popFilter();
void pushTerminate();
void popTerminate();
bool empty() const { return StartOfData == EndOfBuffer; }
bool requiresLandingPad() const {
return InnermostEHScope != stable_end();
}
bool hasNormalCleanups() const {
return InnermostNormalCleanup != stable_end();
}
stable_iterator getInnermostNormalCleanup() const {
return InnermostNormalCleanup;
}
stable_iterator getInnermostActiveNormalCleanup() const;
stable_iterator getInnermostEHScope() const {
return InnermostEHScope;
}
stable_iterator getInnermostActiveEHScope() const;
class iterator;
iterator begin() const;
iterator end() const;
stable_iterator stable_begin() const {
return stable_iterator(EndOfBuffer - StartOfData);
}
static stable_iterator stable_end() {
return stable_iterator(0);
}
stable_iterator stabilize(iterator it) const;
iterator find(stable_iterator save) const;
void removeCleanup(stable_iterator save);
BranchFixup &addBranchFixup() {
assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
BranchFixups.push_back(BranchFixup());
return BranchFixups.back();
}
unsigned getNumBranchFixups() const { return BranchFixups.size(); }
BranchFixup &getBranchFixup(unsigned I) {
assert(I < getNumBranchFixups());
return BranchFixups[I];
}
void popNullFixups();
void clearFixups() { BranchFixups.clear(); }
};
class CodeGenFunction : public CodeGenTypeCache {
CodeGenFunction(const CodeGenFunction&); void operator=(const CodeGenFunction&);
friend class CGCXXABI;
public:
struct JumpDest {
JumpDest() : Block(0), ScopeDepth(), Index(0) {}
JumpDest(llvm::BasicBlock *Block,
EHScopeStack::stable_iterator Depth,
unsigned Index)
: Block(Block), ScopeDepth(Depth), Index(Index) {}
bool isValid() const { return Block != 0; }
llvm::BasicBlock *getBlock() const { return Block; }
EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
unsigned getDestIndex() const { return Index; }
private:
llvm::BasicBlock *Block;
EHScopeStack::stable_iterator ScopeDepth;
unsigned Index;
};
CodeGenModule &CGM; const TargetInfo &Target;
typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy;
CGBuilderTy Builder;
const Decl *CurFuncDecl;
const Decl *CurCodeDecl;
const CGFunctionInfo *CurFnInfo;
QualType FnRetTy;
llvm::Function *CurFn;
GlobalDecl CurGD;
EHScopeStack::stable_iterator PrologueCleanupDepth;
JumpDest ReturnBlock;
llvm::Value *ReturnValue;
llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
bool CatchUndefined;
bool AutoreleaseResult;
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField;
llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags;
EHScopeStack EHStack;
llvm::AllocaInst *NormalCleanupDest;
unsigned NextCleanupDestIndex;
CGBlockInfo *FirstBlockInfo;
llvm::BasicBlock *EHResumeBlock;
llvm::Value *ExceptionSlot;
llvm::AllocaInst *EHSelectorSlot;
llvm::BasicBlock *EmitLandingPad();
llvm::BasicBlock *getInvokeDestImpl();
template <class T>
typename DominatingValue<T>::saved_type saveValueInCond(T value) {
return DominatingValue<T>::save(*this, value);
}
public:
SmallVector<llvm::Value*, 8> ObjCEHValueStack;
class FinallyInfo {
JumpDest RethrowDest;
llvm::Constant *BeginCatchFn;
llvm::AllocaInst *ForEHVar;
llvm::AllocaInst *SavedExnVar;
public:
void enter(CodeGenFunction &CGF, const Stmt *Finally,
llvm::Constant *beginCatchFn, llvm::Constant *endCatchFn,
llvm::Constant *rethrowFn);
void exit(CodeGenFunction &CGF);
};
template <class T, class A0>
void pushFullExprCleanup(CleanupKind kind, A0 a0) {
if (!isInConditionalBranch())
return EHStack.pushCleanup<T>(kind, a0);
typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved);
initFullExprCleanup();
}
template <class T, class A0, class A1>
void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) {
if (!isInConditionalBranch())
return EHStack.pushCleanup<T>(kind, a0, a1);
typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved);
initFullExprCleanup();
}
template <class T, class A0, class A1, class A2>
void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2) {
if (!isInConditionalBranch()) {
return EHStack.pushCleanup<T>(kind, a0, a1, a2);
}
typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2);
typedef EHScopeStack::ConditionalCleanup3<T, A0, A1, A2> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved, a2_saved);
initFullExprCleanup();
}
template <class T, class A0, class A1, class A2, class A3>
void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2, A3 a3) {
if (!isInConditionalBranch()) {
return EHStack.pushCleanup<T>(kind, a0, a1, a2, a3);
}
typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2);
typename DominatingValue<A3>::saved_type a3_saved = saveValueInCond(a3);
typedef EHScopeStack::ConditionalCleanup4<T, A0, A1, A2, A3> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved,
a2_saved, a3_saved);
initFullExprCleanup();
}
void initFullExprCleanup();
void PushDestructorCleanup(QualType T, llvm::Value *Addr);
void PushDestructorCleanup(const CXXDestructorDecl *Dtor,
llvm::Value *Addr);
void PopCleanupBlock(bool FallThroughIsBranchThrough = false);
void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup,
llvm::Instruction *DominatingIP);
void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup,
llvm::Instruction *DominatingIP);
class RunCleanupsScope {
EHScopeStack::stable_iterator CleanupStackDepth;
bool OldDidCallStackSave;
bool PerformCleanup;
RunCleanupsScope(const RunCleanupsScope &); RunCleanupsScope &operator=(const RunCleanupsScope &);
protected:
CodeGenFunction& CGF;
public:
explicit RunCleanupsScope(CodeGenFunction &CGF)
: PerformCleanup(true), CGF(CGF)
{
CleanupStackDepth = CGF.EHStack.stable_begin();
OldDidCallStackSave = CGF.DidCallStackSave;
CGF.DidCallStackSave = false;
}
~RunCleanupsScope() {
if (PerformCleanup) {
CGF.DidCallStackSave = OldDidCallStackSave;
CGF.PopCleanupBlocks(CleanupStackDepth);
}
}
bool requiresCleanups() const {
return CGF.EHStack.stable_begin() != CleanupStackDepth;
}
void ForceCleanup() {
assert(PerformCleanup && "Already forced cleanup");
CGF.DidCallStackSave = OldDidCallStackSave;
CGF.PopCleanupBlocks(CleanupStackDepth);
PerformCleanup = false;
}
};
class LexicalScope: protected RunCleanupsScope {
SourceRange Range;
bool PopDebugStack;
LexicalScope(const LexicalScope &); LexicalScope &operator=(const LexicalScope &);
public:
explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range)
: RunCleanupsScope(CGF), Range(Range), PopDebugStack(true) {
if (CGDebugInfo *DI = CGF.getDebugInfo())
DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin());
}
~LexicalScope() {
if (PopDebugStack) {
CGDebugInfo *DI = CGF.getDebugInfo();
if (DI) DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd());
}
}
void ForceCleanup() {
RunCleanupsScope::ForceCleanup();
if (CGDebugInfo *DI = CGF.getDebugInfo()) {
DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd());
PopDebugStack = false;
}
}
};
void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize);
void ResolveBranchFixups(llvm::BasicBlock *Target);
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) {
return JumpDest(Target,
EHStack.getInnermostNormalCleanup(),
NextCleanupDestIndex++);
}
JumpDest getJumpDestInCurrentScope(StringRef Name = StringRef()) {
return getJumpDestInCurrentScope(createBasicBlock(Name));
}
void EmitBranchThroughCleanup(JumpDest Dest);
bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const;
void popCatchScope();
llvm::BasicBlock *getEHResumeBlock();
llvm::BasicBlock *getEHDispatchBlock(EHScopeStack::stable_iterator scope);
class ConditionalEvaluation {
llvm::BasicBlock *StartBB;
public:
ConditionalEvaluation(CodeGenFunction &CGF)
: StartBB(CGF.Builder.GetInsertBlock()) {}
void begin(CodeGenFunction &CGF) {
assert(CGF.OutermostConditional != this);
if (!CGF.OutermostConditional)
CGF.OutermostConditional = this;
}
void end(CodeGenFunction &CGF) {
assert(CGF.OutermostConditional != 0);
if (CGF.OutermostConditional == this)
CGF.OutermostConditional = 0;
}
llvm::BasicBlock *getStartingBlock() const {
return StartBB;
}
};
bool isInConditionalBranch() const { return OutermostConditional != 0; }
void setBeforeOutermostConditional(llvm::Value *value, llvm::Value *addr) {
assert(isInConditionalBranch());
llvm::BasicBlock *block = OutermostConditional->getStartingBlock();
new llvm::StoreInst(value, addr, &block->back());
}
class StmtExprEvaluation {
CodeGenFunction &CGF;
ConditionalEvaluation *SavedOutermostConditional;
public:
StmtExprEvaluation(CodeGenFunction &CGF)
: CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) {
CGF.OutermostConditional = 0;
}
~StmtExprEvaluation() {
CGF.OutermostConditional = SavedOutermostConditional;
CGF.EnsureInsertPoint();
}
};
class PeepholeProtection {
llvm::Instruction *Inst;
friend class CodeGenFunction;
public:
PeepholeProtection() : Inst(0) {}
};
class OpaqueValueMappingData {
const OpaqueValueExpr *OpaqueValue;
bool BoundLValue;
CodeGenFunction::PeepholeProtection Protection;
OpaqueValueMappingData(const OpaqueValueExpr *ov,
bool boundLValue)
: OpaqueValue(ov), BoundLValue(boundLValue) {}
public:
OpaqueValueMappingData() : OpaqueValue(0) {}
static bool shouldBindAsLValue(const Expr *expr) {
return expr->isGLValue() ||
expr->getType()->isRecordType() ||
expr->getType()->isFunctionType();
}
static OpaqueValueMappingData bind(CodeGenFunction &CGF,
const OpaqueValueExpr *ov,
const Expr *e) {
if (shouldBindAsLValue(ov))
return bind(CGF, ov, CGF.EmitLValue(e));
return bind(CGF, ov, CGF.EmitAnyExpr(e));
}
static OpaqueValueMappingData bind(CodeGenFunction &CGF,
const OpaqueValueExpr *ov,
const LValue &lv) {
assert(shouldBindAsLValue(ov));
CGF.OpaqueLValues.insert(std::make_pair(ov, lv));
return OpaqueValueMappingData(ov, true);
}
static OpaqueValueMappingData bind(CodeGenFunction &CGF,
const OpaqueValueExpr *ov,
const RValue &rv) {
assert(!shouldBindAsLValue(ov));
CGF.OpaqueRValues.insert(std::make_pair(ov, rv));
OpaqueValueMappingData data(ov, false);
data.Protection = CGF.protectFromPeepholes(rv);
return data;
}
bool isValid() const { return OpaqueValue != 0; }
void clear() { OpaqueValue = 0; }
void unbind(CodeGenFunction &CGF) {
assert(OpaqueValue && "no data to unbind!");
if (BoundLValue) {
CGF.OpaqueLValues.erase(OpaqueValue);
} else {
CGF.OpaqueRValues.erase(OpaqueValue);
CGF.unprotectFromPeepholes(Protection);
}
}
};
class OpaqueValueMapping {
CodeGenFunction &CGF;
OpaqueValueMappingData Data;
public:
static bool shouldBindAsLValue(const Expr *expr) {
return OpaqueValueMappingData::shouldBindAsLValue(expr);
}
OpaqueValueMapping(CodeGenFunction &CGF,
const AbstractConditionalOperator *op) : CGF(CGF) {
if (isa<ConditionalOperator>(op))
return;
const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op);
Data = OpaqueValueMappingData::bind(CGF, e->getOpaqueValue(),
e->getCommon());
}
OpaqueValueMapping(CodeGenFunction &CGF,
const OpaqueValueExpr *opaqueValue,
LValue lvalue)
: CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, lvalue)) {
}
OpaqueValueMapping(CodeGenFunction &CGF,
const OpaqueValueExpr *opaqueValue,
RValue rvalue)
: CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) {
}
void pop() {
Data.unbind(CGF);
Data.clear();
}
~OpaqueValueMapping() {
if (Data.isValid()) Data.unbind(CGF);
}
};
unsigned getByRefValueLLVMField(const ValueDecl *VD) const;
llvm::Value *BuildBlockByrefAddress(llvm::Value *BaseAddr,
const VarDecl *V);
private:
CGDebugInfo *DebugInfo;
bool DisableDebugInfo;
bool DidCallStackSave;
llvm::IndirectBrInst *IndirectBranch;
typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
struct BreakContinue {
BreakContinue(JumpDest Break, JumpDest Continue)
: BreakBlock(Break), ContinueBlock(Continue) {}
JumpDest BreakBlock;
JumpDest ContinueBlock;
};
SmallVector<BreakContinue, 8> BreakContinueStack;
llvm::SwitchInst *SwitchInsn;
llvm::BasicBlock *CaseRangeBlock;
llvm::DenseMap<const OpaqueValueExpr *, LValue> OpaqueLValues;
llvm::DenseMap<const OpaqueValueExpr *, RValue> OpaqueRValues;
llvm::DenseMap<const Expr*, llvm::Value*> VLASizeMap;
llvm::BasicBlock *UnreachableBlock;
ImplicitParamDecl *CXXABIThisDecl;
llvm::Value *CXXABIThisValue;
llvm::Value *CXXThisValue;
ImplicitParamDecl *CXXVTTDecl;
llvm::Value *CXXVTTValue;
ConditionalEvaluation *OutermostConditional;
llvm::DenseMap<const ValueDecl *, std::pair<llvm::Type *,
unsigned> > ByRefValueInfo;
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
llvm::BasicBlock *TrapBB;
public:
CodeGenFunction(CodeGenModule &cgm);
~CodeGenFunction();
CodeGenTypes &getTypes() const { return CGM.getTypes(); }
ASTContext &getContext() const { return CGM.getContext(); }
CGDebugInfo *getDebugInfo() {
if (DisableDebugInfo)
return NULL;
return DebugInfo;
}
void disableDebugInfo() { DisableDebugInfo = true; }
void enableDebugInfo() { DisableDebugInfo = false; }
bool shouldUseFusedARCCalls() {
return CGM.getCodeGenOpts().OptimizationLevel == 0;
}
const LangOptions &getLangOptions() const { return CGM.getLangOptions(); }
llvm::Value *getExceptionSlot();
llvm::Value *getEHSelectorSlot();
llvm::Value *getExceptionFromSlot();
llvm::Value *getSelectorFromSlot();
llvm::Value *getNormalCleanupDestSlot();
llvm::BasicBlock *getUnreachableBlock() {
if (!UnreachableBlock) {
UnreachableBlock = createBasicBlock("unreachable");
new llvm::UnreachableInst(getLLVMContext(), UnreachableBlock);
}
return UnreachableBlock;
}
llvm::BasicBlock *getInvokeDest() {
if (!EHStack.requiresLandingPad()) return 0;
return getInvokeDestImpl();
}
llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); }
typedef void Destroyer(CodeGenFunction &CGF, llvm::Value *addr, QualType ty);
void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Value *arrayEndPointer,
QualType elementType,
Destroyer *destroyer);
void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Value *arrayEnd,
QualType elementType,
Destroyer *destroyer);
void pushDestroy(QualType::DestructionKind dtorKind,
llvm::Value *addr, QualType type);
void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray);
void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
llvm::Function *generateDestroyHelper(llvm::Constant *addr,
QualType type,
Destroyer *destroyer,
bool useEHCleanupForArray);
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end,
QualType type, Destroyer *destroyer,
bool checkZeroLength, bool useEHCleanup);
Destroyer *getDestroyer(QualType::DestructionKind destructionKind);
bool needsEHCleanup(QualType::DestructionKind kind) {
switch (kind) {
case QualType::DK_none:
return false;
case QualType::DK_cxx_destructor:
case QualType::DK_objc_weak_lifetime:
return getLangOptions().Exceptions;
case QualType::DK_objc_strong_lifetime:
return getLangOptions().Exceptions &&
CGM.getCodeGenOpts().ObjCAutoRefCountExceptions;
}
llvm_unreachable("bad destruction kind");
}
CleanupKind getCleanupKind(QualType::DestructionKind kind) {
return (needsEHCleanup(kind) ? NormalAndEHCleanup : NormalCleanup);
}
void GenerateObjCMethod(const ObjCMethodDecl *OMD);
void StartObjCMethod(const ObjCMethodDecl *MD,
const ObjCContainerDecl *CD,
SourceLocation StartLoc);
void GenerateObjCGetter(ObjCImplementationDecl *IMP,
const ObjCPropertyImplDecl *PID);
void generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
llvm::Constant *AtomicHelperFn);
void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
ObjCMethodDecl *MD, bool ctor);
void GenerateObjCSetter(ObjCImplementationDecl *IMP,
const ObjCPropertyImplDecl *PID);
void generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
llvm::Constant *AtomicHelperFn);
bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
bool IvarTypeWithAggrGCObjects(QualType Ty);
llvm::Value *EmitBlockLiteral(const BlockExpr *);
llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
const CGBlockInfo &Info,
llvm::StructType *,
llvm::Constant *BlockVarLayout);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &Info,
const Decl *OuterFuncDecl,
const DeclMapTy &ldm,
bool IsLambdaConversionToBlock);
llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateObjCAtomicSetterCopyHelperFunction(
const ObjCPropertyImplDecl *PID);
llvm::Constant *GenerateObjCAtomicGetterCopyHelperFunction(
const ObjCPropertyImplDecl *PID);
llvm::Value *EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty);
void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);
class AutoVarEmission;
void emitByrefStructureInit(const AutoVarEmission &emission);
void enterByrefCleanup(const AutoVarEmission &emission);
llvm::Value *LoadBlockStruct() {
assert(BlockPointer && "no block pointer set!");
return BlockPointer;
}
void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
void AllocateBlockDecl(const BlockDeclRefExpr *E);
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
return GetAddrOfBlockDecl(E->getDecl(), E->isByRef());
}
llvm::Value *GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
llvm::Type *BuildByRefType(const VarDecl *var);
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
void StartFunction(GlobalDecl GD, QualType RetTy,
llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
const FunctionArgList &Args,
SourceLocation StartLoc);
void EmitConstructorBody(FunctionArgList &Args);
void EmitDestructorBody(FunctionArgList &Args);
void EmitFunctionBody(FunctionArgList &Args);
void EmitForwardingCallToLambda(const CXXRecordDecl *Lambda,
CallArgList &CallArgs);
void EmitLambdaToBlockPointerBody(FunctionArgList &Args);
void EmitLambdaBlockInvokeBody();
void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
void EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD);
void EmitReturnBlock();
void FinishFunction(SourceLocation EndLoc=SourceLocation());
void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk);
void GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk);
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
FunctionArgList &Args);
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes);
void InitializeVTablePointer(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
llvm::Constant *VTable,
const CXXRecordDecl *VTableClass);
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
void InitializeVTablePointers(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
llvm::Constant *VTable,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy& VBases);
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type);
bool ShouldInstrumentFunction();
void EmitFunctionInstrumentation(const char *Fn);
void EmitMCountInstrumentation();
void EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Function *Fn,
const FunctionArgList &Args);
void EmitFunctionEpilog(const CGFunctionInfo &FI);
void EmitStartEHSpec(const Decl *D);
void EmitEndEHSpec(const Decl *D);
llvm::BasicBlock *getTerminateLandingPad();
llvm::BasicBlock *getTerminateHandler();
llvm::Type *ConvertTypeForMem(QualType T);
llvm::Type *ConvertType(QualType T);
llvm::Type *ConvertType(const TypeDecl *T) {
return ConvertType(getContext().getTypeDeclType(T));
}
llvm::Value *LoadObjCSelf();
QualType TypeOfSelfObject();
static bool hasAggregateLLVMType(QualType T);
llvm::BasicBlock *createBasicBlock(StringRef name = "",
llvm::Function *parent = 0,
llvm::BasicBlock *before = 0) {
#ifdef NDEBUG
return llvm::BasicBlock::Create(getLLVMContext(), "", parent, before);
#else
return llvm::BasicBlock::Create(getLLVMContext(), name, parent, before);
#endif
}
JumpDest getJumpDestForLabel(const LabelDecl *S);
void SimplifyForwardingBlocks(llvm::BasicBlock *BB);
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false);
void EmitBlockAfterUses(llvm::BasicBlock *BB);
void EmitBranch(llvm::BasicBlock *Block);
bool HaveInsertPoint() const {
return Builder.GetInsertBlock() != 0;
}
void EnsureInsertPoint() {
if (!HaveInsertPoint())
EmitBlock(createBasicBlock());
}
void ErrorUnsupported(const Stmt *S, const char *Type,
bool OmitOnError=false);
LValue MakeAddrLValue(llvm::Value *V, QualType T,
CharUnits Alignment = CharUnits()) {
return LValue::MakeAddr(V, T, Alignment, getContext(),
CGM.getTBAAInfo(T));
}
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
CharUnits Alignment;
if (!T->isIncompleteType())
Alignment = getContext().getTypeAlignInChars(T);
return LValue::MakeAddr(V, T, Alignment, getContext(),
CGM.getTBAAInfo(T));
}
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty,
const Twine &Name = "tmp");
void InitTempAlloca(llvm::AllocaInst *Alloca, llvm::Value *Value);
llvm::AllocaInst *CreateIRTemp(QualType T, const Twine &Name = "tmp");
llvm::AllocaInst *CreateMemTemp(QualType T, const Twine &Name = "tmp");
AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") {
CharUnits Alignment = getContext().getTypeAlignInChars(T);
return AggValueSlot::forAddr(CreateMemTemp(T, Name), Alignment,
T.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
}
llvm::Value *EmitCastToVoidPtr(llvm::Value *value);
llvm::Value *EvaluateExprAsBool(const Expr *E);
void EmitIgnoredExpr(const Expr *E);
RValue EmitAnyExpr(const Expr *E,
AggValueSlot AggSlot = AggValueSlot::ignored(),
bool IgnoreResult = false);
llvm::Value *EmitVAListRef(const Expr *E);
RValue EmitAnyExprToTemp(const Expr *E);
void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
Qualifiers Quals, bool IsInitializer);
void EmitExprAsInit(const Expr *init, const ValueDecl *D,
LValue lvalue, bool capturedByInit);
void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
QualType EltTy, bool isVolatile=false,
unsigned Alignment = 0);
void StartBlock(const char *N);
llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD) {
return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
}
llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
llvm::Value *Res = LocalDeclMap[VD];
assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
return Res;
}
const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
assert(OpaqueValueMapping::shouldBindAsLValue(e));
llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
it = OpaqueLValues.find(e);
assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
return it->second;
}
const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
assert(!OpaqueValueMapping::shouldBindAsLValue(e));
llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
it = OpaqueRValues.find(e);
assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
return it->second;
}
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L);
llvm::BasicBlock *GetIndirectGotoBlock();
void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty);
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
llvm::Value *emitArrayLength(const ArrayType *arrayType,
QualType &baseType,
llvm::Value *&addr);
void EmitVariablyModifiedType(QualType Ty);
std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla);
std::pair<llvm::Value*,QualType> getVLASize(QualType vla);
llvm::Value *LoadCXXThis() {
assert(CXXThisValue && "no 'this' value for this function");
return CXXThisValue;
}
llvm::Value *LoadCXXVTT() {
assert(CXXVTTValue && "no VTT value for this function");
return CXXVTTValue;
}
llvm::Value *
GetAddressOfDirectBaseInCompleteClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
bool BaseIsVirtual);
llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetVirtualBaseClassOffset(llvm::Value *This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl);
void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
CXXCtorType CtorType,
const FunctionArgList &Args);
void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args);
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
llvm::Value *This, llvm::Value *Src,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
const ConstantArrayType *ArrayTy,
llvm::Value *ArrayPtr,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
bool ZeroInitialization = false);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
llvm::Value *ArrayPtr,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
bool ZeroInitialization = false);
static Destroyer destroyCXXObject;
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
bool ForVirtualBase, llvm::Value *This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
llvm::Value *NewPtr, llvm::Value *NumElements);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
llvm::Value *Ptr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
QualType DeleteTy);
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
void MaybeEmitStdInitializerListCleanup(llvm::Value *loc, const Expr *init);
void EmitStdInitializerListCleanup(llvm::Value *loc,
const InitListExpr *init);
void EmitCheck(llvm::Value *, unsigned Size);
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
void EmitDecl(const Decl &D);
void EmitVarDecl(const VarDecl &D);
void EmitScalarInit(const Expr *init, const ValueDecl *D,
LValue lvalue, bool capturedByInit);
void EmitScalarInit(llvm::Value *init, LValue lvalue);
typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
llvm::Value *Address);
void EmitAutoVarDecl(const VarDecl &D);
class AutoVarEmission {
friend class CodeGenFunction;
const VarDecl *Variable;
CharUnits Alignment;
llvm::Value *Address;
llvm::Value *NRVOFlag;
bool IsByRef;
bool IsConstantAggregate;
struct Invalid {};
AutoVarEmission(Invalid) : Variable(0) {}
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Address(0), NRVOFlag(0),
IsByRef(false), IsConstantAggregate(false) {}
bool wasEmittedAsGlobal() const { return Address == 0; }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
if (!IsByRef) return Address;
return CGF.Builder.CreateStructGEP(Address,
CGF.getByRefValueLLVMField(Variable),
Variable->getNameAsString());
}
};
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
void EmitAutoVarInit(const AutoVarEmission &emission);
void EmitAutoVarCleanups(const AutoVarEmission &emission);
void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
QualType::DestructionKind dtorKind);
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, unsigned ArgNo);
PeepholeProtection protectFromPeepholes(RValue rvalue);
void unprotectFromPeepholes(PeepholeProtection protection);
void EmitStopPoint(const Stmt *S);
void EmitStmt(const Stmt *S);
bool EmitSimpleStmt(const Stmt *S);
RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
AggValueSlot AVS = AggValueSlot::ignored());
void EmitLabel(const LabelDecl *D);
void EmitLabelStmt(const LabelStmt &S);
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
void EmitWhileStmt(const WhileStmt &S);
void EmitDoStmt(const DoStmt &S);
void EmitForStmt(const ForStmt &S);
void EmitReturnStmt(const ReturnStmt &S);
void EmitDeclStmt(const DeclStmt &S);
void EmitBreakStmt(const BreakStmt &S);
void EmitContinueStmt(const ContinueStmt &S);
void EmitSwitchStmt(const SwitchStmt &S);
void EmitDefaultStmt(const DefaultStmt &S);
void EmitCaseStmt(const CaseStmt &S);
void EmitCaseStmtRange(const CaseStmt &S);
void EmitAsmStmt(const AsmStmt &S);
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S);
llvm::Constant *getUnwindResumeFn();
llvm::Constant *getUnwindResumeOrRethrowFn();
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S);
RValue GetUndefRValue(QualType Ty);
RValue EmitUnsupportedRValue(const Expr *E,
const char *Name);
LValue EmitUnsupportedLValue(const Expr *E,
const char *Name);
LValue EmitLValue(const Expr *E);
LValue EmitCheckedLValue(const Expr *E);
llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty);
llvm::Value *EmitFromMemory(llvm::Value *Value, QualType Ty);
llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
llvm::MDNode *TBAAInfo = 0);
llvm::Value *EmitLoadOfScalar(LValue lvalue);
void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
bool Volatile, unsigned Alignment, QualType Ty,
llvm::MDNode *TBAAInfo = 0, bool isInit=false);
void EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit=false);
RValue EmitLoadOfLValue(LValue V);
RValue EmitLoadOfExtVectorElementLValue(LValue V);
RValue EmitLoadOfBitfieldLValue(LValue LV);
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false);
void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst);
void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
llvm::Value **Result=0);
LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
LValue EmitCompoundAssignmentLValue(const CompoundAssignOperator *E);
LValue EmitCallExprLValue(const CallExpr *E);
LValue EmitVAArgExprLValue(const VAArgExpr *E);
LValue EmitDeclRefLValue(const DeclRefExpr *E);
LValue EmitStringLiteralLValue(const StringLiteral *E);
LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
LValue EmitPredefinedLValue(const PredefinedExpr *E);
LValue EmitUnaryOpLValue(const UnaryOperator *E);
LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E);
LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E);
LValue EmitMemberExpr(const MemberExpr *E);
LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
AggValueSlot slot = AggValueSlot::ignored());
LValue EmitPseudoObjectLValue(const PseudoObjectExpr *e);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
LValue EmitLValueForAnonRecordField(llvm::Value* Base,
const IndirectFieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForFieldInitialization(llvm::Value* Base,
const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForIvar(QualType ObjectTy,
llvm::Value* Base, const ObjCIvarDecl *Ivar,
unsigned CVRQualifiers);
LValue EmitLValueForBitfield(llvm::Value* Base, const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitBlockDeclRefLValue(const BlockDeclRefExpr *E);
LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
LValue EmitLambdaLValue(const LambdaExpr *E);
LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
LValue EmitStmtExprLValue(const StmtExpr *E);
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
RValue EmitCall(const CGFunctionInfo &FnInfo,
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
const CallArgList &Args,
const Decl *TargetDecl = 0,
llvm::Instruction **callOrInvoke = 0);
RValue EmitCall(QualType FnType, llvm::Value *Callee,
ReturnValueSlot ReturnValue,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
const Decl *TargetDecl = 0);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name = "");
llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
const Twine &Name = "");
llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
llvm::Type *Ty);
llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
llvm::Value *This, llvm::Type *Ty);
llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Type *Ty);
llvm::Value *BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
const CXXRecordDecl *RD);
RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
llvm::Value *This,
llvm::Value *VTT,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
llvm::Value *EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD,
llvm::Value *This);
RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD,
ReturnValueSlot ReturnValue);
RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
ReturnValueSlot ReturnValue);
RValue EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E);
RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitNeonCall(llvm::Function *F,
SmallVectorImpl<llvm::Value*> &O,
const char *name,
unsigned shift = 0, bool rightshift = false);
llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx);
llvm::Value *EmitNeonShiftVector(llvm::Value *V, llvm::Type *Ty,
bool negateForRightShift);
llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
llvm::Value *EmitObjCBoxedExpr(const ObjCBoxedExpr *E);
llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E);
llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E);
llvm::Value *EmitObjCCollectionLiteral(const Expr *E,
const ObjCMethodDecl *MethodWithObjects);
llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
RValue EmitObjCMessageExpr(const ObjCMessageExpr *E,
ReturnValueSlot Return = ReturnValueSlot());
CleanupKind getARCCleanupKind() {
return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions
? NormalAndEHCleanup : NormalCleanup;
}
void EmitARCInitWeak(llvm::Value *value, llvm::Value *addr);
void EmitARCDestroyWeak(llvm::Value *addr);
llvm::Value *EmitARCLoadWeak(llvm::Value *addr);
llvm::Value *EmitARCLoadWeakRetained(llvm::Value *addr);
llvm::Value *EmitARCStoreWeak(llvm::Value *value, llvm::Value *addr,
bool ignored);
void EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src);
void EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src);
llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainAutoreleaseNonBlock(llvm::Value *value);
llvm::Value *EmitARCStoreStrong(LValue lvalue, llvm::Value *value,
bool ignored);
llvm::Value *EmitARCStoreStrongCall(llvm::Value *addr, llvm::Value *value,
bool ignored);
llvm::Value *EmitARCRetain(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainNonBlock(llvm::Value *value);
llvm::Value *EmitARCRetainBlock(llvm::Value *value, bool mandatory);
void EmitARCRelease(llvm::Value *value, bool precise);
llvm::Value *EmitARCAutorelease(llvm::Value *value);
llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value);
llvm::Value *EmitARCRetainAutoreleaseReturnValue(llvm::Value *value);
llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
std::pair<LValue,llvm::Value*>
EmitARCStoreAutoreleasing(const BinaryOperator *e);
std::pair<LValue,llvm::Value*>
EmitARCStoreStrong(const BinaryOperator *e, bool ignored);
llvm::Value *EmitObjCThrowOperand(const Expr *expr);
llvm::Value *EmitObjCProduceObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);
llvm::Value *EmitARCExtendBlockObject(const Expr *expr);
llvm::Value *EmitARCRetainScalarExpr(const Expr *expr);
llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr);
static Destroyer destroyARCStrongImprecise;
static Destroyer destroyARCStrongPrecise;
static Destroyer destroyARCWeak;
void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr);
llvm::Value *EmitObjCAutoreleasePoolPush();
llvm::Value *EmitObjCMRRAutoreleasePoolPush();
void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr);
void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr);
RValue EmitReferenceBindingToExpr(const Expr* E,
const NamedDecl *InitializedDecl);
llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false);
llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy,
QualType DstTy);
llvm::Value *EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy,
QualType DstTy);
void EmitAggExpr(const Expr *E, AggValueSlot AS, bool IgnoreResult = false);
LValue EmitAggExprToLValue(const Expr *E);
void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr,
QualType Ty);
void EmitExtendGCLifetime(llvm::Value *object);
ComplexPairTy EmitComplexExpr(const Expr *E,
bool IgnoreReal = false,
bool IgnoreImag = false);
void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
bool DestIsVolatile);
void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
bool DestIsVolatile);
ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
llvm::GlobalVariable *CreateStaticVarDecl(const VarDecl &D,
const char *Separator,
llvm::GlobalValue::LinkageTypes Linkage);
llvm::GlobalVariable *
AddInitializerToStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV);
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr,
bool PerformInit);
void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr);
void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr,
bool PerformInit);
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
llvm::Constant **Decls,
unsigned NumDecls);
void GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakVH,
llvm::Constant*> > &DtorsAndObjects);
void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit);
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
const Expr *Exp);
void enterFullExpression(const ExprWithCleanups *E) {
if (E->getNumObjects() == 0) return;
enterNonTrivialFullExpression(E);
}
void enterNonTrivialFullExpression(const ExprWithCleanups *E);
void EmitCXXThrowExpr(const CXXThrowExpr *E);
void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);
RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = 0);
llvm::Value *EmitAnnotationCall(llvm::Value *AnnotationFn,
llvm::Value *AnnotatedVal,
llvm::StringRef AnnotationStr,
SourceLocation Location);
void EmitVarAnnotations(const VarDecl *D, llvm::Value *V);
llvm::Value *EmitFieldAnnotations(const FieldDecl *D, llvm::Value *V);
static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts = false);
static bool containsBreak(const Stmt *S);
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result);
bool ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &Result);
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock);
llvm::BasicBlock *getTrapBB();
void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType);
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param);
void SetFPAccuracy(llvm::Value *Val, unsigned AccuracyN,
unsigned AccuracyD = 1);
private:
void EmitReturnOfRValue(RValue RV, QualType Ty);
llvm::Function::arg_iterator
ExpandTypeFromArgs(QualType Ty, LValue Dst,
llvm::Function::arg_iterator AI);
void ExpandTypeToArgs(QualType Ty, RValue Src,
SmallVector<llvm::Value*, 16> &Args,
llvm::FunctionType *IRFuncTy);
llvm::Value* EmitAsmInput(const AsmStmt &S,
const TargetInfo::ConstraintInfo &Info,
const Expr *InputExpr, std::string &ConstraintStr);
llvm::Value* EmitAsmInputLValue(const AsmStmt &S,
const TargetInfo::ConstraintInfo &Info,
LValue InputValue, QualType InputType,
std::string &ConstraintStr);
template<typename T>
void EmitCallArgs(CallArgList& Args, const T* CallArgTypeInfo,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
CallExpr::const_arg_iterator Arg = ArgBeg;
if (CallArgTypeInfo) {
for (typename T::arg_type_iterator I = CallArgTypeInfo->arg_type_begin(),
E = CallArgTypeInfo->arg_type_end(); I != E; ++I, ++Arg) {
assert(Arg != ArgEnd && "Running over edge of argument list!");
QualType ArgType = *I;
#ifndef NDEBUG
QualType ActualArgType = Arg->getType();
if (ArgType->isPointerType() && ActualArgType->isPointerType()) {
QualType ActualBaseType =
ActualArgType->getAs<PointerType>()->getPointeeType();
QualType ArgBaseType =
ArgType->getAs<PointerType>()->getPointeeType();
if (ArgBaseType->isVariableArrayType()) {
if (const VariableArrayType *VAT =
getContext().getAsVariableArrayType(ActualBaseType)) {
if (!VAT->getSizeExpr())
ActualArgType = ArgType;
}
}
}
assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
getTypePtr() ==
getContext().getCanonicalType(ActualArgType).getTypePtr() &&
"type mismatch in call argument!");
#endif
EmitCallArg(Args, *Arg, ArgType);
}
assert((Arg == ArgEnd || CallArgTypeInfo->isVariadic()) &&
"Extra arguments in non-variadic function!");
}
for (; Arg != ArgEnd; ++Arg)
EmitCallArg(Args, *Arg, Arg->getType());
}
const TargetCodeGenInfo &getTargetHooks() const {
return CGM.getTargetCodeGenInfo();
}
void EmitDeclMetadata();
CodeGenModule::ByrefHelpers *
buildByrefHelpers(llvm::StructType &byrefType,
const AutoVarEmission &emission);
void AddObjCARCExceptionMetadata(llvm::Instruction *Inst);
unsigned GetPointeeAlignment(const Expr *Addr);
llvm::Value *GetPointeeAlignmentValue(const Expr *Addr);
};
struct DominatingLLVMValue {
typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
static bool needsSaving(llvm::Value *value) {
if (!isa<llvm::Instruction>(value)) return false;
llvm::BasicBlock *block = cast<llvm::Instruction>(value)->getParent();
return (block != &block->getParent()->getEntryBlock());
}
static saved_type save(CodeGenFunction &CGF, llvm::Value *value) {
if (!needsSaving(value)) return saved_type(value, false);
llvm::Value *alloca =
CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save");
CGF.Builder.CreateStore(value, alloca);
return saved_type(alloca, true);
}
static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) {
if (!value.getInt()) return value.getPointer();
return CGF.Builder.CreateLoad(value.getPointer());
}
};
template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
typedef T *type;
static type restore(CodeGenFunction &CGF, saved_type value) {
return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
}
};
template <> struct DominatingValue<RValue> {
typedef RValue type;
class saved_type {
enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
AggregateAddress, ComplexAddress };
llvm::Value *Value;
Kind K;
saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
public:
static bool needsSaving(RValue value);
static saved_type save(CodeGenFunction &CGF, RValue value);
RValue restore(CodeGenFunction &CGF);
};
static bool needsSaving(type value) {
return saved_type::needsSaving(value);
}
static saved_type save(CodeGenFunction &CGF, type value) {
return saved_type::save(CGF, value);
}
static type restore(CodeGenFunction &CGF, saved_type value) {
return value.restore(CGF);
}
};
} }
#endif