diff gen/tollvm.cpp @ 107:3efbcc81ba45 trunk

[svn r111] Fixed most problems with complex number support and added typeinfo for them. Added typeinfo ti_C. Did some changes to the way expressions that have both lvalue and rvalue LLVM values are handled.
author lindquist
date Tue, 20 Nov 2007 00:02:35 +0100
parents 5b5194b25f33
children 288fe1029e1f
line wrap: on
line diff
--- a/gen/tollvm.cpp	Mon Nov 19 06:01:48 2007 +0100
+++ b/gen/tollvm.cpp	Tue Nov 20 00:02:35 2007 +0100
@@ -689,6 +689,10 @@
                 retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
                 DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv));
             }
+            else if (DComplexValue* cv = arg->isComplex()) {
+                retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
+                DtoComplexSet(retval, cv->re, cv->im);
+            }
             else {
                 retval = arg->getRVal();
             }
@@ -719,6 +723,14 @@
                     allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
                 }
             }
+            else if (realtype->iscomplex()) {
+                if (arg->isComplex()) {
+                    allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
+                }
+                else {
+                    allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
+                }
+            }
             else
             assert(0);
 
@@ -736,6 +748,9 @@
             if (sl->len) Logger::cout() << "len = " << *sl->len << '\n';
             assert(0);
         }
+        else if (DComplexValue* cl = arg->isComplex()) {
+            assert(0 && "complex in the wrong place");
+        }
         else {
             retval = arg->getRVal();
         }
@@ -895,19 +910,27 @@
     }
     else if (t->iscomplex()) {
         assert(!lhs->isComplex());
-        if (DComplexValue* cx = rhs->isComplex()) {
-            DtoComplexSet(lhs->getRVal(), cx->re, cx->im);
+
+        llvm::Value* dst;
+        if (DLRValue* lr = lhs->isLRValue()) {
+            dst = lr->getLVal();
+            rhs = DtoCastComplex(rhs, lr->getLType());
         }
         else {
-            DtoComplexAssign(lhs->getRVal(), rhs->getRVal());
+            dst = lhs->getRVal();
         }
+
+        if (DComplexValue* cx = rhs->isComplex())
+            DtoComplexSet(dst, cx->re, cx->im);
+        else
+            DtoComplexAssign(dst, rhs->getRVal());
     }
     else {
         llvm::Value* r = rhs->getRVal();
         llvm::Value* l = lhs->getLVal();
         Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
         const llvm::Type* lit = l->getType()->getContainedType(0);
-        if (r->getType() != lit) {
+        if (r->getType() != lit) { // :(
             r = DtoBitCast(r, lit);
             Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n';
         }
@@ -982,6 +1005,7 @@
         rval = new llvm::PtrToIntInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
     }
     else {
+        Logger::println("invalid cast from '%s' to '%s'", val->getType()->toChars(), to->toChars());
         assert(0);
     }
 
@@ -1040,16 +1064,48 @@
 DValue* DtoCastComplex(DValue* val, Type* _to)
 {
     Type* to = DtoDType(_to);
-    llvm::Value* v = val->getRVal();
+    Type* vty = val->getType();
     if (to->iscomplex()) {
-        assert(0);
+        if (vty->size() == to->size())
+            return val;
+
+        llvm::Value *re, *im;
+        DtoGetComplexParts(val, re, im);
+        const llvm::Type* toty = DtoComplexBaseType(to);
+
+        if (to->size() < vty->size()) {
+            re = gIR->ir->CreateFPTrunc(re, toty, "tmp");
+            im = gIR->ir->CreateFPTrunc(im, toty, "tmp");
+        }
+        else if (to->size() > vty->size()) {
+            re = gIR->ir->CreateFPExt(re, toty, "tmp");
+            im = gIR->ir->CreateFPExt(im, toty, "tmp");
+        }
+        else {
+            return val;
+        }
+
+        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)
+        llvm::Value* mem = new llvm::AllocaInst(DtoType(_to), "castcomplextmp", gIR->topallocapoint());
+        DtoComplexSet(mem, re, im);
+        return new DLRValue(val->getType(), val->getRVal(), _to, mem);
     }
     else if (to->isimaginary()) {
-        DImValue* im = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(1), "im"));
+        if (val->isComplex())
+            return new DImValue(to, val->isComplex()->im);
+        llvm::Value* v = val->getRVal();
+        DImValue* im = new DImValue(to, DtoLoad(DtoGEPi(v,0,1,"tmp")));
         return DtoCastFloat(im, to);
     }
     else if (to->isfloating()) {
-        DImValue* re = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(0), "re"));
+        if (val->isComplex())
+            return new DImValue(to, val->isComplex()->re);
+        llvm::Value* v = val->getRVal();
+        DImValue* re = new DImValue(to, DtoLoad(DtoGEPi(v,0,0,"tmp")));
         return DtoCastFloat(re, to);
     }
     else