changeset 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 3b8ada4c9f8b
children 7b1040c76dd2
files dmd/statement.h gen/asmstmt.cpp gen/d-asm-i386.h gen/irstate.h gen/statements.cpp
diffstat 5 files changed, 68 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/statement.h	Tue Jun 24 17:24:55 2008 +0200
+++ b/dmd/statement.h	Tue Jun 24 21:38:23 2008 +0200
@@ -791,6 +791,10 @@
     virtual AsmStatement *isAsmStatement() { return this; }
 
     void toIR(IRState *irs);
+
+    // LLVMDC
+    // non-zero if this is a branch, contains the target
+    Identifier* isBranchToLabel;
 };
 
 struct AsmBlockStatement : CompoundStatement
--- 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
+}
--- a/gen/d-asm-i386.h	Tue Jun 24 17:24:55 2008 +0200
+++ b/gen/d-asm-i386.h	Tue Jun 24 21:38:23 2008 +0200
@@ -1427,7 +1427,7 @@
     }
 
     void addLabel(char* id) {
-    insnTemplate->writestring(".LDASM_");
+    //insnTemplate->writestring(".LDASM_");
     insnTemplate->writestring(id);
     }
 
@@ -1911,9 +1911,12 @@
 			    asmcode->dollarLabel = lbl_num; // could make the dollar label part of the same asm..
 			} else if (e->op == TOKdsymbol) {
 			    LabelDsymbol * lbl = (LabelDsymbol *) ((DsymbolExp *) e)->s;
+			    // this can probably be removed
 			    if (! lbl->asmLabelNum)
 				lbl->asmLabelNum = ++d_priv_asm_label_serial;
 
+			    stmt->isBranchToLabel = lbl->ident;
+
 			    use_star = false;
 			    addLabel(lbl->ident->toChars());
 			} else if ((decl && decl->isCodeseg())) { // if function or label
--- a/gen/irstate.h	Tue Jun 24 17:24:55 2008 +0200
+++ b/gen/irstate.h	Tue Jun 24 21:38:23 2008 +0200
@@ -72,12 +72,18 @@
     std::string in_c;
     std::vector<LLValue*> out;
     std::vector<LLValue*> in;
+
+    // if this is nonzero, it contains the target ident
+    Identifier* isBranchToLabel;
 };
 
 struct IRAsmBlock
 {
     std::vector<IRAsmStmt*> s;
     std::set<std::string> clobs;
+
+    // stores the labels within the asm block
+    std::vector<Identifier*> internalLabels;
 };
 
 // represents the module
--- a/gen/statements.cpp	Tue Jun 24 17:24:55 2008 +0200
+++ b/gen/statements.cpp	Tue Jun 24 21:38:23 2008 +0200
@@ -1066,10 +1066,11 @@
     if (p->asmBlock)
     {
         IRAsmStmt* a = new IRAsmStmt;
-        a->code = ".LDASM_";
+//        a->code = ".LDASM_";
         a->code += ident->toChars();
         a->code += ":";
         p->asmBlock->s.push_back(a);
+        p->asmBlock->internalLabels.push_back(ident);
     }
     else
     {