changeset 312:553f844ae5b9 trunk

[svn r333] Fix inline asm bug with multiple branches to the same label.
author ChristianK
date Sun, 29 Jun 2008 22:07:15 +0200
parents 9967a3270837
children a498b736a0bd
files gen/asmstmt.cpp
diffstat 1 files changed, 14 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/gen/asmstmt.cpp	Sat Jun 28 18:37:27 2008 +0200
+++ b/gen/asmstmt.cpp	Sun Jun 29 22:07:15 2008 +0200
@@ -460,10 +460,10 @@
     // to a unique value that will identify the jump target in
     // a post-asm switch
 
-    // maps each special value to a goto destination
-    std::map<int, Identifier*> valToGoto;
+    // maps each goto destination to its special value
+    std::map<Identifier*, int> gotoToVal;
 
-    // location of the value containing the index into the valToGoto map
+    // location of the special value determining the goto label
     // will be set if post-asm dispatcher block is needed
     llvm::AllocaInst* jump_target;
 
@@ -503,8 +503,12 @@
             if(skip) 
                 continue;
 
+            // if we already set things up for this branch target, skip
+            if(gotoToVal.find(a->isBranchToLabel) != gotoToVal.end())
+                continue;
+
             // record that the jump needs to be handled in the post-asm dispatcher
-            valToGoto[n_goto] = a->isBranchToLabel;
+            gotoToVal[a->isBranchToLabel] = n_goto;
 
             // provide an in-asm target for the branch and set value
             Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string);
@@ -619,7 +623,7 @@
     Logger::println("END ASM");
 
     // if asm contained external branches, emit goto forwarder code
-    if(!valToGoto.empty())
+    if(!gotoToVal.empty())
     {
         assert(jump_target);
 
@@ -628,17 +632,17 @@
         llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterasmgotoforwarder", p->topfunc(), oldend);
 
         llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value");
-        llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size());
+        llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, gotoToVal.size());
 
         // add all cases
-        std::map<int, Identifier*>::iterator it, end = valToGoto.end();
-        for(it = valToGoto.begin(); it != end; ++it)
+        std::map<Identifier*, int>::iterator it, end = gotoToVal.end();
+        for(it = gotoToVal.begin(); it != end; ++it)
         {
             llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb);
-            sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb);
+            sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->second), casebb);
 
             p->scope() = IRScope(casebb,bb);
-            DtoGoto(&loc, it->second, enclosinghandler);
+            DtoGoto(&loc, it->first, enclosinghandler);
         }
 
         p->scope() = IRScope(bb,oldend);