зеркало из https://github.com/microsoft/clang-1.git
Honor objc_precise_lifetime in GC mode by feeding the value
in the variable to an inline asm which gets run when the variable goes out of scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
537c346116
Коммит
0c24c808e4
|
@ -364,6 +364,20 @@ namespace {
|
|||
}
|
||||
};
|
||||
|
||||
struct ExtendGCLifetime : EHScopeStack::Cleanup {
|
||||
const VarDecl &Var;
|
||||
ExtendGCLifetime(const VarDecl *var) : Var(*var) {}
|
||||
|
||||
void Emit(CodeGenFunction &CGF, bool forEH) {
|
||||
// Compute the address of the local variable, in case it's a
|
||||
// byref or something.
|
||||
DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue,
|
||||
SourceLocation());
|
||||
llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE));
|
||||
CGF.EmitExtendGCLifetime(value);
|
||||
}
|
||||
};
|
||||
|
||||
struct CallCleanupFunction : EHScopeStack::Cleanup {
|
||||
llvm::Constant *CleanupFn;
|
||||
const CGFunctionInfo &FnInfo;
|
||||
|
@ -1029,6 +1043,12 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
|
|||
}
|
||||
}
|
||||
|
||||
// In GC mode, honor objc_precise_lifetime.
|
||||
if (getLangOptions().getGCMode() != LangOptions::NonGC &&
|
||||
D.hasAttr<ObjCPreciseLifetimeAttr>()) {
|
||||
EHStack.pushCleanup<ExtendGCLifetime>(NormalCleanup, &D);
|
||||
}
|
||||
|
||||
// Handle the cleanup attribute.
|
||||
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
|
||||
const FunctionDecl *FD = CA->getFunctionDecl();
|
||||
|
|
|
@ -2484,4 +2484,22 @@ void CodeGenFunction::EmitObjCAutoreleasePoolStmt(
|
|||
DI->EmitRegionEnd(Builder);
|
||||
}
|
||||
}
|
||||
|
||||
/// EmitExtendGCLifetime - Given a pointer to an Objective-C object,
|
||||
/// make sure it survives garbage collection until this point.
|
||||
void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
|
||||
// We just use an inline assembly.
|
||||
const llvm::Type *paramTypes[] = { VoidPtrTy };
|
||||
llvm::FunctionType *extenderType
|
||||
= llvm::FunctionType::get(VoidTy, paramTypes, /*variadic*/ false);
|
||||
llvm::Value *extender
|
||||
= llvm::InlineAsm::get(extenderType,
|
||||
/* assembly */ "",
|
||||
/* constraints */ "r",
|
||||
/* side effects */ true);
|
||||
|
||||
object = Builder.CreateBitCast(object, VoidPtrTy);
|
||||
Builder.CreateCall(extender, object)->setDoesNotThrow();
|
||||
}
|
||||
|
||||
CGObjCRuntime::~CGObjCRuntime() {}
|
||||
|
|
|
@ -2146,6 +2146,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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче