changeset 1154:9279a9dc6df3

Added support for tuple return with __asmtuple!(int,int) etc.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Sat, 28 Mar 2009 08:25:58 +0100
parents 4454126b4345
children ba9d6292572a
files gen/naked.cpp runtime/import/ldc/llvmasm.di tests/mini/__asm1.d
diffstat 3 files changed, 53 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/gen/naked.cpp	Sat Mar 28 07:24:53 2009 +0100
+++ b/gen/naked.cpp	Sat Mar 28 08:25:58 2009 +0100
@@ -376,17 +376,36 @@
     }
 
     // build asm function type
-    const llvm::Type* ret_type = DtoType(fd->type->nextOf());
+    Type* type = fd->type->nextOf()->toBasetype();
+    const llvm::Type* ret_type = DtoType(type);
     llvm::FunctionType* FT = llvm::FunctionType::get(ret_type, argtypes, false);
 
     // build asm call
     bool sideeffect = true;
     llvm::InlineAsm* ia = llvm::InlineAsm::get(FT, code, constraints, sideeffect);
 
-    llvm::Value* v = gIR->ir->CreateCall(ia, args.begin(), args.end(), "");
+    llvm::Value* rv = gIR->ir->CreateCall(ia, args.begin(), args.end(), "");
+
+    // work around missing tuple support for users of the return value
+    if (type->ty == Tstruct)
+    {
+        // make a copy
+        llvm::Value* mem = DtoAlloca(ret_type, ".__asm_tuple_ret");
+
+        TypeStruct* ts = (TypeStruct*)type;
+        size_t n = ts->sym->fields.dim;
+        for (size_t i = 0; i < n; i++)
+        {
+            llvm::Value* v = gIR->ir->CreateExtractValue(rv, i, "");
+            llvm::Value* gep = DtoGEPi(mem, 0, i);
+            DtoStore(v, gep);
+        }
+
+        return new DVarValue(fd->type->nextOf(), mem);
+    }
 
     // return call as im value
-    return new DImValue(fd->type->nextOf(), v);
+    return new DImValue(fd->type->nextOf(), rv);
 }
 
 
--- a/runtime/import/ldc/llvmasm.di	Sat Mar 28 07:24:53 2009 +0100
+++ b/runtime/import/ldc/llvmasm.di	Sat Mar 28 08:25:58 2009 +0100
@@ -1,13 +1,17 @@
 module ldc.llvmasm;
 
-pragma(llvm_inline_asm)
-template __asm()
+struct __asmtuple_t(T...)
 {
-    void __asm(char[] asmcode, char[] constraints, ...);
+    T v;
 }
 
 pragma(llvm_inline_asm)
-template __asm(T)
 {
-    T __asm(char[] asmcode, char[] constraints, ...);
+    void __asm( )(char[] asmcode, char[] constraints, ...);
+    T    __asm(T)(char[] asmcode, char[] constraints, ...);
+
+    template __asmtuple(T...)
+    {
+        __asmtuple_t!(T) __asmtuple(char[] asmcode, char[] constraints, ...);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/__asm1.d	Sat Mar 28 08:25:58 2009 +0100
@@ -0,0 +1,22 @@
+import ldc.llvmasm;
+void main() {
+    version(X86)
+    {
+        int i;
+        __asm("movl $1, $0", "=*m,i", &i, 42);
+        assert(i == 42);
+
+        int j = __asm!(int)("movl $1, %eax", "={ax},i", 42);
+        assert(j == 42);
+
+        auto k = __asmtuple!(int,int)("mov $2, %eax ; mov $3, %edx", "={ax},={dx},i,i", 10, 20);
+        assert(k.v[0] == 10);
+        assert(k.v[1] == 20);
+    }
+    else version(PPC)
+    {
+        int j = 42;
+        int i = __asm!(int)("li $1, $0", "=r,*m", &j);
+        assert(i == 42);
+    }
+}