Fariborz, Sorry for the delayed review; one comment on this patch: I would really prefer that the code to emit the exception handling for @synchronized be shared with the regular code for exception handling. I haven't looked closely but I think this is doable with only a little work to factor a common routine out of EmitTryStmt.
Even if this routine has to do a dyn_cast on the statement type (for generating the finally block), this is preferable to duplicating the logic for setting up the exception handling context. - Daniel On Sat, Nov 15, 2008 at 1:26 PM, Chris Lattner <[EMAIL PROTECTED]> wrote: > Author: lattner > Date: Sat Nov 15 15:26:17 2008 > New Revision: 59377 > > URL: http://llvm.org/viewvc/llvm-project?rev=59377&view=rev > Log: > Start implementing support for @synchonized with the darwin ObjC API. > > Patch by Fariborz! > > > Modified: > cfe/trunk/lib/CodeGen/CGObjC.cpp > cfe/trunk/lib/CodeGen/CGObjCGNU.cpp > cfe/trunk/lib/CodeGen/CGObjCMac.cpp > cfe/trunk/lib/CodeGen/CGObjCRuntime.h > cfe/trunk/lib/CodeGen/CGStmt.cpp > cfe/trunk/lib/CodeGen/CodeGenFunction.h > > Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Nov 15 15:26:17 2008 > @@ -533,4 +533,10 @@ > CGM.getObjCRuntime().EmitThrowStmt(*this, S); > } > > +void CodeGenFunction::EmitObjCAtSynchronizedStmt( > + const ObjCAtSynchronizedStmt > &S) > +{ > + CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); > +} > + > CGObjCRuntime::~CGObjCRuntime() {} > > Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sat Nov 15 15:26:17 2008 > @@ -128,6 +128,8 @@ > const ObjCAtTryStmt &S); > virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, > const ObjCAtThrowStmt &S); > + virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, > + const ObjCAtSynchronizedStmt &S); > }; > } // end anonymous namespace > > @@ -961,6 +963,11 @@ > CGF.ErrorUnsupported(&S, "@throw statement"); > } > > +void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, > + const ObjCAtSynchronizedStmt &S) { > + CGF.ErrorUnsupported(&S, "@synchronized statement"); > +} > + > CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule > &CGM){ > return new CGObjCGNU(CGM); > } > > Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat Nov 15 15:26:17 2008 > @@ -155,7 +155,13 @@ > > /// 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(); > @@ -430,6 +436,8 @@ > const ObjCAtTryStmt &S); > virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, > const ObjCAtThrowStmt &S); > + virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, > + const ObjCAtSynchronizedStmt &S); > > }; > } // end anonymous namespace > @@ -1751,6 +1759,96 @@ > EmitBranch(ExecuteTryExit ? E->FinallyBlock : E->FinallyNoExit); > } > > +/// EmitSynchronizedStmt - Code gen for @synchronized(expr) stmt; > +/// Effectively generating code for: > +/// objc_sync_enter(expr); > +/// @try stmt @finally { objc_sync_exit(expr); } > +void CGObjCMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, > + const ObjCAtSynchronizedStmt &S) { > + // Create various blocks we refer to for handling @finally. > + llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); > + llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit"); > + llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); > + llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); > + llvm::Value *DestCode = > + CGF.CreateTempAlloca(llvm::Type::Int32Ty, "finally.dst"); > + > + // Generate jump code. Done here so we can directly add things to > + // the switch instruction. > + llvm::BasicBlock *FinallyJump = CGF.createBasicBlock("finally.jump"); > + llvm::SwitchInst *FinallySwitch = > + llvm::SwitchInst::Create(new llvm::LoadInst(DestCode, "", FinallyJump), > + FinallyEnd, 10, FinallyJump); > + > + // Push an EH context entry, used for handling rethrows and jumps > + // through finally. > + CodeGenFunction::ObjCEHEntry EHEntry(FinallyBlock, FinallyNoExit, > + FinallySwitch, DestCode); > + CGF.ObjCEHStack.push_back(&EHEntry); > + > + // Allocate memory for the exception data and rethrow pointer. > + llvm::Value *ExceptionData = > CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, > + "exceptiondata.ptr"); > + llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, > + "_rethrow"); > + // Call objc_sync_enter(sync.expr) > + CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, > + CGF.EmitScalarExpr(S.getSynchExpr())); > + > + // Enter a new try block and call setjmp. > + CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData); > + llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0, > + "jmpbufarray"); > + JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp"); > + llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn, > + JmpBufPtr, "result"); > + > + llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); > + llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); > + CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, > "threw"), > + TryHandler, TryBlock); > + > + // Emit the @try block. > + CGF.EmitBlock(TryBlock); > + CGF.EmitStmt(S.getSynchBody()); > + CGF.EmitJumpThroughFinally(&EHEntry, FinallyEnd); > + > + // Emit the "exception in @try" block. > + CGF.EmitBlock(TryHandler); > + > + // Retrieve the exception object. We may emit multiple blocks but > + // nothing can cross this so the value is already in SSA form. > + llvm::Value *Caught = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn, > + ExceptionData, > + "caught"); > + EHEntry.Exception = Caught; > + CGF.Builder.CreateStore(Caught, RethrowPtr); > + CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false); > + > + // Pop the exception-handling stack entry. It is important to do > + // this now, because the code in the @finally block is not in this > + // context. > + CGF.ObjCEHStack.pop_back(); > + > + // Emit the @finally block. > + CGF.EmitBlock(FinallyBlock); > + CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData); > + > + CGF.EmitBlock(FinallyNoExit); > + // objc_sync_exit(expr); As finally's sole statement. > + CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, > + CGF.EmitScalarExpr(S.getSynchExpr())); > + > + CGF.EmitBlock(FinallyJump); > + > + CGF.EmitBlock(FinallyRethrow); > + CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, > + CGF.Builder.CreateLoad(RethrowPtr)); > + CGF.Builder.CreateUnreachable(); > + > + CGF.EmitBlock(FinallyEnd); > +} > + > /* *** Private Interface *** */ > > /// EmitImageInfo - Emit the image info marker used to encode some module > @@ -2415,6 +2513,23 @@ > Params, > 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)); > > Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original) > +++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Sat Nov 15 15:26:17 2008 > @@ -38,6 +38,7 @@ > > class ObjCAtTryStmt; > class ObjCAtThrowStmt; > + class ObjCAtSynchronizedStmt; > class ObjCCategoryImplDecl; > class ObjCImplementationDecl; > class ObjCInterfaceDecl; > @@ -142,6 +143,8 @@ > const ObjCAtTryStmt &S) = 0; > virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, > const ObjCAtThrowStmt &S) = 0; > + virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, > + const ObjCAtSynchronizedStmt &S) = 0; > }; > > /// Creates an instance of an Objective-C runtime class. > > Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sat Nov 15 15:26:17 2008 > @@ -92,7 +92,7 @@ > EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S)); > break; > case Stmt::ObjCAtSynchronizedStmtClass: > - ErrorUnsupported(S, "@synchronized statement"); > + EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S)); > break; > case Stmt::ObjCForCollectionStmtClass: > EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S)); > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=59377&r1=59376&r2=59377&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Nov 15 15:26:17 2008 > @@ -401,6 +401,7 @@ > void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S); > void EmitObjCAtTryStmt(const ObjCAtTryStmt &S); > void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S); > + void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S); > > > //===--------------------------------------------------------------------===// > // LValue Expression Emission > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
