Mercurial > projects > ldc
diff gen/llvmhelpers.cpp @ 309:d59c363fccad trunk
[svn r330] Implemented synchronized statements.
Changed the tryfinally handlers to a more generalized EnclosingHandler.
Changed ClassInfoS to be mutable so they can be used as locks.
Added new BB after throw ala return/break etc.
author | lindquist |
---|---|
date | Sat, 28 Jun 2008 11:37:53 +0200 |
parents | 2b72433d5c8c |
children | a9697749e898 |
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/llvmhelpers.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -174,7 +174,7 @@ /*//////////////////////////////////////////////////////////////////////////////////////// // GOTO HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ -void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally) +void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler) { assert(!gIR->scopereturned()); @@ -189,44 +189,117 @@ lblstmt->llvmBB = llvm::BasicBlock::Create("label", gIR->topfunc()); // find finallys between goto and label - TryFinallyStatement* endfinally = enclosingtryfinally; - while(endfinally != NULL && endfinally != lblstmt->enclosingtryfinally) { - endfinally = endfinally->enclosingtryfinally; + EnclosingHandler* endfinally = enclosinghandler; + while(endfinally != NULL && endfinally != lblstmt->enclosinghandler) { + endfinally = endfinally->getEnclosing(); } // error if didn't find tf statement of label - if(endfinally != lblstmt->enclosingtryfinally) + if(endfinally != lblstmt->enclosinghandler) error("cannot goto into try block", loc->toChars()); // emit code for finallys between goto and label - DtoFinallyBlocks(enclosingtryfinally, endfinally); + DtoEnclosingHandlers(enclosinghandler, endfinally); llvm::BranchInst::Create(lblstmt->llvmBB, gIR->scopebb()); } /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// -// TRY FINALLY HELPER +// TRY-FINALLY, VOLATILE AND SYNCHRONIZED HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ -void DtoFinallyBlocks(TryFinallyStatement* start, TryFinallyStatement* end) + +void EnclosingSynchro::emitCode(IRState * p) +{ + if (s->exp) + DtoLeaveMonitor(s->llsync); + else + DtoLeaveCritical(s->llsync); +} + +EnclosingHandler* EnclosingSynchro::getEnclosing() +{ + return s->enclosinghandler; +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void EnclosingVolatile::emitCode(IRState * p) +{ + // store-load barrier + DtoMemoryBarrier(false, false, true, false); +} + +EnclosingHandler* EnclosingVolatile::getEnclosing() +{ + return v->enclosinghandler; +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void EnclosingTryFinally::emitCode(IRState * p) +{ + assert(tf->finalbody); + tf->finalbody->toIR(p); +} + +EnclosingHandler* EnclosingTryFinally::getEnclosing() +{ + return tf->enclosinghandler; +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end) { // verify that end encloses start - TryFinallyStatement* endfinally = start; + EnclosingHandler* endfinally = start; while(endfinally != NULL && endfinally != end) { - endfinally = endfinally->enclosingtryfinally; + endfinally = endfinally->getEnclosing(); } assert(endfinally == end); // emit code for finallys between start and end - TryFinallyStatement* tf = start; + EnclosingHandler* tf = start; while(tf != end) { - tf->finalbody->toIR(gIR); - tf = tf->enclosingtryfinally; + tf->emitCode(gIR); + tf = tf->getEnclosing(); } } /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// +// SYNCHRONIZED SECTION HELPERS +////////////////////////////////////////////////////////////////////////////////////////*/ + +void DtoEnterCritical(LLValue* g) +{ + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_criticalenter"); + gIR->ir->CreateCall(fn, g, ""); +} + +void DtoLeaveCritical(LLValue* g) +{ + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_criticalexit"); + gIR->ir->CreateCall(fn, g, ""); +} + +void DtoEnterMonitor(LLValue* v) +{ + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_monitorenter"); + v = DtoBitCast(v, fn->getFunctionType()->getParamType(0)); + gIR->ir->CreateCall(fn, v, ""); +} + +void DtoLeaveMonitor(LLValue* v) +{ + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_monitorexit"); + v = DtoBitCast(v, fn->getFunctionType()->getParamType(0)); + gIR->ir->CreateCall(fn, v, ""); +} + +/****************************************************************************************/ +/*//////////////////////////////////////////////////////////////////////////////////////// // NESTED VARIABLE HELPERS ////////////////////////////////////////////////////////////////////////////////////////*/