diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/CodeGen/CGObjC.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/CodeGen/CGObjC.cpp')
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 265 |
1 files changed, 153 insertions, 112 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index c90e4ec..79d97b9 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -21,8 +21,8 @@ #include "clang/AST/StmtObjC.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/DataLayout.h" -#include "llvm/InlineAsm.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/InlineAsm.h" using namespace clang; using namespace CodeGen; @@ -70,7 +70,7 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // messaged (avoids pulling it out of the result type). CGObjCRuntime &Runtime = CGM.getObjCRuntime(); const ObjCInterfaceDecl *ClassDecl = BoxingMethod->getClassInterface(); - llvm::Value *Receiver = Runtime.GetClass(Builder, ClassDecl); + llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl); const ParmVarDecl *argDecl = *BoxingMethod->param_begin(); QualType ArgQT = argDecl->getType().getUnqualifiedType(); @@ -109,32 +109,50 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, if (DLE) Keys = CreateMemTemp(ElementArrayType, "keys"); + // In ARC, we may need to do extra work to keep all the keys and + // values alive until after the call. + SmallVector<llvm::Value *, 16> NeededObjects; + bool TrackNeededObjects = + (getLangOpts().ObjCAutoRefCount && + CGM.getCodeGenOpts().OptimizationLevel != 0); + // Perform the actual initialialization of the array(s). for (uint64_t i = 0; i < NumElements; i++) { if (ALE) { - // Emit the initializer. + // Emit the element and store it to the appropriate array slot. const Expr *Rhs = ALE->getElement(i); LValue LV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i), ElementType, Context.getTypeAlignInChars(Rhs->getType()), Context); - EmitScalarInit(Rhs, /*D=*/0, LV, /*capturedByInit=*/false); + + llvm::Value *value = EmitScalarExpr(Rhs); + EmitStoreThroughLValue(RValue::get(value), LV, true); + if (TrackNeededObjects) { + NeededObjects.push_back(value); + } } else { - // Emit the key initializer. + // Emit the key and store it to the appropriate array slot. const Expr *Key = DLE->getKeyValueElement(i).Key; LValue KeyLV = LValue::MakeAddr(Builder.CreateStructGEP(Keys, i), ElementType, Context.getTypeAlignInChars(Key->getType()), Context); - EmitScalarInit(Key, /*D=*/0, KeyLV, /*capturedByInit=*/false); + llvm::Value *keyValue = EmitScalarExpr(Key); + EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true); - // Emit the value initializer. + // Emit the value and store it to the appropriate array slot. const Expr *Value = DLE->getKeyValueElement(i).Value; LValue ValueLV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i), ElementType, Context.getTypeAlignInChars(Value->getType()), Context); - EmitScalarInit(Value, /*D=*/0, ValueLV, /*capturedByInit=*/false); + llvm::Value *valueValue = EmitScalarExpr(Value); + EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true); + if (TrackNeededObjects) { + NeededObjects.push_back(keyValue); + NeededObjects.push_back(valueValue); + } } } @@ -163,7 +181,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCInterfaceDecl *Class = InterfacePointerType->getObjectType()->getInterface(); CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - llvm::Value *Receiver = Runtime.GetClass(Builder, Class); + llvm::Value *Receiver = Runtime.GetClass(*this, Class); // Generate the message send. RValue result @@ -172,6 +190,15 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, Sel, Receiver, Args, Class, MethodWithObjects); + + // The above message send needs these objects, but in ARC they are + // passed in a buffer that is essentially __unsafe_unretained. + // Therefore we must prevent the optimizer from releasing them until + // after the call. + if (TrackNeededObjects) { + EmitARCIntrinsicUse(NeededObjects); + } + return Builder.CreateBitCast(result.getScalarVal(), ConvertType(E->getType())); } @@ -191,12 +218,12 @@ llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { // Note that this implementation allows for non-constant strings to be passed // as arguments to @selector(). Currently, the only thing preventing this // behaviour is the type checking in the front end. - return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector()); + return CGM.getObjCRuntime().GetSelector(*this, E->getSelector()); } llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { // FIXME: This should pass the Decl not the name. - return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol()); + return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol()); } /// \brief Adjust the type of the result of an Objective-C message send @@ -310,7 +337,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, assert(ObjTy && "Invalid Objective-C class message send"); OID = ObjTy->getInterface(); assert(OID && "Invalid Objective-C class message send"); - Receiver = Runtime.GetClass(Builder, OID); + Receiver = Runtime.GetClass(*this, OID); isClassMessage = true; break; } @@ -772,7 +799,7 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); llvm::Value *copyCppAtomicObjectFn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction(); + CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction(); CGF.EmitCall(CGF.getTypes().arrangeFreeFunctionCall(CGF.getContext().VoidTy, args, FunctionType::ExtInfo(), @@ -895,16 +922,21 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); QualType ivarType = ivar->getType(); - if (ivarType->isAnyComplexType()) { - ComplexPairTy pair = LoadComplexFromAddr(LV.getAddress(), - LV.isVolatileQualified()); - StoreComplexToAddr(pair, ReturnValue, LV.isVolatileQualified()); - } else if (hasAggregateLLVMType(ivarType)) { + switch (getEvaluationKind(ivarType)) { + case TEK_Complex: { + ComplexPairTy pair = EmitLoadOfComplex(LV); + EmitStoreOfComplex(pair, + MakeNaturalAlignAddrLValue(ReturnValue, ivarType), + /*init*/ true); + return; + } + case TEK_Aggregate: // The return value slot is guaranteed to not be aliased, but // that's not necessarily the same as "on the stack", so // we still potentially need objc_memmove_collectable. EmitAggregateCopy(ReturnValue, LV.getAddress(), ivarType); - } else { + return; + case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { value = LV.getAddress(); @@ -926,8 +958,10 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } EmitReturnOfRValue(RValue::get(value), propType); + return; } - return; + } + llvm_unreachable("bad evaluation kind"); } } @@ -1007,7 +1041,7 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); llvm::Value *copyCppAtomicObjectFn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction(); + CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction(); CGF.EmitCall(CGF.getTypes().arrangeFreeFunctionCall(CGF.getContext().VoidTy, args, FunctionType::ExtInfo(), @@ -1182,7 +1216,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, selfDecl->getType(), CK_LValueToRValue, &self, VK_RValue); ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(), - SourceLocation(), &selfLoad, true, true); + SourceLocation(), SourceLocation(), + &selfLoad, true, true); ParmVarDecl *argDecl = *setterMethod->param_begin(); QualType argType = argDecl->getType().getNonReferenceType(); @@ -1679,7 +1714,8 @@ namespace { llvm::Value *object; void Emit(CodeGenFunction &CGF, Flags flags) { - CGF.EmitARCRelease(object, /*precise*/ true); + // Releases at the end of the full-expression are imprecise. + CGF.EmitARCRelease(object, ARCImpreciseLifetime); } }; } @@ -1699,21 +1735,38 @@ llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type, return EmitARCRetainAutorelease(type, value); } +/// Given a number of pointers, inform the optimizer that they're +/// being intrinsically used up until this point in the program. +void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) { + llvm::Constant *&fn = CGM.getARCEntrypoints().clang_arc_use; + if (!fn) { + llvm::FunctionType *fnType = + llvm::FunctionType::get(CGM.VoidTy, ArrayRef<llvm::Type*>(), true); + fn = CGM.CreateRuntimeFunction(fnType, "clang.arc.use"); + } + + // This isn't really a "runtime" function, but as an intrinsic it + // doesn't really matter as long as we align things up. + EmitNounwindRuntimeCall(fn, values); +} + static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM, llvm::FunctionType *type, StringRef fnName) { llvm::Constant *fn = CGM.CreateRuntimeFunction(type, fnName); - // If the target runtime doesn't naturally support ARC, emit weak - // references to the runtime support library. We don't really - // permit this to fail, but we need a particular relocation style. if (llvm::Function *f = dyn_cast<llvm::Function>(fn)) { - if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC()) + // If the target runtime doesn't naturally support ARC, emit weak + // references to the runtime support library. We don't really + // permit this to fail, but we need a particular relocation style. + if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC()) { f->setLinkage(llvm::Function::ExternalWeakLinkage); - // set nonlazybind attribute for these APIs for performance. - if (fnName == "objc_retain" || fnName == "objc_release") - f->addFnAttr(llvm::Attributes::NonLazyBind); + } else if (fnName == "objc_retain" || fnName == "objc_release") { + // If we have Native ARC, set nonlazybind attribute for these APIs for + // performance. + f->addFnAttr(llvm::Attribute::NonLazyBind); + } } return fn; @@ -1725,13 +1778,13 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM, static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF, llvm::Value *value, llvm::Constant *&fn, - StringRef fnName) { + StringRef fnName, + bool isTailCall = false) { if (isa<llvm::ConstantPointerNull>(value)) return value; if (!fn) { - std::vector<llvm::Type*> args(1, CGF.Int8PtrTy); llvm::FunctionType *fnType = - llvm::FunctionType::get(CGF.Int8PtrTy, args, false); + llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false); fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName); } @@ -1740,8 +1793,9 @@ static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF, value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); // Call the function. - llvm::CallInst *call = CGF.Builder.CreateCall(fn, value); - call->setDoesNotThrow(); + llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value); + if (isTailCall) + call->setTailCall(); // Cast the result back to the original type. return CGF.Builder.CreateBitCast(call, origType); @@ -1754,9 +1808,8 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, llvm::Constant *&fn, StringRef fnName) { if (!fn) { - std::vector<llvm::Type*> args(1, CGF.Int8PtrPtrTy); llvm::FunctionType *fnType = - llvm::FunctionType::get(CGF.Int8PtrTy, args, false); + llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrPtrTy, false); fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName); } @@ -1765,11 +1818,9 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy); // Call the function. - llvm::CallInst *call = CGF.Builder.CreateCall(fn, addr); - call->setDoesNotThrow(); + llvm::Value *result = CGF.EmitNounwindRuntimeCall(fn, addr); // Cast the result back to a dereference of the original type. - llvm::Value *result = call; if (origType != CGF.Int8PtrPtrTy) result = CGF.Builder.CreateBitCast(result, cast<llvm::PointerType>(origType)->getElementType()); @@ -1798,11 +1849,11 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, llvm::Type *origType = value->getType(); - addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy); - value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); - - llvm::CallInst *result = CGF.Builder.CreateCall2(fn, addr, value); - result->setDoesNotThrow(); + llvm::Value *args[] = { + CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) + }; + llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return 0; @@ -1819,17 +1870,18 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, assert(dst->getType() == src->getType()); if (!fn) { - std::vector<llvm::Type*> argTypes(2, CGF.Int8PtrPtrTy); + llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrPtrTy }; + llvm::FunctionType *fnType = llvm::FunctionType::get(CGF.Builder.getVoidTy(), argTypes, false); fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName); } - dst = CGF.Builder.CreateBitCast(dst, CGF.Int8PtrPtrTy); - src = CGF.Builder.CreateBitCast(src, CGF.Int8PtrPtrTy); - - llvm::CallInst *result = CGF.Builder.CreateCall2(fn, dst, src); - result->setDoesNotThrow(); + llvm::Value *args[] = { + CGF.Builder.CreateBitCast(dst, CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src, CGF.Int8PtrPtrTy) + }; + CGF.EmitNounwindRuntimeCall(fn, args); } /// Produce the code to do a retain. Based on the type, calls one of: @@ -1932,14 +1984,14 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { /// Release the given object. /// call void \@objc_release(i8* %value) -void CodeGenFunction::EmitARCRelease(llvm::Value *value, bool precise) { +void CodeGenFunction::EmitARCRelease(llvm::Value *value, + ARCPreciseLifetime_t precise) { if (isa<llvm::ConstantPointerNull>(value)) return; llvm::Constant *&fn = CGM.getARCEntrypoints().objc_release; if (!fn) { - std::vector<llvm::Type*> args(1, Int8PtrTy); llvm::FunctionType *fnType = - llvm::FunctionType::get(Builder.getVoidTy(), args, false); + llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); fn = createARCRuntimeFunction(CGM, fnType, "objc_release"); } @@ -1947,10 +1999,9 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value, bool precise) { value = Builder.CreateBitCast(value, Int8PtrTy); // Call objc_release. - llvm::CallInst *call = Builder.CreateCall(fn, value); - call->setDoesNotThrow(); + llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value); - if (!precise) { + if (precise == ARCImpreciseLifetime) { SmallVector<llvm::Value*,1> args; call->setMetadata("clang.imprecise_release", llvm::MDNode::get(Builder.getContext(), args)); @@ -1966,7 +2017,8 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value, bool precise) { /// At -O1 and above, just load and call objc_release. /// /// call void \@objc_storeStrong(i8** %addr, i8* null) -void CodeGenFunction::EmitARCDestroyStrong(llvm::Value *addr, bool precise) { +void CodeGenFunction::EmitARCDestroyStrong(llvm::Value *addr, + ARCPreciseLifetime_t precise) { if (CGM.getCodeGenOpts().OptimizationLevel == 0) { llvm::PointerType *addrTy = cast<llvm::PointerType>(addr->getType()); llvm::Value *null = llvm::ConstantPointerNull::get( @@ -1995,10 +2047,11 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(llvm::Value *addr, fn = createARCRuntimeFunction(CGM, fnType, "objc_storeStrong"); } - addr = Builder.CreateBitCast(addr, Int8PtrPtrTy); - llvm::Value *castValue = Builder.CreateBitCast(value, Int8PtrTy); - - Builder.CreateCall2(fn, addr, castValue)->setDoesNotThrow(); + llvm::Value *args[] = { + Builder.CreateBitCast(addr, Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy) + }; + EmitNounwindRuntimeCall(fn, args); if (ignored) return 0; return value; @@ -2035,7 +2088,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst, EmitStoreOfScalar(newValue, dst); // Finally, release the old value. - EmitARCRelease(oldValue, /*precise*/ false); + EmitARCRelease(oldValue, dst.isARCPreciseLifetime()); return newValue; } @@ -2054,7 +2107,8 @@ llvm::Value * CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) { return emitARCValueOperation(*this, value, CGM.getARCEntrypoints().objc_autoreleaseReturnValue, - "objc_autoreleaseReturnValue"); + "objc_autoreleaseReturnValue", + /*isTailCall*/ true); } /// Do a fused retain/autorelease of the given object. @@ -2063,7 +2117,8 @@ llvm::Value * CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) { return emitARCValueOperation(*this, value, CGM.getARCEntrypoints().objc_retainAutoreleaseReturnValue, - "objc_retainAutoreleaseReturnValue"); + "objc_retainAutoreleaseReturnValue", + /*isTailCall*/ true); } /// Do a fused retain/autorelease of the given object. @@ -2144,17 +2199,15 @@ void CodeGenFunction::EmitARCInitWeak(llvm::Value *addr, llvm::Value *value) { void CodeGenFunction::EmitARCDestroyWeak(llvm::Value *addr) { llvm::Constant *&fn = CGM.getARCEntrypoints().objc_destroyWeak; if (!fn) { - std::vector<llvm::Type*> args(1, Int8PtrPtrTy); llvm::FunctionType *fnType = - llvm::FunctionType::get(Builder.getVoidTy(), args, false); + llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrPtrTy, false); fn = createARCRuntimeFunction(CGM, fnType, "objc_destroyWeak"); } // Cast the argument to 'id*'. addr = Builder.CreateBitCast(addr, Int8PtrPtrTy); - llvm::CallInst *call = Builder.CreateCall(fn, addr); - call->setDoesNotThrow(); + EmitNounwindRuntimeCall(fn, addr); } /// void \@objc_moveWeak(i8** %dest, i8** %src) @@ -2185,10 +2238,7 @@ llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() { fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPush"); } - llvm::CallInst *call = Builder.CreateCall(fn); - call->setDoesNotThrow(); - - return call; + return EmitNounwindRuntimeCall(fn); } /// Produce the code to do a primitive release. @@ -2198,17 +2248,15 @@ void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) { llvm::Constant *&fn = CGM.getRREntrypoints().objc_autoreleasePoolPop; if (!fn) { - std::vector<llvm::Type*> args(1, Int8PtrTy); llvm::FunctionType *fnType = - llvm::FunctionType::get(Builder.getVoidTy(), args, false); + llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); // We don't want to use a weak import here; instead we should not // fall into this path. fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPop"); } - llvm::CallInst *call = Builder.CreateCall(fn, value); - call->setDoesNotThrow(); + EmitNounwindRuntimeCall(fn, value); } /// Produce the code to do an MRR version objc_autoreleasepool_push. @@ -2218,7 +2266,7 @@ void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) { /// llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() { CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - llvm::Value *Receiver = Runtime.EmitNSAutoreleasePoolClassRef(Builder); + llvm::Value *Receiver = Runtime.EmitNSAutoreleasePoolClassRef(*this); // [NSAutoreleasePool alloc] IdentifierInfo *II = &CGM.getContext().Idents.get("alloc"); Selector AllocSel = getContext().Selectors.getSelector(0, &II); @@ -2252,13 +2300,13 @@ void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) { void CodeGenFunction::destroyARCStrongPrecise(CodeGenFunction &CGF, llvm::Value *addr, QualType type) { - CGF.EmitARCDestroyStrong(addr, /*precise*/ true); + CGF.EmitARCDestroyStrong(addr, ARCPreciseLifetime); } void CodeGenFunction::destroyARCStrongImprecise(CodeGenFunction &CGF, llvm::Value *addr, QualType type) { - CGF.EmitARCDestroyStrong(addr, /*precise*/ false); + CGF.EmitARCDestroyStrong(addr, ARCImpreciseLifetime); } void CodeGenFunction::destroyARCWeak(CodeGenFunction &CGF, @@ -2440,7 +2488,7 @@ static bool shouldEmitSeparateBlockRetain(const Expr *e) { /// This massively duplicates emitPseudoObjectRValue. static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF, const PseudoObjectExpr *E) { - llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; + SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; // Find the result expression. const Expr *resultExpr = E->getResultExpr(); @@ -2490,12 +2538,10 @@ static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF, static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { - // Look through cleanups. - if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { - CGF.enterFullExpression(cleanups); - CodeGenFunction::RunCleanupsScope scope(CGF); - return tryEmitARCRetainScalarExpr(CGF, cleanups->getSubExpr()); - } + // We should *never* see a nested full-expression here, because if + // we fail to emit at +1, our caller must not retain after we close + // out the full-expression. + assert(!isa<ExprWithCleanups>(e)); // The desired result type, if it differs from the type of the // ultimate opaque expression. @@ -2647,6 +2693,13 @@ static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF, /// best-effort attempt to peephole expressions that naturally produce /// retained objects. llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) { + // The retain needs to happen within the full-expression. + if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { + enterFullExpression(cleanups); + RunCleanupsScope scope(*this); + return EmitARCRetainScalarExpr(cleanups->getSubExpr()); + } + TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); llvm::Value *value = result.getPointer(); if (!result.getInt()) @@ -2656,6 +2709,13 @@ llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) { llvm::Value * CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) { + // The retain needs to happen within the full-expression. + if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { + enterFullExpression(cleanups); + RunCleanupsScope scope(*this); + return EmitARCRetainAutoreleaseScalarExpr(cleanups->getSubExpr()); + } + TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); llvm::Value *value = result.getPointer(); if (result.getInt()) @@ -2687,17 +2747,7 @@ llvm::Value *CodeGenFunction::EmitObjCThrowOperand(const Expr *expr) { // In ARC, retain and autorelease the expression. if (getLangOpts().ObjCAutoRefCount) { // Do so before running any cleanups for the full-expression. - // tryEmitARCRetainScalarExpr does make an effort to do things - // inside cleanups, but there are crazy cases like - // @throw A().foo; - // where a full retain+autorelease is required and would - // otherwise happen after the destructor for the temporary. - if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr)) { - enterFullExpression(ewc); - expr = ewc->getSubExpr(); - } - - CodeGenFunction::RunCleanupsScope cleanups(*this); + // EmitARCRetainAutoreleaseScalarExpr does this for us. return EmitARCRetainAutoreleaseScalarExpr(expr); } @@ -2733,7 +2783,7 @@ CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e, llvm::Value *oldValue = EmitLoadOfScalar(lvalue); EmitStoreOfScalar(value, lvalue); - EmitARCRelease(oldValue, /*precise*/ false); + EmitARCRelease(oldValue, lvalue.isARCPreciseLifetime()); } else { value = EmitARCStoreStrong(lvalue, value, ignored); } @@ -2791,12 +2841,7 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { /* side effects */ true); object = Builder.CreateBitCast(object, VoidPtrTy); - Builder.CreateCall(extender, object)->setDoesNotThrow(); -} - -static bool hasAtomicCopyHelperAPI(const ObjCRuntime &runtime) { - // For now, only NeXT has these APIs. - return runtime.isNeXTFamily(); + EmitNounwindRuntimeCall(extender, object); } /// GenerateObjCAtomicSetterCopyHelperFunction - Given a c++ object type with @@ -2806,9 +2851,8 @@ static bool hasAtomicCopyHelperAPI(const ObjCRuntime &runtime) { llvm::Constant * CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( const ObjCPropertyImplDecl *PID) { - // FIXME. This api is for NeXt runtime only for now. if (!getLangOpts().CPlusPlus || - !hasAtomicCopyHelperAPI(getLangOpts().ObjCRuntime)) + !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) return 0; QualType Ty = PID->getPropertyIvarDecl()->getType(); if (!Ty->isRecordType()) @@ -2831,7 +2875,6 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( SourceLocation(), SourceLocation(), II, C.VoidTy, 0, SC_Static, - SC_None, false, false); @@ -2890,9 +2933,8 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( llvm::Constant * CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( const ObjCPropertyImplDecl *PID) { - // FIXME. This api is for NeXt runtime only for now. if (!getLangOpts().CPlusPlus || - !hasAtomicCopyHelperAPI(getLangOpts().ObjCRuntime)) + !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) return 0; const ObjCPropertyDecl *PD = PID->getPropertyDecl(); QualType Ty = PD->getType(); @@ -2917,7 +2959,6 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( SourceLocation(), SourceLocation(), II, C.VoidTy, 0, SC_Static, - SC_None, false, false); |