diff gen/asmstmt.cpp @ 305:2b72433d5c8c trunk

[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support. Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its Identifier, which should be useful elsewhere too. Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author lindquist
date Fri, 27 Jun 2008 22:04:35 +0200
parents 3ebc136702dd
children d59c363fccad
line wrap: on
line diff
--- a/gen/asmstmt.cpp	Wed Jun 25 23:42:38 2008 +0200
+++ b/gen/asmstmt.cpp	Fri Jun 27 22:04:35 2008 +0200
@@ -461,16 +461,24 @@
     // a post-asm switch
 
     // maps each special value to a goto destination
-    std::map<int, LabelDsymbol*> valToGoto;
+    std::map<int, Identifier*> valToGoto;
 
     // location of the value containing the index into the valToGoto map
     // will be set if post-asm dispatcher block is needed
     llvm::AllocaInst* jump_target;
 
     {
+        FuncDeclaration* fd = gIR->func()->decl;
+        char* fdmangle = fd->mangle();
+
+        // we use a simple static counter to make sure the new end labels are unique
+        static size_t uniqueLabelsId = 0;
+        std::ostringstream asmGotoEndLabel;
+        asmGotoEndLabel << "." << fdmangle << "__llvm_asm_end" << uniqueLabelsId++;
+
         // initialize the setter statement we're going to build
         IRAsmStmt* outSetterStmt = new IRAsmStmt;
-        std::string asmGotoEnd = "jmp __llvm_asm_end ; ";
+        std::string asmGotoEnd = "jmp "+asmGotoEndLabel.str()+" ; ";
         std::ostringstream code;
         code << asmGotoEnd;
 
@@ -490,7 +498,7 @@
             end = asmblock->internalLabels.end();
             bool skip = false;
             for(it = asmblock->internalLabels.begin(); it != end; ++it)
-                if((*it)->equals(a->isBranchToLabel->ident))
+                if((*it)->equals(a->isBranchToLabel))
                     skip = true;
             if(skip) 
                 continue;
@@ -499,11 +507,11 @@
             valToGoto[n_goto] = a->isBranchToLabel;
 
             // 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->ident->string);
-            code << a->isBranchToLabel->ident->string << ": ; ";
+            Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string);
+            code << fdmangle << '_' << a->isBranchToLabel->string << ": ; ";
             code << "movl $<<in" << n_goto << ">>, $<<out0>> ; ";
             //FIXME: Store the value -> label mapping somewhere, so it can be referenced later
-            outSetterStmt->in.push_back(llvm::ConstantInt::get(llvm::IntegerType::get(32), n_goto));
+            outSetterStmt->in.push_back(DtoConstUint(n_goto));
             outSetterStmt->in_c += "i,";
             code << asmGotoEnd;
 
@@ -513,11 +521,11 @@
         {
             // finalize code
             outSetterStmt->code = code.str();
-            outSetterStmt->code += "__llvm_asm_end: ; ";
+            outSetterStmt->code += asmGotoEndLabel.str()+": ; ";
 
             // create storage for and initialize the temporary
             jump_target = new llvm::AllocaInst(llvm::IntegerType::get(32), "__llvm_jump_target", p->topallocapoint());
-            gIR->ir->CreateStore(llvm::ConstantInt::get(llvm::IntegerType::get(32), 0), jump_target);
+            gIR->ir->CreateStore(DtoConstUint(0), jump_target);
             // setup variable for output from asm
             outSetterStmt->out_c = "=*m,";
             outSetterStmt->out.push_back(jump_target);
@@ -623,7 +631,7 @@
         llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size());
 
         // add all cases
-        std::map<int, LabelDsymbol*>::iterator it, end = valToGoto.end();
+        std::map<int, Identifier*>::iterator it, end = valToGoto.end();
         for(it = valToGoto.begin(); it != end; ++it)
         {
             llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb);