changeset 954:e048e36bc155

Added support for using a temporary to implement emulated ABI return from inline asm, could be easier to use, but I think this will do. It's so extremely target dependent in any case that doing a completely generic approach seems hard.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 14 Feb 2009 15:25:48 +0100
parents 5fa3e0ea06e9
children 8a70b4381369
files gen/asmstmt.cpp gen/irstate.h gen/naked.cpp
diffstat 3 files changed, 31 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/gen/asmstmt.cpp	Fri Feb 13 22:20:30 2009 +0100
+++ b/gen/asmstmt.cpp	Sat Feb 14 15:25:48 2009 +0100
@@ -629,7 +629,7 @@
         }
         remap_inargs(a->code, inn+a->out.size(), asmIdx);
         if (!code.empty())
-            code += " ; ";
+            code += "\n\t";
         code += a->code;
     }
     asmblock->s.clear();
@@ -671,8 +671,13 @@
     args.insert(args.end(), outargs.begin(), outargs.end());
     args.insert(args.end(), inargs.begin(), inargs.end());
     llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), "");
+
+    // capture abi return value
     if (useabiret)
     {
+        if (p->asmBlock->retemu)
+        p->asmBlock->asmBlock->abiret = DtoLoad(p->asmBlock->asmBlock->abiret);
+        else
         p->asmBlock->asmBlock->abiret = call;
     }
 
--- a/gen/irstate.h	Fri Feb 13 22:20:30 2009 +0100
+++ b/gen/irstate.h	Sat Feb 14 15:25:48 2009 +0100
@@ -88,8 +88,9 @@
     AsmBlockStatement* asmBlock;
     const LLType* retty;
     unsigned retn;
+    bool retemu; // emulate abi ret with a temporary
 
-    IRAsmBlock(AsmBlockStatement* b) : asmBlock(b), retty(NULL), retn(0) {}
+    IRAsmBlock(AsmBlockStatement* b) : asmBlock(b), retty(NULL), retn(0), retemu(false) {}
 };
 
 // llvm::CallInst and llvm::InvokeInst don't share a common base
--- a/gen/naked.cpp	Fri Feb 13 22:20:30 2009 +0100
+++ b/gen/naked.cpp	Sat Feb 14 15:25:48 2009 +0100
@@ -207,6 +207,29 @@
         {
             as->out_c = "={ax},={dx},";
             asmblock->retn = 2;
+        #if 0
+            // this is to show how to allocate a temporary for the return value
+            // in case the appropriate multi register constraint isn't supported.
+            // this way abi return from inline asm can still be emulated.
+
+            // generate asm
+            as->out_c = "=*m,=*m,";
+            LLValue* tmp = DtoAlloca(llretTy, ".tmp_asm_ret");
+            as->out.push_back( tmp );
+            as->out.push_back( DtoGEPi(tmp, 0,1) );
+            as->code = "movd %eax, $<<out0>>" "\n\t" "mov %edx, $<<out1>>";
+
+            // fix asmblock
+            asmblock->retn = 0;
+            asmblock->retemu = true;
+            asmblock->asmBlock->abiret = tmp;
+
+            // add "ret" stmt
+            asmblock->s.push_back(as);
+
+            // done, we don't want anything pushed in the front of the block
+            return;
+        #endif
         }
         else
         {