diff gen/asmstmt.cpp @ 299:df8a7b8d5929 trunk

[svn r320] Begun work on branches out of asm blocks. Unfinished.
author ChristianK
date Tue, 24 Jun 2008 21:38:23 +0200
parents fa691b1c0498
children 7b1040c76dd2
line wrap: on
line diff
--- a/gen/asmstmt.cpp	Tue Jun 24 17:24:55 2008 +0200
+++ b/gen/asmstmt.cpp	Tue Jun 24 21:38:23 2008 +0200
@@ -78,6 +78,8 @@
     refparam = 0;
     naked = 0;
     regs = 0;
+
+    isBranchToLabel = NULL;
 }
 
 Statement *AsmStatement::syntaxCopy()
@@ -433,6 +435,7 @@
     asmStmt->in_c = llvmInConstraints;
     asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end());
     asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end());
+    asmStmt->isBranchToLabel = isBranchToLabel;
     asmblock->s.push_back(asmStmt);
 }
 
@@ -508,6 +511,51 @@
         }
     }
 
+    // build forwarder for in-asm branches to external labels
+    // this additional asm code sets the __llvm_jump_target variable
+    // to a unique value that will identify the jump target in
+    // a post-asm switch
+    //FIXME: Need to init __llvm_jump_target
+    //FIXME: Store the value -> label mapping somewhere, so it can be referenced later
+    std::string asmGotoEnd = "jmp __llvm_asm_end ; ";
+    std::string outGotoSetter = asmGotoEnd;
+
+    size_t n = asmblock->s.size();
+    for(size_t i=0; i<n; ++i)
+    {
+        IRAsmStmt* a = asmblock->s[i];
+
+        // skip non-branch statements
+        if(!a->isBranchToLabel)
+            continue;
+
+        // if internal, no special handling is necessary, skip
+        std::vector<Identifier*>::const_iterator it, end;
+        end = asmblock->internalLabels.end();
+        bool skip = false;
+        for(it = asmblock->internalLabels.begin(); it != end; ++it)
+            if((*it)->equals(a->isBranchToLabel))
+                skip = true;
+        if(skip) 
+            continue;
+
+        // 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);
+        outGotoSetter += a->isBranchToLabel->string;
+        outGotoSetter += ": ; ";
+        outGotoSetter += "nop ; "; //FIXME: Change this to set __llvm_jump_target to a unique value
+        outGotoSetter += asmGotoEnd;
+    }
+    if(outGotoSetter != asmGotoEnd)
+    {
+        outGotoSetter += "__llvm_asm_end: ; ";
+        IRAsmStmt* outSetterStmt = new IRAsmStmt;
+        outSetterStmt->code = outGotoSetter;
+        //FIXME: set other stuff
+        asmblock->s.push_back(outSetterStmt);
+    }
+
+
     // build asm block
     std::vector<LLValue*> outargs;
     std::vector<LLValue*> inargs;
@@ -519,7 +567,7 @@
     std::string code;
     size_t asmIdx = 0;
 
-    size_t n = asmblock->s.size();
+    n = asmblock->s.size();
     for (size_t i=0; i<n; ++i)
     {
         IRAsmStmt* a = asmblock->s[i];
@@ -588,6 +636,8 @@
 
     p->asmBlock = NULL;
     Logger::println("END ASM");
+
+    //FIXME: Emit goto forwarder code here
 }
 
 // the whole idea of this statement is to avoid the flattening
@@ -609,4 +659,4 @@
     }
     AsmBlockStatement *cs = new AsmBlockStatement(loc, a);
     return cs;
-}
\ No newline at end of file
+}