# HG changeset patch # User lindquist # Date 1195437538 -3600 # Node ID 4d1e9eb001e0d344a6182203728bca9271a639b5 # Parent 855adfdb8d38c4667d8abde5897d8393cba6bc11 [svn r108] Now basic suppport for complex types. =,+,-,*,/ are supported. diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/binops.cpp --- a/gen/binops.cpp Sun Nov 18 08:25:07 2007 +0100 +++ b/gen/binops.cpp Mon Nov 19 02:58:58 2007 +0100 @@ -3,26 +3,35 @@ #include "declaration.h" #include "gen/irstate.h" +#include "gen/tollvm.h" #include "gen/dvalue.h" +////////////////////////////////////////////////////////////////////////////// + DValue* DtoBinAdd(DValue* lhs, DValue* rhs) { llvm::Value* v = gIR->ir->CreateAdd(lhs->getRVal(), rhs->getRVal(), "tmp"); return new DImValue( lhs->getType(), v ); } +////////////////////////////////////////////////////////////////////////////// + DValue* DtoBinSub(DValue* lhs, DValue* rhs) { llvm::Value* v = gIR->ir->CreateSub(lhs->getRVal(), rhs->getRVal(), "tmp"); return new DImValue( lhs->getType(), v ); } +////////////////////////////////////////////////////////////////////////////// + DValue* DtoBinMul(DValue* lhs, DValue* rhs) { llvm::Value* v = gIR->ir->CreateMul(lhs->getRVal(), rhs->getRVal(), "tmp"); return new DImValue( lhs->getType(), v ); } +////////////////////////////////////////////////////////////////////////////// + DValue* DtoBinDiv(DValue* lhs, DValue* rhs) { Type* t = lhs->getType(); @@ -39,6 +48,8 @@ return new DImValue( lhs->getType(), res ); } +////////////////////////////////////////////////////////////////////////////// + DValue* DtoBinRem(DValue* lhs, DValue* rhs) { Type* t = lhs->getType(); diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/complex.cpp --- /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 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 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 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 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"); +} diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/complex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/complex.h Mon Nov 19 02:58:58 2007 +0100 @@ -0,0 +1,27 @@ +#ifndef LLVMDC_GEN_COMPLEX_H +#define LLVMDC_GEN_COMPLEX_H + +const llvm::StructType* DtoComplexType(Type* t); +const llvm::Type* DtoComplexBaseType(Type* t); + +llvm::Constant* DtoConstComplex(Type* t, llvm::Constant* re, llvm::Constant* im); +llvm::Constant* DtoConstComplex(Type* t, long double re, long double im); +llvm::Constant* DtoUndefComplex(Type* _ty); + +llvm::Constant* DtoComplexShuffleMask(unsigned a, unsigned b); + +llvm::Value* DtoRealPart(DValue* val); +llvm::Value* DtoImagPart(DValue* val); +DValue* DtoComplex(Type* to, DValue* val); + +void DtoComplexAssign(llvm::Value* l, llvm::Value* r); +void DtoComplexSet(llvm::Value* c, llvm::Value* re, llvm::Value* im); + +DValue* DtoComplexAdd(Type* type, DValue* lhs, DValue* rhs); +DValue* DtoComplexSub(Type* type, DValue* lhs, DValue* rhs); +DValue* DtoComplexMul(Type* type, DValue* lhs, DValue* rhs); +DValue* DtoComplexDiv(Type* type, DValue* lhs, DValue* rhs); + +llvm::Value* DtoComplexEquals(TOK op, DValue* lhs, DValue* rhs); + +#endif // LLVMDC_GEN_COMPLEX_H diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/dvalue.h --- a/gen/dvalue.h Sun Nov 18 08:25:07 2007 +0100 +++ b/gen/dvalue.h Mon Nov 19 02:58:58 2007 +0100 @@ -32,6 +32,7 @@ struct DSliceValue; struct DArrayLenValue; struct DLValueCast; +struct DComplexValue; // base class for d-values struct DValue : Object @@ -51,6 +52,7 @@ virtual DFuncValue* isFunc() { return NULL; } virtual DArrayLenValue* isArrayLen() { return NULL; } virtual DLValueCast* isLValueCast() { return NULL; } + virtual DComplexValue* isComplex() { return NULL; }; virtual bool inPlace() { return false; } @@ -190,4 +192,21 @@ virtual DLValueCast* isLValueCast() { return this; } }; +// complex number immediate d-value (much like slice) +struct DComplexValue : DValue +{ + Type* type; + llvm::Value* re; + llvm::Value* im; + + DComplexValue(Type* t, llvm::Value* r, llvm::Value* i) { + type = t; + re = r; + im = i; + } + + virtual Type* getType() { assert(type); return type; } + virtual DComplexValue* isComplex() { return this; } +}; + #endif // LLVMDC_GEN_DVALUE_H diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/toir.cpp --- a/gen/toir.cpp Sun Nov 18 08:25:07 2007 +0100 +++ b/gen/toir.cpp Mon Nov 19 02:58:58 2007 +0100 @@ -28,7 +28,7 @@ #include "gen/structs.h" #include "gen/classes.h" #include "gen/typeinf.h" - +#include "gen/complex.h" #include "gen/dvalue.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -291,13 +291,7 @@ Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; Type* t = DtoDType(type); - const llvm::Type* fty = DtoType(t); - if (t->ty == Tfloat32 || t->ty == Timaginary32) - return llvm::ConstantFP::get(fty,float(value)); - else if (t->ty == Tfloat64 || t->ty == Timaginary64 || t->ty == Tfloat80 || t->ty == Timaginary80) - return llvm::ConstantFP::get(fty,double(value)); - assert(0); - return NULL; + return DtoConstFP(t, value); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -334,7 +328,18 @@ { Logger::print("ComplexExp::toElem(): %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - assert(0 && "no complex yet"); + llvm::Constant* c = toConstElem(p); + + if (c->isNullValue()) { + Type* t = DtoDType(type); + if (t->ty == Tcomplex32) + c = DtoConstFP(Type::tfloat32, 0); + else + c = DtoConstFP(Type::tfloat64, 0); + return new DComplexValue(type, c, c); + } + + return new DComplexValue(type, c->getOperand(0), c->getOperand(1)); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -343,7 +348,7 @@ { Logger::print("ComplexExp::toConstElem(): %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - assert(0 && "no complex yet"); + return DtoConstComplex(type, value.re, value.im); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -484,164 +489,6 @@ } return l; - - /* - if (l->type == DValue::ARRAYLEN) - { - DtoResizeDynArray(l->mem, r->getValue()); - delete r; - delete l; - return 0; - } - - Type* e1type = DtoDType(e1->type); - Type* e2type = DtoDType(e2->type); - TY e1ty = e1type->ty; - TY e2ty = e2type->ty; - - DValue* e = new DValue(this); - e->type = DValue::VAR; - - // struct - if (e1ty == Tstruct) { - e->mem = l->mem; - // struct + struct - if (e2ty == Tstruct) { - // struct literals do the assignment themselvs (in place) - if (!r->inplace) { - DtoStructCopy(l->mem,r->getValue()); - } - else { - e->inplace = true; - } - } - // struct + const int - else if (e2type->isintegral()){ - IntegerExp* iexp = (IntegerExp*)e2; - assert(iexp->value == 0 && "Only integral struct initializer allowed is zero"); - DtoStructZeroInit(l->mem); - } - // :x - else - assert(0 && "struct = unknown"); - } - else if (e1ty == Tsarray) { - assert(0 && "static array not supported"); - } - else if (e1ty == Tarray) { - if (e2type->isscalar() || e2type->ty == Tclass){ - if (l->type == DValue::SLICE) { - DtoArrayInit(l->mem, l->arg, r->getValue()); - } - else { - DtoArrayInit(l->mem, r->getValue()); - } - } - else if (e2ty == Tarray) { - //new llvm::StoreInst(r->val,l->val,p->scopebb()); - if (r->type == DValue::NUL) { - llvm::Constant* c = llvm::cast(r->val); - assert(c->isNullValue()); - DtoNullArray(l->mem); - e->mem = l->mem; - } - else if (r->type == DValue::SLICE) { - if (l->type == DValue::SLICE) { - DtoArrayCopy(l,r); - e->type = DValue::SLICE; - e->mem = l->mem; - e->arg = l->arg; - } - else { - DtoSetArray(l->mem,r->arg,r->mem); - e->mem = l->mem; - } - } - else { - // new expressions write directly to the array reference - // so do string literals - e->mem = l->mem; - if (!r->inplace) { - assert(r->mem); - DtoArrayAssign(l->mem, r->mem); - } - else { - e->inplace = true; - } - } - } - else - assert(0); - } - else if (e1ty == Tpointer) { - e->mem = l->mem; - if (e2ty == Tpointer) { - llvm::Value* v = r->field ? r->mem : r->getValue(); - Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n'; - new llvm::StoreInst(v, l->mem, p->scopebb()); - } - else - assert(0); - } - else if (e1ty == Tclass) { - if (e2ty == Tclass) { - llvm::Value* tmp = r->getValue(); - Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n'; - // assignment to this in constructor special case - if (l->isthis) { - FuncDeclaration* fdecl = p->func().decl; - // respecify the this param - if (!llvm::isa(fdecl->llvmThisVar)) - fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint()); - new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb()); - e->mem = fdecl->llvmThisVar; - } - // regular class ref -> class ref assignment - else { - new llvm::StoreInst(tmp, l->mem, p->scopebb()); - e->mem = l->mem; - } - } - else - assert(0); - } - else if (e1ty == Tdelegate) { - Logger::println("Assigning to delegate"); - if (e2ty == Tdelegate) { - if (r->type == DValue::NUL) { - llvm::Constant* c = llvm::cast(r->val); - if (c->isNullValue()) { - DtoNullDelegate(l->mem); - e->mem = l->mem; - } - else - assert(0); - } - else if (r->inplace) { - // do nothing - e->inplace = true; - e->mem = l->mem; - } - else { - DtoDelegateCopy(l->mem, r->getValue()); - e->mem = l->mem; - } - } - else - assert(0); - } - // !struct && !array && !pointer && !class - else { - Logger::cout() << *l->mem << '\n'; - new llvm::StoreInst(r->getValue(),l->mem,p->scopebb()); - e->mem = l->mem; - } - - delete r; - delete l; - - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// @@ -682,8 +529,14 @@ llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb()); return new DImValue(type, v); } + else if (t->iscomplex()) { + return DtoComplexAdd(type, l, r); + } assert(0); } + else if (t->iscomplex()) { + return DtoComplexAdd(type, l, r); + } else { return DtoBinAdd(l,r); } @@ -701,39 +554,22 @@ DValue* r = e2->toElem(p); p->exps.pop_back(); + Type* t = DtoDType(type); + DValue* res; if (DtoDType(e1->type)->ty == Tpointer) { llvm::Value* gep = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb()); res = new DImValue(type, gep); } + else if (t->iscomplex()) { + res = DtoComplexAdd(type, l, r); + } else { res = DtoBinAdd(l,r); } DtoAssign(l, res); return l; - - /* - - Type* e1type = DtoDType(e1->type); - - DValue* e = new DValue(this); - llvm::Value* val = 0; - if (e1type->ty == Tpointer) { - val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb()); - } - else { - val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb()); - } - - assert(l->mem); - new llvm::StoreInst(val,l->mem,p->scopebb()); - e->type = DValue::VAR; - - delete l; - delete r; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// @@ -746,6 +582,8 @@ DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); + Type* t = DtoDType(type); + if (DtoDType(e1->type)->ty == Tpointer) { llvm::Value* lv = l->getRVal(); llvm::Value* rv = r->getRVal(); @@ -759,34 +597,12 @@ diff = p->ir->CreateIntToPtr(diff, DtoType(type)); return new DImValue(type, diff); } + else if (t->iscomplex()) { + return DtoComplexSub(type, l, r); + } else { return DtoBinSub(l,r); } - - /* - llvm::Value* left = l->getValue(); - if (isaPointer(left->getType())) - left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb()); - - llvm::Value* right = r->getValue(); - if (isaPointer(right->getType())) - right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb()); - - e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb()); - e->type = DValue::VAL; - - const llvm::Type* totype = DtoType(type); - if (e->val->getType() != totype) { - assert(0); - assert(isaPointer(e->val->getType())); - assert(llvm::isa(totype)); - e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb()); - } - - delete l; - delete r; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// @@ -799,6 +615,8 @@ DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); + Type* t = DtoDType(type); + DValue* res; if (DtoDType(e1->type)->ty == Tpointer) { llvm::Value* tmp = r->getRVal(); @@ -807,212 +625,113 @@ tmp = new llvm::GetElementPtrInst(l->getRVal(),tmp,"tmp",p->scopebb()); res = new DImValue(type, tmp); } + else if (t->iscomplex()) { + res = DtoComplexSub(type, l, r); + } else { res = DtoBinSub(l,r); } DtoAssign(l, res); return l; - - /* - - Type* e1type = DtoDType(e1->type); - - llvm::Value* tmp = 0; - if (e1type->ty == Tpointer) { - tmp = r->getValue(); - llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false); - tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb()); - tmp = new llvm::GetElementPtrInst(l->getValue(),tmp,"tmp",p->scopebb()); - } - else { - tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb()); - } - - assert(l->mem); - new llvm::StoreInst(tmp, l->mem, p->scopebb()); - - delete l; - delete r; - - DValue* e = new DValue(this); - e->val = tmp; - e->type = DValue::VAR; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* MulExp::toElem(IRState* p) { - Logger::print("MulExp::toElem: %s\n", toChars()); + Logger::print("MulExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); - return DtoBinMul(l,r); - /* - if (l->dvalue && r->dvalue) { - Logger::println("DVALUE PATH"); - e->dvalue = DtoBinMul(l->dvalue, r->dvalue); - e->val = e->dvalue->getRVal(); + if (type->iscomplex()) { + return DtoComplexMul(type, l, r); } - else { - llvm::Value* vl = l->getValue(); - llvm::Value* vr = r->getValue(); - Logger::cout() << "mul: " << *vl << ", " << *vr << '\n'; - e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb()); - e->dvalue = new DImValue(type, e->val); - } - e->type = DValue::VAL; - delete l; - delete r; - return e; - */ + + return DtoBinMul(l,r); } ////////////////////////////////////////////////////////////////////////////////////////// DValue* MulAssignExp::toElem(IRState* p) { - Logger::print("MulAssignExp::toElem: %s\n", toChars()); + Logger::print("MulAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); - DValue* res = DtoBinMul(l,r); + DValue* res; + if (type->iscomplex()) { + res = DtoComplexMul(type, l, r); + } + else { + res = DtoBinMul(l,r); + } DtoAssign(l, res); return l; - - /* - llvm::Value* vl = l->getValue(); - llvm::Value* vr = r->getValue(); - Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n'; - llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb()); - - assert(l->mem); - new llvm::StoreInst(tmp,l->mem,p->scopebb()); - - delete l; - delete r; - - DValue* e = new DValue(this); - e->val = tmp; - e->type = DValue::VAR; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* DivExp::toElem(IRState* p) { - Logger::print("DivExp::toElem: %s\n", toChars()); + Logger::print("DivExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); + if (type->iscomplex()) { + return DtoComplexDiv(type, l, r); + } + return DtoBinDiv(l, r); - /* - - Type* t = DtoDType(type); - - if (t->isunsigned()) - e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isintegral()) - e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isfloating()) - e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else - assert(0); - e->type = DValue::VAL; - delete l; - delete r; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* DivAssignExp::toElem(IRState* p) { - Logger::print("DivAssignExp::toElem: %s\n", toChars()); + Logger::print("DivAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); - DValue* res = DtoBinDiv(l,r); + DValue* res; + if (type->iscomplex()) { + res = DtoComplexDiv(type, l, r); + } + else { + res = DtoBinDiv(l,r); + } DtoAssign(l, res); return l; - - /* - - Type* t = DtoDType(type); - - llvm::Value* tmp; - if (t->isunsigned()) - tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isintegral()) - tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isfloating()) - tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else - assert(0); - - assert(l->mem); - new llvm::StoreInst(tmp,l->mem,p->scopebb()); - - delete l; - delete r; - - DValue* e = new DValue(this); - e->val = tmp; - e->type = DValue::VAR; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* ModExp::toElem(IRState* p) { - Logger::print("ModExp::toElem: %s\n", toChars()); + Logger::print("ModExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); DValue* r = e2->toElem(p); return DtoBinRem(l, r); - /* - Type* t = DtoDType(type); - - if (t->isunsigned()) - e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isintegral()) - e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isfloating()) - e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else - assert(0); - e->type = DValue::VAL; - delete l; - delete r; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* ModAssignExp::toElem(IRState* p) { - Logger::print("ModAssignExp::toElem: %s\n", toChars()); + Logger::print("ModAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* l = e1->toElem(p); @@ -1022,39 +741,13 @@ DtoAssign(l, res); return l; - - /* - - Type* t = DtoDType(type); - - llvm::Value* tmp; - if (t->isunsigned()) - tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isintegral()) - tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (t->isfloating()) - tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else - assert(0); - - assert(l->mem); - new llvm::StoreInst(tmp,l->mem,p->scopebb()); - - delete l; - delete r; - - DValue* e = new DValue(this); - e->val = tmp; - e->type = DValue::VAR; - return e; - */ } ////////////////////////////////////////////////////////////////////////////////////////// DValue* CallExp::toElem(IRState* p) { - Logger::print("CallExp::toElem: %s\n", toChars()); + Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; DValue* fn = e1->toElem(p); @@ -1880,6 +1573,11 @@ } eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } + else if (t->iscomplex()) + { + Logger::println("complex"); + eval = DtoComplexEquals(op, l, r); + } else if (t->isfloating()) { Logger::println("floating"); @@ -2439,9 +2137,9 @@ if (t->isintegral()) zero = llvm::ConstantInt::get(val->getType(), 0, true); else if (t->isfloating()) { - if (t->ty == Tfloat32) + if (t->ty == Tfloat32 || t->ty == Timaginary32) zero = llvm::ConstantFP::get(val->getType(), float(0)); - else if (t->ty == Tfloat64 || t->ty == Tfloat80) + else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80) zero = llvm::ConstantFP::get(val->getType(), double(0)); else assert(0); diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/tollvm.cpp --- a/gen/tollvm.cpp Sun Nov 18 08:25:07 2007 +0100 +++ b/gen/tollvm.cpp Mon Nov 19 02:58:58 2007 +0100 @@ -18,11 +18,13 @@ #include "gen/structs.h" #include "gen/classes.h" #include "gen/typeinf.h" +#include "gen/complex.h" bool DtoIsPassedByRef(Type* type) { - TY t = DtoDType(type)->ty; - return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray); + Type* typ = DtoDType(type); + TY t = typ->ty; + return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex()); } Type* DtoDType(Type* t) @@ -72,10 +74,9 @@ // complex case Tcomplex32: - return DtoComplexType(llvm::Type::FloatTy); case Tcomplex64: case Tcomplex80: - return DtoComplexType(llvm::Type::DoubleTy); + return DtoComplexType(t); // pointers case Tpointer: { @@ -196,16 +197,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// -const llvm::StructType* DtoComplexType(const llvm::Type* base) -{ - std::vector types; - types.push_back(base); - types.push_back(base); - return llvm::StructType::get(types); -} - -////////////////////////////////////////////////////////////////////////////////////////// - static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false) { assert(bits == 32 || bits == 64); @@ -902,6 +893,15 @@ DtoStore(rhs->getRVal(), lhs->getLVal()); } } + else if (t->iscomplex()) { + assert(!lhs->isComplex()); + if (DComplexValue* cx = rhs->isComplex()) { + DtoComplexSet(lhs->getRVal(), cx->re, cx->im); + } + else { + DtoComplexAssign(lhs->getRVal(), rhs->getRVal()); + } + } else { llvm::Value* r = rhs->getRVal(); llvm::Value* l = lhs->getLVal(); @@ -990,6 +990,9 @@ DValue* DtoCastFloat(DValue* val, Type* to) { + if (val->getType() == to) + return val; + const llvm::Type* tolltype = DtoType(to); Type* totype = DtoDType(to); @@ -1001,7 +1004,11 @@ llvm::Value* rval; - if (totype->isfloating()) { + if (totype->iscomplex()) { + assert(0); + //return new DImValue(to, DtoComplex(to, val)); + } + else if (totype->isfloating()) { if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) { rval = val->getRVal(); } @@ -1030,6 +1037,25 @@ return new DImValue(to, rval); } +DValue* DtoCastComplex(DValue* val, Type* _to) +{ + Type* to = DtoDType(_to); + llvm::Value* v = val->getRVal(); + if (to->iscomplex()) { + assert(0); + } + else if (to->isimaginary()) { + DImValue* im = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(1), "im")); + return DtoCastFloat(im, to); + } + else if (to->isfloating()) { + DImValue* re = new DImValue(to, gIR->ir->CreateExtractElement(v, DtoConstUint(0), "re")); + return DtoCastFloat(re, to); + } + else + assert(0); +} + DValue* DtoCastClass(DValue* val, Type* _to) { const llvm::Type* tolltype = DtoType(_to); @@ -1045,6 +1071,9 @@ if (fromtype->isintegral()) { return DtoCastInt(val, to); } + else if (fromtype->iscomplex()) { + return DtoCastComplex(val, to); + } else if (fromtype->isfloating()) { return DtoCastFloat(val, to); } @@ -1081,6 +1110,16 @@ return llvm::ConstantInt::get(llvm::Type::Int1Ty, b, false); } +llvm::ConstantFP* DtoConstFP(Type* t, long double value) +{ + TY ty = DtoDType(t)->ty; + if (ty == Tfloat32 || ty == Timaginary32) + return llvm::ConstantFP::get(llvm::Type::FloatTy, float(value)); + else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80) + return llvm::ConstantFP::get(llvm::Type::DoubleTy, double(value)); +} + + ////////////////////////////////////////////////////////////////////////////////////////// llvm::Constant* DtoConstString(const char* str) @@ -1165,6 +1204,8 @@ return false; } +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t) { if (v->getType() == t) @@ -1172,6 +1213,8 @@ return gIR->ir->CreateBitCast(v, t, "tmp"); } +////////////////////////////////////////////////////////////////////////////////////////// + const llvm::PointerType* isaPointer(llvm::Value* v) { return llvm::dyn_cast(v->getType()); diff -r 855adfdb8d38 -r 4d1e9eb001e0 gen/tollvm.h --- a/gen/tollvm.h Sun Nov 18 08:25:07 2007 +0100 +++ b/gen/tollvm.h Mon Nov 19 02:58:58 2007 +0100 @@ -22,8 +22,6 @@ const llvm::Type* DtoSize_t(); -const llvm::StructType* DtoComplexType(const llvm::Type* base); - llvm::Constant* DtoConstInitializer(Type* type, Initializer* init); llvm::Constant* DtoConstFieldInitializer(Type* type, Initializer* init); DValue* DtoInitializer(Initializer* init); @@ -50,6 +48,8 @@ llvm::ConstantInt* DtoConstSize_t(size_t); llvm::ConstantInt* DtoConstUint(unsigned i); llvm::ConstantInt* DtoConstInt(int i); +llvm::ConstantFP* DtoConstFP(Type* t, long double value); + llvm::Constant* DtoConstString(const char*); llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0); llvm::Constant* DtoConstBool(bool); @@ -98,6 +98,7 @@ DValue* DtoCastInt(DValue* val, Type* to); DValue* DtoCastPtr(DValue* val, Type* to); DValue* DtoCastFloat(DValue* val, Type* to); +DValue* DtoCastComplex(DValue* val, Type* to); DValue* DtoCastClass(DValue* val, Type* to); DValue* DtoCast(DValue* val, Type* to); diff -r 855adfdb8d38 -r 4d1e9eb001e0 llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Sun Nov 18 08:25:07 2007 +0100 +++ b/llvmdc.kdevelop.filelist Mon Nov 19 02:58:58 2007 +0100 @@ -105,6 +105,8 @@ gen/binops.cpp gen/classes.cpp gen/classes.h +gen/complex.cpp +gen/complex.h gen/dvalue.cpp gen/dvalue.h gen/dwarftypes.cpp @@ -142,6 +144,7 @@ lphobos/internal/aApplyR.d lphobos/internal/adi.d lphobos/internal/arrays.d +lphobos/internal/cmath2.d lphobos/internal/contract.d lphobos/internal/mem.d lphobos/internal/moduleinit.d @@ -317,6 +320,8 @@ test/classinfo2.d test/comma.d test/complex1.d +test/complex2.d +test/complex3.d test/cond.d test/cond1.d test/condexp.d diff -r 855adfdb8d38 -r 4d1e9eb001e0 test/complex1.d --- a/test/complex1.d Sun Nov 18 08:25:07 2007 +0100 +++ b/test/complex1.d Mon Nov 19 02:58:58 2007 +0100 @@ -2,5 +2,20 @@ void main() { - cfloat c1; + cfloat cf1 = 3f + 0i; + cfloat cf2 = 4f + 1i; + cfloat cf3 = func(); + auto c1 = cf1 + cf2; + auto c2 = cf2 - cf3; + { + auto c3 = cf1 * cf3; + { + auto c4 = cf2 / cf3; + } + } } + +cfloat func() +{ + return 3f + 1i; +} diff -r 855adfdb8d38 -r 4d1e9eb001e0 test/complex2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/complex2.d Mon Nov 19 02:58:58 2007 +0100 @@ -0,0 +1,14 @@ +module complex2; + +void main() +{ + cdouble c = 3.0 + 0i; + cdouble d = 2.0 + 0i; + { + cdouble c1 = c + 3.0; + cdouble c2 = c - 3.0i; + } + { + cdouble c1 = c / 2.0; + } +} diff -r 855adfdb8d38 -r 4d1e9eb001e0 test/complex3.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/complex3.d Mon Nov 19 02:58:58 2007 +0100 @@ -0,0 +1,9 @@ +module complex3; + +void main() +{ + cfloat c1 = 1f + 0i; + cfloat c2 = 0f + 0i; + //c2 += 1f + 0i; + //assert(c1 == c2); +}