[cfe-commits] r65362 - in /cfe/trunk: lib/CodeGen/CGObjCMac.cpp test/CodeGenObjC/synchronized.m
Daniel Dunbar
daniel at zuster.org
Mon Feb 23 17:43:46 PST 2009
Author: ddunbar
Date: Mon Feb 23 19:43:46 2009
New Revision: 65362
URL: http://llvm.org/viewvc/llvm-project?rev=65362&view=rev
Log:
Fix two @synchronized bugs found by inspection: the expression to sychronize on should only be evaluated once, and it is evaluated outside the cleanup scope.
Also, lift SyncEnter and SyncExit up in nervous anticipation of x86-64
zero cost EH.
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/test/CodeGenObjC/synchronized.m
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=65362&r1=65361&r2=65362&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Feb 23 19:43:46 2009
@@ -105,6 +105,12 @@
/// ExceptionThrowFn - LLVM objc_exception_throw function.
llvm::Function *ExceptionThrowFn;
+ /// SyncEnterFn - LLVM object_sync_enter function.
+ llvm::Function *SyncEnterFn;
+
+ /// SyncExitFn - LLVM object_sync_exit function.
+ llvm::Function *SyncExitFn;
+
ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCCommonTypesHelper(){}
};
@@ -188,12 +194,6 @@
/// SetJmpFn - LLVM _setjmp function.
llvm::Function *SetJmpFn;
- /// SyncEnterFn - LLVM object_sync_enter function.
- llvm::Function *SyncEnterFn;
-
- /// SyncExitFn - LLVM object_sync_exit function.
- llvm::Function *SyncExitFn;
-
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCTypesHelper() {}
@@ -1892,6 +1892,18 @@
llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
+
+ // For @synchronized, call objc_sync_enter(sync.expr). The
+ // evaluation of the expression must occur before we enter the
+ // @synchronized. We can safely avoid a temp here because jumps into
+ // @synchronized are illegal & this will dominate uses.
+ llvm::Value *SyncArg = 0;
+ if (!isTry) {
+ SyncArg =
+ CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
+ SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
+ CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, SyncArg);
+ }
// Push an EH context entry, used for handling rethrows and jumps
// through finally.
@@ -1908,14 +1920,6 @@
"_call_try_exit");
CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(), CallTryExitPtr);
- if (!isTry) {
- // For @synchronized, call objc_sync_enter(sync.expr)
- llvm::Value *Arg = CGF.EmitScalarExpr(
- cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
- Arg = CGF.Builder.CreateBitCast(Arg, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, Arg);
- }
-
// Enter a new try block and call setjmp.
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
@@ -2079,14 +2083,10 @@
if (const ObjCAtFinallyStmt* FinallyStmt =
cast<ObjCAtTryStmt>(S).getFinallyStmt())
CGF.EmitStmt(FinallyStmt->getFinallyBody());
- }
- else {
- // For @synchronized objc_sync_exit(expr); As finally's sole statement.
- // For @synchronized, call objc_sync_enter(sync.expr)
- llvm::Value *Arg = CGF.EmitScalarExpr(
- cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
- Arg = CGF.Builder.CreateBitCast(Arg, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, Arg);
+ } else {
+ // Emit objc_sync_exit(expr); as finally's sole statement for
+ // @synchronized.
+ CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, SyncArg);
}
// Emit the switch block
@@ -2740,9 +2740,18 @@
Params.push_back(IdType);
FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
-
ExceptionThrowFn =
CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
+
+ // synchronized APIs
+ // void objc_sync_enter (id)
+ // void objc_sync_exit (id)
+ Params.clear();
+ Params.push_back(IdType);
+
+ FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
+ SyncEnterFn = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
+ SyncExitFn = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
}
ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
@@ -3049,23 +3058,6 @@
false),
"objc_exception_match");
- // synchronized APIs
- // void objc_sync_enter (id)
- Params.clear();
- Params.push_back(ObjectPtrTy);
- SyncEnterFn =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
- Params,
- false),
- "objc_sync_enter");
- // void objc_sync_exit (id)
- SyncExitFn =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
- Params,
- false),
- "objc_sync_exit");
-
-
Params.clear();
Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
SetJmpFn =
Modified: cfe/trunk/test/CodeGenObjC/synchronized.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/synchronized.m?rev=65362&r1=65361&r2=65362&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/synchronized.m (original)
+++ cfe/trunk/test/CodeGenObjC/synchronized.m Mon Feb 23 19:43:46 2009
@@ -1,5 +1,6 @@
-// RUN: clang -emit-llvm -triple=i686-apple-darwin8 -o %t %s
-// RUNX: clang -emit-llvm -o %t %s
+// RUN: clang -emit-llvm -triple=i686-apple-darwin8 -o %t %s -O2 &&
+// RUN: grep 'ret i32' %t | count 1 &&
+// RUN: grep 'ret i32 1' %t | count 1
#include <stdio.h>
@@ -28,5 +29,17 @@
}
}
+int f0(id a) {
+ int x = 0;
+ @synchronized((x++, a)) {
+ }
+ return x; // ret i32 1
+}
-
+void f1(id a) {
+ // The trick here is that the return shouldn't go through clean up,
+ // but there isn't a simple way to check this property.
+ @synchronized(({ return; }), a) {
+ return;
+ }
+}
More information about the cfe-commits
mailing list