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
 ////////////////////////////////////////////////////////////////////////////////////////*/