Mercurial > projects > ldc
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"); +}