diff gen/complex.cpp @ 585:fbb1a366cfbc

Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 09 Sep 2008 16:49:47 -0700
parents a34078905d01
children 192b82878b78
line wrap: on
line diff
--- a/gen/complex.cpp	Mon Sep 08 20:38:55 2008 +0200
+++ b/gen/complex.cpp	Tue Sep 09 16:49:47 2008 -0700
@@ -8,20 +8,15 @@
 #include "gen/llvmhelpers.h"
 #include "gen/irstate.h"
 #include "gen/dvalue.h"
+#include "gen/logger.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 const llvm::StructType* DtoComplexType(Type* type)
 {
     Type* t = type->toBasetype();
-
     const LLType* base = DtoComplexBaseType(t);
-
-    std::vector<const LLType*> types;
-    types.push_back(base);
-    types.push_back(base);
-
-    return llvm::StructType::get(types);
+    return llvm::StructType::get(base, base, NULL);
 }
 
 const LLType* DtoComplexBaseType(Type* t)
@@ -47,19 +42,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLConstant* DtoConstComplex(Type* ty, LLConstant* re, LLConstant* im)
-{
-    assert(0);
-    const LLType* base = DtoComplexBaseType(ty);
-
-    std::vector<LLConstant*> inits;
-    inits.push_back(re);
-    inits.push_back(im);
-
-    const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
-    return llvm::ConstantVector::get(vt, inits);
-}
-
 LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
 {
     TY ty = _ty->toBasetype()->ty;
@@ -108,7 +90,7 @@
 {
     Type* t = val->getType()->toBasetype();
 
-    if (val->isComplex() || t->iscomplex()) {
+    if (t->iscomplex()) {
         return DtoCastComplex(loc, val, to);
     }
 
@@ -127,27 +109,27 @@
         baserety = Type::tfloat80;
         baseimty = Type::timaginary80;
     }
+    else {
+        assert(0);
+    }
+
+    const LLType* complexTy = DtoType(to);
+    LLValue* res;
 
     if (t->isimaginary()) {
-        return new DComplexValue(to, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
+        res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
     }
-    else if (t->isfloating()) {
-        return new DComplexValue(to, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
+    else if (t->isfloating() || t->isintegral()) {
+        res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
     }
-    else if (t->isintegral()) {
-        return new DComplexValue(to, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
+    else {
+        assert(0);
     }
-    assert(0);
+    return new DImValue(to, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoComplexAssign(LLValue* l, LLValue* r)
-{
-    DtoStore(DtoLoad(DtoGEPi(r, 0,0, "tmp")), DtoGEPi(l,0,0,"tmp"));
-    DtoStore(DtoLoad(DtoGEPi(r, 0,1, "tmp")), DtoGEPi(l,0,1,"tmp"));
-}
-
 void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
 {
     DtoStore(re, DtoGEPi(c,0,0,"tmp"));
@@ -158,15 +140,10 @@
 
 void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im)
 {
-    // get LLValues
-    if (DComplexValue* cx = c->isComplex()) {
-        re = cx->re;
-        im = cx->im;
-    }
-    else {
-        re = DtoLoad(DtoGEPi(c->getRVal(),0,0,"tmp"));
-        im = DtoLoad(DtoGEPi(c->getRVal(),0,1,"tmp"));
-    }
+    LLValue* v = c->getRVal();
+    Logger::cout() << "extracting real and imaginary parts from: " << *v << '\n';
+    re = gIR->ir->CreateExtractValue(v, 0, ".re_part");
+    im = gIR->ir->CreateExtractValue(v, 1, ".im_part");
 }
 
 DValue* resolveLR(DValue* val, bool getlval)
@@ -232,7 +209,8 @@
     else // either hasIm(rhstype) or no im at all (then use any)
         res_im = rhs_im;
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -262,7 +240,8 @@
     else
         res_im = lhs_im;
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -314,7 +293,8 @@
     else
         res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null!
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -390,7 +370,8 @@
         res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im");
     }
 
-    return new DComplexValue(type, res_re, res_im);
+    LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -408,7 +389,8 @@
     re = gIR->ir->CreateNeg(a, "tmp");
     im = gIR->ir->CreateNeg(b, "tmp");
 
-    return new DComplexValue(type, re, im);
+    LLValue* res = DtoAggrPair(DtoType(type), re, im);
+    return new DImValue(type, res);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -462,35 +444,35 @@
             re = gIR->ir->CreateFPTrunc(re, toty, "tmp");
             im = gIR->ir->CreateFPTrunc(im, toty, "tmp");
         }
-        else if (to->size() > vty->size()) {
+        else {
             re = gIR->ir->CreateFPExt(re, toty, "tmp");
             im = gIR->ir->CreateFPExt(im, toty, "tmp");
         }
-        else {
-            return val;
+
+        LLValue* pair = DtoAggrPair(DtoType(_to), re, im);
+        DValue* rval = new DImValue(_to, pair);
+
+        // if the value we're casting is not a lvalue, the cast value can't be either
+        if (!val->isLVal()) {
+            return rval;
         }
 
-        if (val->isComplex())
-            return new DComplexValue(_to, re, im);
-
         // unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions.
-        // so we need to give it storage, or fix the system that handles this stuff (DLRValue)
-        LLValue* mem = DtoAlloca(DtoType(_to), "castcomplextmp");
-        DtoComplexSet(mem, re, im);
-        return new DLRValue(val, new DImValue(_to, mem));
+        // so we need to maintain the storage
+        return new DLRValue(val, rval);
     }
     else if (to->isimaginary()) {
-        if (val->isComplex())
-            return new DImValue(to, val->isComplex()->im);
+        // FIXME: this loads both values, even when we only need one
         LLValue* v = val->getRVal();
-        DImValue* im = new DImValue(to, DtoLoad(DtoGEPi(v,0,1,"tmp")));
+        LLValue* impart = gIR->ir->CreateExtractValue(v, 1, ".im_part");
+        DImValue* im = new DImValue(to, impart);
         return DtoCastFloat(loc, im, to);
     }
     else if (to->isfloating()) {
-        if (val->isComplex())
-            return new DImValue(to, val->isComplex()->re);
+        // FIXME: this loads both values, even when we only need one
         LLValue* v = val->getRVal();
-        DImValue* re = new DImValue(to, DtoLoad(DtoGEPi(v,0,0,"tmp")));
+        LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part");
+        DImValue* re = new DImValue(to, repart);
         return DtoCastFloat(loc, re, to);
     }
     else