diff options
| author | Chris Lattner <sabre@nondot.org> | 2008-11-15 21:26:17 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2008-11-15 21:26:17 +0000 | 
| commit | e132e2432a3834f6128ffe304b04ec58b415af3a (patch) | |
| tree | 97a5e302dccb46fc3bd458c3eded056bc90d60e5 /clang/lib/CodeGen | |
| parent | 7e173692555e075ce7f315ee0f8c47f68a688fb3 (diff) | |
| download | bcm5719-llvm-e132e2432a3834f6128ffe304b04ec58b415af3a.tar.gz bcm5719-llvm-e132e2432a3834f6128ffe304b04ec58b415af3a.zip | |
Start implementing support for @synchonized with the darwin ObjC API.
Patch by Fariborz!
llvm-svn: 59377
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 117 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCRuntime.h | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | 
6 files changed, 134 insertions, 2 deletions
| diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 3ffdb4d8667..058278cfa4e 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -533,4 +533,10 @@ void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S)    CGM.getObjCRuntime().EmitThrowStmt(*this, S);  } +void CodeGenFunction::EmitObjCAtSynchronizedStmt( +                                              const ObjCAtSynchronizedStmt &S) +{ +  CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); +} +  CGObjCRuntime::~CGObjCRuntime() {} diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4afbf3c2fb4..4726be21151 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -128,6 +128,8 @@ public:                             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 @@ void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,    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);  } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 70b9b49f7dd..296b1af5518 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -155,7 +155,13 @@ public:    /// 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 @@ public:                             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 @@ void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E,    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 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)                                                        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)); diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index d690289f140..435e1483e38 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -38,6 +38,7 @@ namespace CodeGen {    class ObjCAtTryStmt;    class ObjCAtThrowStmt; +  class ObjCAtSynchronizedStmt;    class ObjCCategoryImplDecl;    class ObjCImplementationDecl;    class ObjCInterfaceDecl; @@ -142,6 +143,8 @@ public:                             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.   diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 767e275d2d2..3f2cd803dab 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -92,7 +92,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {      EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S));      break;    case Stmt::ObjCAtSynchronizedStmtClass: -    ErrorUnsupported(S, "@synchronized statement"); +    EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S));      break;    case Stmt::ObjCForCollectionStmtClass:       EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S)); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 50b35bd8cdb..5d99dba69a8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -401,6 +401,7 @@ public:    void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);    void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);    void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S); +  void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);    //===--------------------------------------------------------------------===//    //                         LValue Expression Emission | 

