diff options
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 414 |
1 files changed, 325 insertions, 89 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index bb8fd8e..f27ed94 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -18,8 +18,10 @@ #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" @@ -63,6 +65,7 @@ namespace clang { class ObjCAtTryStmt; class ObjCAtThrowStmt; class ObjCAtSynchronizedStmt; + class ObjCAutoreleasePoolStmt; namespace CodeGen { class CodeGenTypes; @@ -179,15 +182,39 @@ public: /// Cleanup implementations should generally be declared in an /// anonymous namespace. class Cleanup { + // Anchor the construction vtable. + virtual void anchor(); public: - // Anchor the construction vtable. We use the destructor because - // gcc gives an obnoxious warning if there are virtual methods - // with an accessible non-virtual destructor. Unfortunately, - // declaring this destructor makes it non-trivial, but there - // doesn't seem to be any other way around this warning. - // - // This destructor will never be called. - virtual ~Cleanup(); + /// Generation flags. + class Flags { + enum { + F_IsForEH = 0x1, + F_IsNormalCleanupKind = 0x2, + F_IsEHCleanupKind = 0x4 + }; + unsigned flags; + + public: + Flags() : flags(0) {} + + /// isForEH - true if the current emission is for an EH cleanup. + 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; } + + /// isEHCleanupKind - true if the cleanup was pushed as an EH + /// cleanup. + bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; } + void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; } + }; + + // Provide a virtual destructor to suppress a very common warning + // that unfortunately cannot be suppressed without this. Cleanups + // should not rely on this destructor ever being called. + virtual ~Cleanup() {} /// Emit the cleanup. For normal cleanups, this is run in the /// same EH context as when the cleanup was pushed, i.e. the @@ -196,29 +223,7 @@ public: /// // \param IsForEHCleanup true if this is for an EH cleanup, false /// if for a normal cleanup. - virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0; - }; - - /// UnconditionalCleanupN stores its N parameters and just passes - /// them to the real cleanup function. - template <class T, class A0> - class UnconditionalCleanup1 : public Cleanup { - A0 a0; - public: - UnconditionalCleanup1(A0 a0) : a0(a0) {} - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - T::Emit(CGF, IsForEHCleanup, a0); - } - }; - - template <class T, class A0, class A1> - class UnconditionalCleanup2 : public Cleanup { - A0 a0; A1 a1; - public: - UnconditionalCleanup2(A0 a0, A1 a1) : a0(a0), a1(a1) {} - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - T::Emit(CGF, IsForEHCleanup, a0, a1); - } + virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0; }; /// ConditionalCleanupN stores the saved form of its N parameters, @@ -228,9 +233,9 @@ public: typedef typename DominatingValue<A0>::saved_type A0_saved; A0_saved a0_saved; - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + void Emit(CodeGenFunction &CGF, Flags flags) { A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); - T::Emit(CGF, IsForEHCleanup, a0); + T(a0).Emit(CGF, flags); } public: @@ -245,10 +250,10 @@ public: A0_saved a0_saved; A1_saved a1_saved; - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + void Emit(CodeGenFunction &CGF, Flags flags) { A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); - T::Emit(CGF, IsForEHCleanup, a0, a1); + T(a0, a1).Emit(CGF, flags); } public: @@ -256,6 +261,51 @@ public: : 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: // The implementation for this class is in CGException.h and // CGException.cpp; the definition is here because it's used as a @@ -568,6 +618,10 @@ public: /// CurGD - The GlobalDecl for the current function being compiled. GlobalDecl CurGD; + /// PrologueCleanupDepth - The cleanup depth enclosing all the + /// cleanups associated with the parameters. + EHScopeStack::stable_iterator PrologueCleanupDepth; + /// ReturnBlock - Unified return block. JumpDest ReturnBlock; @@ -584,6 +638,9 @@ public: bool CatchUndefined; + /// In ARC, whether we should autorelease the return value. + bool AutoreleaseResult; + const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; @@ -626,16 +683,28 @@ public: /// rethrows. llvm::SmallVector<llvm::Value*, 8> ObjCEHValueStack; - // A struct holding information about a finally block's IR - // generation. For now, doesn't actually hold anything. - struct FinallyInfo { - }; + /// A class controlling the emission of a finally block. + class FinallyInfo { + /// Where the catchall's edge through the cleanup should go. + JumpDest RethrowDest; + + /// A function to call to enter the catch. + llvm::Constant *BeginCatchFn; - FinallyInfo EnterFinallyBlock(const Stmt *Stmt, - llvm::Constant *BeginCatchFn, - llvm::Constant *EndCatchFn, - llvm::Constant *RethrowFn); - void ExitFinallyBlock(FinallyInfo &FinallyInfo); + /// An i1 variable indicating whether or not the @finally is + /// running for an exception. + llvm::AllocaInst *ForEHVar; + + /// An i8* variable into which the exception pointer to rethrow + /// has been saved. + llvm::AllocaInst *SavedExnVar; + + public: + void enter(CodeGenFunction &CGF, const Stmt *Finally, + llvm::Constant *beginCatchFn, llvm::Constant *endCatchFn, + llvm::Constant *rethrowFn); + void exit(CodeGenFunction &CGF); + }; /// pushFullExprCleanup - Push a cleanup to be run at the end of the /// current full-expression. Safe against the possibility that @@ -644,10 +713,8 @@ public: void pushFullExprCleanup(CleanupKind kind, A0 a0) { // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. - if (!isInConditionalBranch()) { - typedef EHScopeStack::UnconditionalCleanup1<T, A0> CleanupType; - return EHStack.pushCleanup<CleanupType>(kind, a0); - } + if (!isInConditionalBranch()) + return EHStack.pushCleanup<T>(kind, a0); typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0); @@ -663,10 +730,8 @@ public: void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) { // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. - if (!isInConditionalBranch()) { - typedef EHScopeStack::UnconditionalCleanup2<T, A0, A1> CleanupType; - return EHStack.pushCleanup<CleanupType>(kind, a0, 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); @@ -676,6 +741,48 @@ public: initFullExprCleanup(); } + /// pushFullExprCleanup - Push a cleanup to be run at the end of the + /// current full-expression. Safe against the possibility that + /// we're currently inside a conditionally-evaluated expression. + template <class T, class A0, class A1, class A2> + void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2) { + // If we're not in a conditional branch, or if none of the + // arguments requires saving, then use the unconditional cleanup. + 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(); + } + + /// pushFullExprCleanup - Push a cleanup to be run at the end of the + /// current full-expression. Safe against the possibility that + /// we're currently inside a conditionally-evaluated expression. + template <class T, class A0, class A1, class A2, class A3> + void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2, A3 a3) { + // If we're not in a conditional branch, or if none of the + // arguments requires saving, then use the unconditional cleanup. + 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(); + } + /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the /// given address. Does nothing if T is not a C++ class type with a @@ -1048,6 +1155,9 @@ public: void disableDebugInfo() { DisableDebugInfo = true; } void enableDebugInfo() { DisableDebugInfo = false; } + bool shouldUseFusedARCCalls() { + return CGM.getCodeGenOpts().OptimizationLevel == 0; + } const LangOptions &getLangOptions() const { return CGM.getLangOptions(); } @@ -1075,6 +1185,57 @@ public: llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); } //===--------------------------------------------------------------------===// + // Cleanups + //===--------------------------------------------------------------------===// + + 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); + + /// Determines whether an EH cleanup is required to destroy a type + /// with the given destruction kind. + 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); + } + + //===--------------------------------------------------------------------===// // Objective-C //===--------------------------------------------------------------------===// @@ -1236,9 +1397,9 @@ public: /// a terminate scope encloses a try. llvm::BasicBlock *getTerminateHandler(); - const llvm::Type *ConvertTypeForMem(QualType T); - const llvm::Type *ConvertType(QualType T); - const llvm::Type *ConvertType(const TypeDecl *T) { + llvm::Type *ConvertTypeForMem(QualType T); + llvm::Type *ConvertType(QualType T); + llvm::Type *ConvertType(const TypeDecl *T) { return ConvertType(getContext().getTypeDeclType(T)); } @@ -1345,7 +1506,8 @@ public: /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const llvm::Twine &Name = "tmp") { - return AggValueSlot::forAddr(CreateMemTemp(T, Name), false, false); + return AggValueSlot::forAddr(CreateMemTemp(T, Name), T.getQualifiers(), + false); } /// Emit a cast to void* in the appropriate address space. @@ -1379,14 +1541,12 @@ public: /// EmitAnyExprToMem - Emits the code necessary to evaluate an /// arbitrary expression into the given memory location. void EmitAnyExprToMem(const Expr *E, llvm::Value *Location, - bool IsLocationVolatile, - bool IsInitializer); + Qualifiers Quals, bool IsInitializer); /// EmitExprAsInit - Emits the code necessary to initialize a /// location in memory with the given initializer. - void EmitExprAsInit(const Expr *init, const VarDecl *var, - llvm::Value *loc, CharUnits alignment, - bool capturedByInit); + void EmitExprAsInit(const Expr *init, const ValueDecl *D, + LValue lvalue, bool capturedByInit); /// EmitAggregateCopy - Emit an aggrate copy. /// @@ -1451,16 +1611,24 @@ public: // instruction in LLVM instead once it works well enough. llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty); - /// EmitVLASize - Generate code for any VLA size expressions that might occur - /// in a variably modified type. If Ty is a VLA, will return the value that - /// corresponds to the size in bytes of the VLA type. Will return 0 otherwise. + /// emitArrayLength - Compute the length of an array, even if it's a + /// VLA, and drill down to the base element type. + llvm::Value *emitArrayLength(const ArrayType *arrayType, + QualType &baseType, + llvm::Value *&addr); + + /// EmitVLASize - Capture all the sizes for the VLA expressions in + /// the given variably-modified type and store them in the VLASizeMap. /// /// This function can be called with a null (unreachable) insert point. - llvm::Value *EmitVLASize(QualType Ty); + void EmitVariablyModifiedType(QualType Ty); - // GetVLASize - Returns an LLVM value that corresponds to the size in bytes - // of a variable length array type. - llvm::Value *GetVLASize(const VariableArrayType *); + /// getVLASize - Returns an LLVM value that corresponds to the size, + /// in non-variably-sized elements, of a variable length array type, + /// plus that largest non-variably-sized element type. Assumes that + /// the type has already been emitted with EmitVariablyModifiedType. + std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla); + std::pair<llvm::Value*,QualType> getVLASize(QualType vla); /// LoadCXXThis - Load the value of 'this'. This function is only valid while /// generating code for an C++ member function. @@ -1535,17 +1703,7 @@ public: CallExpr::const_arg_iterator ArgEnd, bool ZeroInitialization = false); - void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, - const ArrayType *Array, - llvm::Value *This); - - void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, - llvm::Value *NumElements, - llvm::Value *This); - - llvm::Function *GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, - const ArrayType *Array, - llvm::Value *This); + static Destroyer destroyCXXObject; void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, llvm::Value *This); @@ -1584,6 +1742,10 @@ public: /// This function can be called with a null (unreachable) insert point. 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); @@ -1639,6 +1801,8 @@ public: 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); @@ -1709,6 +1873,7 @@ public: 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(); @@ -1775,6 +1940,12 @@ public: unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo = 0); + /// EmitLoadOfScalar - Load a scalar value from an address, taking + /// care to appropriately convert from the memory representation to + /// the LLVM value representation. The l-value must be a simple + /// l-value. + llvm::Value *EmitLoadOfScalar(LValue lvalue); + /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to /// the LLVM value representation. @@ -1782,21 +1953,26 @@ public: bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo = 0); + /// EmitStoreOfScalar - Store a scalar value to an address, taking + /// care to appropriately convert from the memory representation to + /// the LLVM value representation. The l-value must be a simple + /// l-value. + void EmitStoreOfScalar(llvm::Value *value, LValue lvalue); + /// EmitLoadOfLValue - Given an expression that represents a value lvalue, /// this method emits the address of the lvalue, then loads the result as an /// rvalue, returning the rvalue. - RValue EmitLoadOfLValue(LValue V, QualType LVType); - RValue EmitLoadOfExtVectorElementLValue(LValue V, QualType LVType); - RValue EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType); + RValue EmitLoadOfLValue(LValue V); + RValue EmitLoadOfExtVectorElementLValue(LValue V); + RValue EmitLoadOfBitfieldLValue(LValue LV); RValue EmitLoadOfPropertyRefLValue(LValue LV, ReturnValueSlot Return = ReturnValueSlot()); /// EmitStoreThroughLValue - Store the specified rvalue into the specified /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. - void EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty); - void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst, - QualType Ty); + void EmitStoreThroughLValue(RValue Src, LValue Dst); + void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); void EmitStoreThroughPropertyRefLValue(RValue Src, LValue Dst); /// EmitStoreThroughLValue - Store Src into Dst with same constraints as @@ -1805,7 +1981,7 @@ public: /// \param Result [out] - If non-null, this will be set to a Value* for the /// bit-field contents after the store, appropriate for use as the result of /// an assignment to the bit-field. - void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, QualType Ty, + void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, llvm::Value **Result=0); /// Emit an l-value for an assignment (simple or compound) of complex type. @@ -1832,6 +2008,7 @@ public: 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); llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -1897,8 +2074,9 @@ public: ReturnValueSlot ReturnValue = ReturnValueSlot()); llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee, - llvm::Value * const *ArgBegin, - llvm::Value * const *ArgEnd, + llvm::ArrayRef<llvm::Value *> Args, + const llvm::Twine &Name = ""); + llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee, const llvm::Twine &Name = ""); llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This, @@ -1961,6 +2139,59 @@ public: RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return = ReturnValueSlot()); + /// Retrieves the default cleanup kind for an ARC cleanup. + /// Except under -fobjc-arc-eh, ARC cleanups are normal-only. + CleanupKind getARCCleanupKind() { + return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions + ? NormalAndEHCleanup : NormalCleanup; + } + + // ARC primitives. + 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); + 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 *EmitObjCProduceObject(QualType T, llvm::Value *Ptr); + llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); + llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); + + 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); + /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in /// expression. Will emit a temporary variable if E is not an LValue. RValue EmitReferenceBindingToExpr(const Expr* E, @@ -2002,6 +2233,10 @@ public: void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty); + /// EmitExtendGCLifetime - Given a pointer to an Objective-C object, + /// make sure it survives garbage collection until this point. + void EmitExtendGCLifetime(llvm::Value *object); + /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. ComplexPairTy EmitComplexExpr(const Expr *E, @@ -2135,7 +2370,8 @@ private: /// Ty, into individual arguments on the provided vector \arg Args. See /// ABIArgInfo::Expand. void ExpandTypeToArgs(QualType Ty, RValue Src, - llvm::SmallVector<llvm::Value*, 16> &Args); + llvm::SmallVector<llvm::Value*, 16> &Args, + llvm::FunctionType *IRFuncTy); llvm::Value* EmitAsmInput(const AsmStmt &S, const TargetInfo::ConstraintInfo &Info, |