[cfe-commits] r59377 - in /cfe/trunk/lib/CodeGen: CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h CGStmt.cpp CodeGenFunction.h

Daniel Dunbar daniel at zuster.org
Tue Nov 18 22:35:05 PST 2008


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 <sabre at nondot.org> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



More information about the cfe-commits mailing list