diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-29 22:59:37 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-29 22:59:37 +0000 |
commit | a0f55792409289d1d343023fa8292cff6355e538 (patch) | |
tree | a5d98a138c8c9c5f3e9069844e674bbe8e10e3cb /Driver/RewriteTest.cpp | |
parent | 7d7fe6d539b3bdb1701835223cca306c325614a7 (diff) |
Rewriting of @synchronized. This has one FIXME in it. But this should allow @sychronized to be rewritten.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Driver/RewriteTest.cpp')
-rw-r--r-- | Driver/RewriteTest.cpp | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index 0bcef95476..aac572177a 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -199,6 +199,7 @@ namespace { Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); + Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S); Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S); Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); @@ -807,6 +808,9 @@ Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) return RewriteObjCTryStmt(StmtTry); + if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) + return RewriteObjCSynchronizedStmt(StmtTry); + if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) return RewriteObjCThrowStmt(StmtThrow); @@ -903,7 +907,7 @@ Stmt *RewriteTest::RewriteContinueStmt(ContinueStmt *S) { return 0; } -/// RewriteObjCTryStmt - Rewriter for ObjC2's foreach statement. +/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. /// It rewrites: /// for ( type elem in collection) { stmts; } @@ -1070,6 +1074,54 @@ Stmt *RewriteTest::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S) { return 0; } +/// RewriteObjCSynchronizedStmt - +/// This routine rewrites @synchronized(expr) stmt; +/// into: +/// objc_sync_enter(expr); +/// @try stmt @finally { objc_sync_exit(expr); } +/// +Stmt *RewriteTest::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { + // Get the start location and compute the semi location. + SourceLocation startLoc = S->getLocStart(); + const char *startBuf = SM->getCharacterData(startLoc); + + assert((*startBuf == '@') && "bogus @synchronized location"); + + std::string buf; + buf = "objc_sync_enter"; + Rewrite.ReplaceText(startLoc, 13, buf.c_str(), buf.size()); + SourceLocation endLoc = S->getSynchExpr()->getLocEnd(); + const char *endBuf = SM->getCharacterData(endLoc); + endBuf++; + const char *rparenBuf = strchr(endBuf, ')'); + SourceLocation rparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf); + buf = ");\n"; + // declare a new scope with two variables, _stack and _rethrow. + buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; + buf += "int buf[18/*32-bit i386*/];\n"; + buf += "char *pointers[4];} _stack;\n"; + buf += "id volatile _rethrow = 0;\n"; + buf += "objc_exception_try_enter(&_stack);\n"; + buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; + Rewrite.ReplaceText(rparenLoc, 1, buf.c_str(), buf.size()); + startLoc = S->getSynchBody()->getLocEnd(); + startBuf = SM->getCharacterData(startLoc); + + assert((*startBuf == '}') && "bogus @try block"); + SourceLocation lastCurlyLoc = startLoc; + buf = "}\nelse {\n"; + buf += " _rethrow = objc_exception_extract(&_stack);\n"; + buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; + // FIXME: This must be objc_sync_exit(syncExpr); + buf += " objc_sync_exit();\n"; + buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; + buf += "}\n"; + buf += "}"; + + Rewrite.ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + return 0; +} + Stmt *RewriteTest::RewriteObjCTryStmt(ObjCAtTryStmt *S) { // Get the start location and compute the semi location. SourceLocation startLoc = S->getLocStart(); |