diff gen/complex.cpp @ 104:4d1e9eb001e0 trunk

[svn r108] Now basic suppport for complex types. =,+,-,*,/ are supported.
author lindquist
date Mon, 19 Nov 2007 02:58:58 +0100
parents
children 3efbcc81ba45
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/complex.cpp	Mon Nov 19 02:58:58 2007 +0100
@@ -0,0 +1,358 @@
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "declaration.h"
+
+#include "gen/complex.h"
+#include "gen/tollvm.h"
+#include "gen/irstate.h"
+#include "gen/dvalue.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::StructType* DtoComplexType(Type* type)
+{
+    Type* t = DtoDType(type);
+
+    const llvm::Type* base = DtoComplexBaseType(t);
+
+    std::vector<const llvm::Type*> types;
+    types.push_back(base);
+    types.push_back(base);
+
+    return llvm::StructType::get(types);
+}
+
+const llvm::Type* DtoComplexBaseType(Type* t)
+{
+    TY ty = DtoDType(t)->ty;
+    const llvm::Type* base;
+    if (ty == Tcomplex32) {
+        return llvm::Type::FloatTy;
+    }
+    else if (ty == Tcomplex64 || ty == Tcomplex80) {
+        return llvm::Type::DoubleTy;
+    }
+    else {
+        assert(0);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* DtoConstComplex(Type* ty, llvm::Constant* re, llvm::Constant* im)
+{
+    assert(0);
+    const llvm::Type* base = DtoComplexBaseType(ty);
+
+    std::vector<llvm::Constant*> inits;
+    inits.push_back(re);
+    inits.push_back(im);
+
+    const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
+    return llvm::ConstantVector::get(vt, inits);
+}
+
+llvm::Constant* DtoConstComplex(Type* _ty, long double re, long double im)
+{
+    TY ty = DtoDType(_ty)->ty;
+
+    llvm::ConstantFP* fre;
+    llvm::ConstantFP* fim;
+
+    const llvm::Type* base;
+
+    if (ty == Tcomplex32) {
+        fre = DtoConstFP(Type::tfloat32, re);
+        fim = DtoConstFP(Type::tfloat32, im);
+        base = llvm::Type::FloatTy;
+    }
+    else if (ty == Tcomplex64 || ty == Tcomplex80) {
+        fre = DtoConstFP(Type::tfloat64, re);
+        fim = DtoConstFP(Type::tfloat64, im);
+        base = llvm::Type::DoubleTy;
+    }
+    else
+    assert(0);
+
+    std::vector<llvm::Constant*> inits;
+    inits.push_back(fre);
+    inits.push_back(fim);
+    return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
+}
+
+llvm::Constant* DtoUndefComplex(Type* _ty)
+{
+    assert(0);
+    TY ty = DtoDType(_ty)->ty;
+    const llvm::Type* base;
+    if (ty == Tcomplex32) {
+        base = llvm::Type::FloatTy;
+    }
+    else if (ty == Tcomplex64 || ty == Tcomplex80) {
+        base = llvm::Type::DoubleTy;
+    }
+    else
+    assert(0);
+
+    std::vector<llvm::Constant*> inits;
+    inits.push_back(llvm::UndefValue::get(base));
+    inits.push_back(llvm::UndefValue::get(base));
+
+    const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
+    return llvm::ConstantVector::get(vt, inits);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoRealPart(DValue* val)
+{
+    assert(0);
+    return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(0), "tmp");
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoImagPart(DValue* val)
+{
+    assert(0);
+    return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(1), "tmp");
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoComplex(Type* to, DValue* val)
+{
+    Type* t = DtoDType(val->getType());
+    TY ty = t->ty;
+
+    if (val->isComplex() || t->iscomplex()) {
+        assert(DtoDType(to) == t);
+        return val;
+    }
+
+    const llvm::Type* base = DtoComplexBaseType(to);
+
+    llvm::Constant* undef = llvm::UndefValue::get(base);
+    llvm::Constant* zero;
+    if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
+        zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0));
+    else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
+        zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0));
+
+    if (t->isimaginary()) {
+        return new DComplexValue(to, zero, val->getRVal());
+    }
+    else if (t->isfloating()) {
+        return new DComplexValue(to, val->getRVal(), zero);
+    }
+    else
+    assert(0);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoComplexAssign(llvm::Value* l, llvm::Value* 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(llvm::Value* c, llvm::Value* re, llvm::Value* im)
+{
+    DtoStore(re, DtoGEPi(c,0,0,"tmp"));
+    DtoStore(im, DtoGEPi(c,0,1,"tmp"));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoComplexAdd(Type* type, DValue* lhs, DValue* rhs)
+{
+    lhs = DtoComplex(type, lhs);
+    rhs = DtoComplex(type, rhs);
+
+    llvm::Value *a, *b, *c, *d, *re, *im;
+
+    // lhs values
+    if (DComplexValue* cx = lhs->isComplex()) {
+        a = cx->re;
+        b = cx->im;
+    }
+    else {
+        a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
+        b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
+    }
+
+    // rhs values
+    if (DComplexValue* cx = rhs->isComplex()) {
+        c = cx->re;
+        d = cx->im;
+    }
+    else {
+        c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
+        d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
+    }
+
+    // add up
+    re = gIR->ir->CreateAdd(a, c, "tmp");
+    im = gIR->ir->CreateAdd(b, d, "tmp");
+
+    return new DComplexValue(type, re, im);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoComplexSub(Type* type, DValue* lhs, DValue* rhs)
+{
+    lhs = DtoComplex(type, lhs);
+    rhs = DtoComplex(type, rhs);
+
+    llvm::Value *a, *b, *c, *d, *re, *im;
+
+    // lhs values
+    if (DComplexValue* cx = lhs->isComplex()) {
+        a = cx->re;
+        b = cx->im;
+    }
+    else {
+        a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
+        b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
+    }
+
+    // rhs values
+    if (DComplexValue* cx = rhs->isComplex()) {
+        c = cx->re;
+        d = cx->im;
+    }
+    else {
+        c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
+        d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
+    }
+
+    // add up
+    re = gIR->ir->CreateSub(a, c, "tmp");
+    im = gIR->ir->CreateSub(b, d, "tmp");
+
+    return new DComplexValue(type, re, im);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoComplexMul(Type* type, DValue* lhs, DValue* rhs)
+{
+    lhs = DtoComplex(type, lhs);
+    rhs = DtoComplex(type, rhs);
+
+    llvm::Value *a, *b, *c, *d, *re, *im;
+
+    // lhs values
+    if (DComplexValue* cx = lhs->isComplex()) {
+        a = cx->re;
+        b = cx->im;
+    }
+    else {
+        a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
+        b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
+    }
+
+    // rhs values
+    if (DComplexValue* cx = rhs->isComplex()) {
+        c = cx->re;
+        d = cx->im;
+    }
+    else {
+        c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
+        d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
+    }
+
+    llvm::Value *tmp1, *tmp2;
+
+    tmp1 = gIR->ir->CreateMul(a, c, "tmp");
+    tmp2 = gIR->ir->CreateMul(b, d, "tmp");
+    re = gIR->ir->CreateSub(tmp1, tmp2, "tmp");
+
+    tmp1 = gIR->ir->CreateMul(b, c, "tmp");
+    tmp2 = gIR->ir->CreateMul(a, d, "tmp");
+    im = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
+
+    return new DComplexValue(type, re, im);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoComplexDiv(Type* type, DValue* lhs, DValue* rhs)
+{
+    lhs = DtoComplex(type, lhs);
+    rhs = DtoComplex(type, rhs);
+
+    llvm::Value *a, *b, *c, *d, *re, *im;
+
+    // lhs values
+    if (DComplexValue* cx = lhs->isComplex()) {
+        a = cx->re;
+        b = cx->im;
+    }
+    else {
+        a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp"));
+        b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp"));
+    }
+
+    // rhs values
+    if (DComplexValue* cx = rhs->isComplex()) {
+        c = cx->re;
+        d = cx->im;
+    }
+    else {
+        c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp"));
+        d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp"));
+    }
+
+    llvm::Value *tmp1, *tmp2, *denom;
+
+    tmp1 = gIR->ir->CreateMul(c, c, "tmp");
+    tmp2 = gIR->ir->CreateMul(d, d, "tmp");
+    denom = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
+
+    tmp1 = gIR->ir->CreateMul(a, c, "tmp");
+    tmp2 = gIR->ir->CreateMul(b, d, "tmp");
+    re = gIR->ir->CreateAdd(tmp1, tmp2, "tmp");
+    re = gIR->ir->CreateFDiv(re, denom, "tmp");
+
+    tmp1 = gIR->ir->CreateMul(b, c, "tmp");
+    tmp2 = gIR->ir->CreateMul(a, d, "tmp");
+    im = gIR->ir->CreateSub(tmp1, tmp2, "tmp");
+    im = gIR->ir->CreateFDiv(im, denom, "tmp");
+
+    return new DComplexValue(type, re, im);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoComplexEquals(TOK op, DValue* lhs, DValue* rhs)
+{
+    llvm::Value* lvec = lhs->getRVal();
+    llvm::Value* rvec = rhs->getRVal();
+
+    llvm::FCmpInst::Predicate cmpop;
+    switch(op)
+    {
+    case TOKequal:
+        cmpop = llvm::FCmpInst::FCMP_OEQ;
+        break;
+    case TOKnotequal:
+        cmpop = llvm::FCmpInst::FCMP_UNE;
+        break;
+    default:
+        assert(0);
+    }
+
+    llvm::Value* l1 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(0), "re");
+    llvm::Value* r1 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(0), "re");
+    llvm::Value* b1 = new llvm::FCmpInst(cmpop, l1, r1, "tmp", gIR->scopebb());
+
+    llvm::Value* l2 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(1), "im");
+    llvm::Value* r2 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(1), "im");
+    llvm::Value* b2 = new llvm::FCmpInst(cmpop, l2, r2, "tmp", gIR->scopebb());
+
+    return gIR->ir->CreateAnd(b1,b2,"tmp");
+}