[cfe-commits] r136823 - in /cfe/trunk: lib/CodeGen/CGObjC.cpp test/CodeGenObjC/arc.m
John McCall
rjmccall at apple.com
Wed Aug 3 15:24:24 PDT 2011
Author: rjmccall
Date: Wed Aug 3 17:24:24 2011
New Revision: 136823
URL: http://llvm.org/viewvc/llvm-project?rev=136823&view=rev
Log:
Use the general conditional-cleanup framework instead of rolling our
own, incorrectly, for releasing objects at the end of a full-expression.
Modified:
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/test/CodeGenObjC/arc.m
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=136823&r1=136822&r2=136823&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Wed Aug 3 17:24:24 2011
@@ -1273,33 +1273,11 @@
namespace {
struct CallObjCRelease : EHScopeStack::Cleanup {
- CallObjCRelease(QualType type, llvm::Value *ptr, llvm::Value *condition)
- : type(type), ptr(ptr), condition(condition) {}
- QualType type;
- llvm::Value *ptr;
- llvm::Value *condition;
+ CallObjCRelease(llvm::Value *object) : object(object) {}
+ llvm::Value *object;
void Emit(CodeGenFunction &CGF, Flags flags) {
- llvm::Value *object;
-
- // If we're in a conditional branch, we had to stash away in an
- // alloca the pointer to be released.
- llvm::BasicBlock *cont = 0;
- if (condition) {
- llvm::BasicBlock *release = CGF.createBasicBlock("release.yes");
- cont = CGF.createBasicBlock("release.cont");
-
- llvm::Value *cond = CGF.Builder.CreateLoad(condition);
- CGF.Builder.CreateCondBr(cond, release, cont);
- CGF.EmitBlock(release);
- object = CGF.Builder.CreateLoad(ptr);
- } else {
- object = ptr;
- }
-
CGF.EmitARCRelease(object, /*precise*/ true);
-
- if (cont) CGF.EmitBlock(cont);
}
};
}
@@ -1309,27 +1287,8 @@
llvm::Value *CodeGenFunction::EmitObjCConsumeObject(QualType type,
llvm::Value *object) {
// If we're in a conditional branch, we need to make the cleanup
- // conditional. FIXME: this really needs to be supported by the
- // environment.
- llvm::AllocaInst *cond;
- llvm::Value *ptr;
- if (isInConditionalBranch()) {
- cond = CreateTempAlloca(Builder.getInt1Ty(), "release.cond");
- ptr = CreateTempAlloca(object->getType(), "release.value");
-
- // The alloca is false until we get here.
- // FIXME: er. doesn't this need to be set at the start of the condition?
- InitTempAlloca(cond, Builder.getFalse());
-
- // Then it turns true.
- Builder.CreateStore(Builder.getTrue(), cond);
- Builder.CreateStore(object, ptr);
- } else {
- cond = 0;
- ptr = object;
- }
-
- EHStack.pushCleanup<CallObjCRelease>(getARCCleanupKind(), type, ptr, cond);
+ // conditional.
+ pushFullExprCleanup<CallObjCRelease>(getARCCleanupKind(), object);
return object;
}
Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=136823&r1=136822&r2=136823&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Wed Aug 3 17:24:24 2011
@@ -578,18 +578,18 @@
// CHECK: define void @test22(
// CHECK: [[COND:%.*]] = alloca i8,
// CHECK-NEXT: [[X:%.*]] = alloca i8*,
- // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1
// CHECK-NEXT: [[RELVAL:%.*]] = alloca i8*
- // CHECK-NEXT: store i1 false, i1* [[RELCOND]]
+ // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1
// CHECK-NEXT: zext
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]]
// CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
+ // CHECK-NEXT: store i1 false, i1* [[RELCOND]]
// CHECK-NEXT: br i1 [[T1]],
// CHECK: br label
// CHECK: [[CALL:%.*]] = call i8* @test22_helper()
- // CHECK-NEXT: store i1 true, i1* [[RELCOND]]
// CHECK-NEXT: store i8* [[CALL]], i8** [[RELVAL]]
+ // CHECK-NEXT: store i1 true, i1* [[RELCOND]]
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ]
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) nounwind
@@ -1790,3 +1790,52 @@
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: ret void
}
+
+// rdar://problem/9891815
+void test62(void) {
+ // CHECK: define void @test62()
+ // CHECK: [[I:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca i8*
+ // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i1
+ extern id test62_make(void);
+ extern void test62_body(void);
+
+ // CHECK-NEXT: store i32 0, i32* [[I]], align 4
+ // CHECK-NEXT: br label
+
+ // CHECK: [[T0:%.*]] = load i32* [[I]], align 4
+ // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20
+ // CHECK-NEXT: br i1 [[T1]],
+
+ for (unsigned i = 0; i != 20; ++i) {
+ // CHECK: [[T0:%.*]] = load i32* [[I]], align 4
+ // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
+ // CHECK-NEXT: store i1 false, i1* [[CLEANUP_REQUIRED]]
+ // CHECK-NEXT: br i1 [[T1]],
+ // CHECK: [[T0:%.*]] = call i8* @test62_make()
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_VALUE]]
+ // CHECK-NEXT: store i1 true, i1* [[CLEANUP_REQUIRED]]
+ // CHECK-NEXT: [[T2:%.*]] = icmp ne i8* [[T1]], null
+ // CHECK-NEXT: br label
+ // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ]
+ // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_REQUIRED]]
+ // CHECK-NEXT: br i1 [[T0]],
+ // CHECK: [[T0:%.*]] = load i8** [[CLEANUP_VALUE]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: br label
+ // CHECK: br i1 [[COND]]
+ // CHECK: call void @test62_body()
+ // CHECK-NEXT: br label
+ // CHECK: br label
+ if (i != 0 && test62_make() != 0)
+ test62_body();
+ }
+
+ // CHECK: [[T0:%.*]] = load i32* [[I]], align 4
+ // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 1
+ // CHECK-NEXT: store i32 [[T1]], i32* [[I]]
+ // CHECK-NEXT: br label
+
+ // CHECK: ret void
+}
More information about the cfe-commits
mailing list