Skip to content

Commit 1bd2556

Browse files
committed
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. llvm-svn: 133840
1 parent 6e3dfa6 commit 1bd2556

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,20 @@ namespace {
364364
}
365365
};
366366

367+
struct ExtendGCLifetime : EHScopeStack::Cleanup {
368+
const VarDecl &Var;
369+
ExtendGCLifetime(const VarDecl *var) : Var(*var) {}
370+
371+
void Emit(CodeGenFunction &CGF, bool forEH) {
372+
// Compute the address of the local variable, in case it's a
373+
// byref or something.
374+
DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue,
375+
SourceLocation());
376+
llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE));
377+
CGF.EmitExtendGCLifetime(value);
378+
}
379+
};
380+
367381
struct CallCleanupFunction : EHScopeStack::Cleanup {
368382
llvm::Constant *CleanupFn;
369383
const CGFunctionInfo &FnInfo;
@@ -1029,6 +1043,12 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
10291043
}
10301044
}
10311045

1046+
// In GC mode, honor objc_precise_lifetime.
1047+
if (getLangOptions().getGCMode() != LangOptions::NonGC &&
1048+
D.hasAttr<ObjCPreciseLifetimeAttr>()) {
1049+
EHStack.pushCleanup<ExtendGCLifetime>(NormalCleanup, &D);
1050+
}
1051+
10321052
// Handle the cleanup attribute.
10331053
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
10341054
const FunctionDecl *FD = CA->getFunctionDecl();

clang/lib/CodeGen/CGObjC.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,4 +2484,22 @@ void CodeGenFunction::EmitObjCAutoreleasePoolStmt(
24842484
DI->EmitRegionEnd(Builder);
24852485
}
24862486
}
2487+
2488+
/// EmitExtendGCLifetime - Given a pointer to an Objective-C object,
2489+
/// make sure it survives garbage collection until this point.
2490+
void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
2491+
// We just use an inline assembly.
2492+
const llvm::Type *paramTypes[] = { VoidPtrTy };
2493+
llvm::FunctionType *extenderType
2494+
= llvm::FunctionType::get(VoidTy, paramTypes, /*variadic*/ false);
2495+
llvm::Value *extender
2496+
= llvm::InlineAsm::get(extenderType,
2497+
/* assembly */ "",
2498+
/* constraints */ "r",
2499+
/* side effects */ true);
2500+
2501+
object = Builder.CreateBitCast(object, VoidPtrTy);
2502+
Builder.CreateCall(extender, object)->setDoesNotThrow();
2503+
}
2504+
24872505
CGObjCRuntime::~CGObjCRuntime() {}

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,10 @@ class CodeGenFunction : public CodeGenTypeCache {
21462146
void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr,
21472147
QualType Ty);
21482148

2149+
/// EmitExtendGCLifetime - Given a pointer to an Objective-C object,
2150+
/// make sure it survives garbage collection until this point.
2151+
void EmitExtendGCLifetime(llvm::Value *object);
2152+
21492153
/// EmitComplexExpr - Emit the computation of the specified expression of
21502154
/// complex type, returning the result.
21512155
ComplexPairTy EmitComplexExpr(const Expr *E,

0 commit comments

Comments
 (0)