diff gen/llvmhelpers.cpp @ 1141:f99a3b393c03

Reorganize EnclosingHandlers to require less changes to the frontend and allow us to implement the synchronized storage class for functions.
author Christian Kamm <kamm incasoftware de>
date Tue, 24 Mar 2009 21:18:18 +0100
parents a08983bf972e
children 40caa8207b3e
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Tue Mar 24 14:34:16 2009 +0100
+++ b/gen/llvmhelpers.cpp	Tue Mar 24 21:18:18 2009 +0100
@@ -110,7 +110,7 @@
 // ASSERT HELPER
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-void DtoAssert(Module* M, Loc* loc, DValue* msg)
+void DtoAssert(Module* M, Loc loc, DValue* msg)
 {
     std::vector<LLValue*> args;
 
@@ -133,7 +133,7 @@
     args.push_back(DtoLoad(M->ir.irModule->fileName));
 
     // line param
-    LLConstant* c = DtoConstUint(loc->linnum);
+    LLConstant* c = DtoConstUint(loc.linnum);
     args.push_back(c);
 
     // call
@@ -172,19 +172,19 @@
 /*////////////////////////////////////////////////////////////////////////////////////////
 // GOTO HELPER
 ////////////////////////////////////////////////////////////////////////////////////////*/
-void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, TryFinallyStatement* sourcetf)
+void DtoGoto(Loc loc, Identifier* target)
 {
     assert(!gIR->scopereturned());
 
     LabelStatement* lblstmt = DtoLabelStatement(target);
     if(!lblstmt) {
-        error(*loc, "the label %s does not exist", target->toChars());
+        error(loc, "the label %s does not exist", target->toChars());
         fatal();
     }
 
     // if the target label is inside inline asm, error
     if(lblstmt->asmLabel) {
-        error(*loc, "cannot goto to label %s inside an inline asm block", target->toChars());
+        error(loc, "cannot goto to label %s inside an inline asm block", target->toChars());
         fatal();
     }
 
@@ -194,25 +194,16 @@
     if (targetBB == NULL)
         targetBB = llvm::BasicBlock::Create("label_" + labelname, gIR->topfunc());
 
-    // find finallys between goto and label
-    EnclosingHandler* endfinally = enclosinghandler;
-    while(endfinally != NULL && endfinally != lblstmt->enclosinghandler) {
-        endfinally = endfinally->getEnclosing();
-    }
-
-    // error if didn't find tf statement of label
-    if(endfinally != lblstmt->enclosinghandler)
-        error(*loc, "cannot goto into try block");
+    // emit code for finallys between goto and label
+    DtoEnclosingHandlers(loc, lblstmt);
 
     // goto into finally blocks is forbidden by the spec
-    // though it should not be problematic to implement
+    // but should work fine
+    /*
     if(lblstmt->tf != sourcetf) {
-        error(*loc, "spec disallows goto into finally block");
+        error(loc, "spec disallows goto into finally block");
         fatal();
-    }
-
-    // emit code for finallys between goto and label
-    DtoEnclosingHandlers(enclosinghandler, endfinally);
+    }*/
 
     llvm::BranchInst::Create(targetBB, gIR->scopebb());
 }
@@ -225,16 +216,11 @@
 void EnclosingSynchro::emitCode(IRState * p)
 {
     if (s->exp)
-        DtoLeaveMonitor(s->llsync);
+        DtoLeaveMonitor(s->exp->toElem(p)->getRVal());
     else
         DtoLeaveCritical(s->llsync);
 }
 
-EnclosingHandler* EnclosingSynchro::getEnclosing()
-{
-    return s->enclosinghandler;
-}
-
 ////////////////////////////////////////////////////////////////////////////////////////
 
 void EnclosingVolatile::emitCode(IRState * p)
@@ -243,11 +229,6 @@
     DtoMemoryBarrier(false, false, true, false);
 }
 
-EnclosingHandler* EnclosingVolatile::getEnclosing()
-{
-    return v->enclosinghandler;
-}
-
 ////////////////////////////////////////////////////////////////////////////////////////
 
 void EnclosingTryFinally::emitCode(IRState * p)
@@ -256,34 +237,43 @@
         tf->finalbody->toIR(p);
 }
 
-EnclosingHandler* EnclosingTryFinally::getEnclosing()
-{
-    return tf->enclosinghandler;
-}
-
 ////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end)
+void DtoEnclosingHandlers(Loc loc, Statement* target)
 {
-    // verify that end encloses start
-    EnclosingHandler* endfinally = start;
-    while(endfinally != NULL && endfinally != end) {
-        endfinally = endfinally->getEnclosing();
+    // labels are a special case: they are not required to enclose the current scope
+    // for them we use the enclosing scope handler as a reference point
+    LabelStatement* lblstmt = dynamic_cast<LabelStatement*>(target);
+    if (lblstmt)
+        target = lblstmt->enclosingScopeExit;
+
+    // figure out up until what handler we need to emit
+    IRState::TargetScopeVec::reverse_iterator targetit;
+    for (targetit = gIR->targetScopes.rbegin(); targetit != gIR->targetScopes.rend(); ++targetit) {
+        if (targetit->s == target) {
+            break;
+        }
     }
-    assert(endfinally == end);
 
+    if (target && targetit == gIR->targetScopes.rend()) {
+        if (lblstmt)
+            error(loc, "cannot goto into try, volatile or synchronized statement at %s", target->loc.toChars());
+        else
+            error(loc, "internal error, cannot find jump path to statement at %s", target->loc.toChars());
+        return;
+    }
 
     //
-    // emit code for finallys between start and end
+    // emit code for enclosing handlers
     //
 
     // since the labelstatements possibly inside are private
     // and might already exist push a label scope
     gIR->func()->pushUniqueLabelScope("enclosing");
-    EnclosingHandler* tf = start;
-    while(tf != end) {
-        tf->emitCode(gIR);
-        tf = tf->getEnclosing();
+    IRState::TargetScopeVec::reverse_iterator it;
+    for (it = gIR->targetScopes.rbegin(); it != targetit; ++it) {
+        if (it->enclosinghandler)
+            it->enclosinghandler->emitCode(gIR);
     }
     gIR->func()->popLabelScope();
 }