[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