diff gen/abi.cpp @ 1018:e8c6dbcd33d1

- Fixed x86-32 C ABI for complex number return values. - Removed unused code from the ABI class.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 01 Mar 2009 19:01:05 +0100
parents c749648ed2b8
children 9167d492cbc2
line wrap: on
line diff
--- a/gen/abi.cpp	Sun Mar 01 11:04:05 2009 +0100
+++ b/gen/abi.cpp	Sun Mar 01 19:01:05 2009 +0100
@@ -85,7 +85,65 @@
     }
     bool test(TypeFunction* tf)
     {
-        return (tf->next->toBasetype()->iscomplex());
+        // extern(D) && is(T:creal)
+        return (tf->linkage == LINKd && tf->next->toBasetype()->iscomplex());
+    }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+struct X86_cfloat_rewrite : ABIRetRewrite
+{
+    // i64 -> {float,float}
+    LLValue* get(LLValue* in)
+    {
+        // extract real part
+        LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::Int32Ty);
+        rpart = gIR->ir->CreateBitCast(rpart, LLType::FloatTy, ".re");
+
+        // extract imag part
+        LLValue* ipart = gIR->ir->CreateLShr(in, LLConstantInt::get(LLType::Int64Ty, 32, false));
+        ipart = gIR->ir->CreateTrunc(ipart, LLType::Int32Ty);
+        ipart = gIR->ir->CreateBitCast(ipart, LLType::FloatTy, ".im");
+
+        // return {float,float} aggr pair with same bits
+        return DtoAggrPair(rpart, ipart, ".final_cfloat");
+    }
+
+    // {float,float} -> i64
+    LLValue* put(LLValue* v)
+    {
+        // extract real
+        LLValue* r = gIR->ir->CreateExtractValue(v, 0);
+        // cast to i32
+        r = gIR->ir->CreateBitCast(r, LLType::Int32Ty);
+        // zext to i64
+        r = gIR->ir->CreateZExt(r, LLType::Int64Ty);
+
+        // extract imag
+        LLValue* i = gIR->ir->CreateExtractValue(v, 1);
+        // cast to i32
+        i = gIR->ir->CreateBitCast(i, LLType::Int32Ty);
+        // zext to i64
+        i = gIR->ir->CreateZExt(i, LLType::Int64Ty);
+        // shift up
+        i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::Int64Ty, 32, false));
+
+        // combine and return
+        return v = gIR->ir->CreateOr(r, i);
+    }
+
+    // {float,float} -> i64
+    const LLType* type(const LLType* t)
+    {
+        return LLType::Int64Ty;
+    }
+
+    // test if rewrite applies to function
+    bool test(TypeFunction* tf)
+    {
+        return (tf->linkage != LINKd) 
+            && (tf->next->toBasetype() == Type::tcomplex32);
     }
 };
 
@@ -96,18 +154,19 @@
     X86TargetABI()
     {
         retOps.push_back(new X87_complex_swap);
+        retOps.push_back(new X86_cfloat_rewrite);
     }
 
-    bool returnInArg(Type* t)
+    bool returnInArg(TypeFunction* tf)
     {
-        Type* rt = t->toBasetype();
-        return (rt->ty == Tstruct);
-    }
-
-    bool passByRef(Type* t)
-    {
-        t = t->toBasetype();
-        return (t->ty == Tstruct || t->ty == Tsarray);
+        Type* rt = tf->next->toBasetype();
+        // D only returns structs on the stack
+        if (tf->linkage == LINKd)
+            return (rt->ty == Tstruct);
+        // other ABI's follow C, which is cdouble and creal returned on the stack
+        // as well as structs
+        else
+            return (rt->ty == Tstruct || rt->ty == Tcomplex64 || rt->ty == Tcomplex80);
     }
 };
 
@@ -194,17 +253,11 @@
         retOps.push_back(new X86_64_cfloat_rewrite);
     }
 
-    bool returnInArg(Type* t)
+    bool returnInArg(TypeFunction* tf)
     {
-        Type* rt = t->toBasetype();
+        Type* rt = tf->next->toBasetype();
         return (rt->ty == Tstruct);
     }
-
-    bool passByRef(Type* t)
-    {
-        t = t->toBasetype();
-        return (t->ty == Tstruct || t->ty == Tsarray);
-    }
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -221,17 +274,11 @@
         // Don't push anything into retOps, assume defaults will be fine.
     }
 
-    bool returnInArg(Type* t)
+    bool returnInArg(TypeFunction* tf)
     {
-        Type* rt = t->toBasetype();
+        Type* rt = tf->next->toBasetype();
         return (rt->ty == Tstruct);
     }
-
-    bool passByRef(Type* t)
-    {
-        t = t->toBasetype();
-        return (t->ty == Tstruct || t->ty == Tsarray);
-    }
 };
 
 //////////////////////////////////////////////////////////////////////////////