mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-25 00:53:14 +01:00
Simplify complex number handling. Fixes bug with complex substraction.
This commit is contained in:
232
gen/complex.cpp
232
gen/complex.cpp
@@ -88,12 +88,50 @@ LLValue* DtoImagPart(DValue* val)
|
||||
|
||||
DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
|
||||
{
|
||||
Type* t = val->getType()->toBasetype();
|
||||
const LLType* complexTy = DtoType(to);
|
||||
|
||||
if (t->iscomplex()) {
|
||||
return DtoCastComplex(loc, val, to);
|
||||
Type* baserety;
|
||||
Type* baseimty;
|
||||
TY ty = to->ty;
|
||||
if (ty == Tcomplex32) {
|
||||
baserety = Type::tfloat32;
|
||||
baseimty = Type::timaginary32;
|
||||
} else if (ty == Tcomplex64) {
|
||||
baserety = Type::tfloat64;
|
||||
baseimty = Type::timaginary64;
|
||||
} else if (ty == Tcomplex80) {
|
||||
baserety = Type::tfloat80;
|
||||
baseimty = Type::timaginary80;
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
LLValue *re, *im;
|
||||
DtoGetComplexParts(loc, to, val, re, im);
|
||||
|
||||
if(!re)
|
||||
re = LLConstant::getNullValue(DtoType(baserety));
|
||||
if(!im)
|
||||
im = LLConstant::getNullValue(DtoType(baseimty));
|
||||
|
||||
LLValue* res = DtoAggrPair(complexTy, re, im);
|
||||
|
||||
return new DImValue(to, res);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
|
||||
{
|
||||
DtoStore(re, DtoGEPi(c,0,0,"tmp"));
|
||||
DtoStore(im, DtoGEPi(c,0,1,"tmp"));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoGetComplexParts(Loc& loc, Type* to, DValue* val, LLValue*& re, LLValue*& im)
|
||||
{
|
||||
const LLType* base = DtoComplexBaseType(to);
|
||||
|
||||
Type* baserety;
|
||||
@@ -113,103 +151,57 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
const LLType* complexTy = DtoType(to);
|
||||
LLValue* res;
|
||||
Type* t = val->getType()->toBasetype();
|
||||
|
||||
if (t->isimaginary()) {
|
||||
res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal());
|
||||
if (t->iscomplex()) {
|
||||
DValue* v = DtoCastComplex(loc, val, to);
|
||||
if (to->iscomplex()) {
|
||||
re = gIR->ir->CreateExtractValue(v->getRVal(), 0, ".re_part");
|
||||
im = gIR->ir->CreateExtractValue(v->getRVal(), 1, ".im_part");
|
||||
} else
|
||||
DtoGetComplexParts(loc, to, v, re, im);
|
||||
}
|
||||
else if (t->isimaginary()) {
|
||||
re = NULL;
|
||||
im = DtoCastFloat(loc, val, baseimty)->getRVal();
|
||||
}
|
||||
else if (t->isfloating()) {
|
||||
res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
|
||||
re = DtoCastFloat(loc, val, baserety)->getRVal();
|
||||
im = NULL;
|
||||
}
|
||||
else if (t->isintegral()) {
|
||||
res = DtoAggrPair(complexTy, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty)));
|
||||
re = DtoCastInt(loc, val, baserety)->getRVal();
|
||||
im = NULL;
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
return new DImValue(to, res);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im)
|
||||
{
|
||||
DtoStore(re, DtoGEPi(c,0,0,"tmp"));
|
||||
DtoStore(im, DtoGEPi(c,0,1,"tmp"));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (DLRValue* lr = val->isLRValue()) {
|
||||
if (getlval)
|
||||
return lr->lvalue;
|
||||
else
|
||||
return lr->rvalue;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasRe(Type* t)
|
||||
{
|
||||
return
|
||||
(t->ty != Timaginary32 &&
|
||||
t->ty != Timaginary64 &&
|
||||
t->ty != Timaginary80);
|
||||
}
|
||||
|
||||
bool hasIm(Type* t)
|
||||
{
|
||||
return
|
||||
(t->ty == Timaginary32 ||
|
||||
t->ty == Timaginary64 ||
|
||||
t->ty == Timaginary80 ||
|
||||
t->ty == Tcomplex32 ||
|
||||
t->ty == Tcomplex64 ||
|
||||
t->ty == Tcomplex80);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoComplexAdd(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
{
|
||||
DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true));
|
||||
DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false));
|
||||
|
||||
llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im;
|
||||
|
||||
// lhs values
|
||||
DtoGetComplexParts(clhs, lhs_re, lhs_im);
|
||||
DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im);
|
||||
// rhs values
|
||||
DtoGetComplexParts(crhs, rhs_re, rhs_im);
|
||||
DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im);
|
||||
|
||||
// add up
|
||||
Type* lhstype = lhs->getType();
|
||||
Type* rhstype = rhs->getType();
|
||||
if(hasRe(lhstype) && hasRe(rhstype))
|
||||
if(lhs_re && rhs_re)
|
||||
res_re = gIR->ir->CreateAdd(lhs_re, rhs_re, "tmp");
|
||||
else if(hasRe(lhstype))
|
||||
else if(lhs_re)
|
||||
res_re = lhs_re;
|
||||
else // either hasRe(rhstype) or no re at all (then use any)
|
||||
else // either rhs_re or no re at all (then use any)
|
||||
res_re = rhs_re;
|
||||
|
||||
if(hasIm(lhstype) && hasIm(rhstype))
|
||||
if(lhs_im && rhs_im)
|
||||
res_im = gIR->ir->CreateAdd(lhs_im, rhs_im, "tmp");
|
||||
else if(hasIm(lhstype))
|
||||
else if(lhs_im)
|
||||
res_im = lhs_im;
|
||||
else // either hasIm(rhstype) or no im at all (then use any)
|
||||
else // either rhs_im or no im at all (then use any)
|
||||
res_im = rhs_im;
|
||||
|
||||
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
|
||||
@@ -220,28 +212,27 @@ DValue* DtoComplexAdd(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
|
||||
DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
{
|
||||
DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true));
|
||||
DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false));
|
||||
|
||||
llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im;
|
||||
|
||||
// lhs values
|
||||
DtoGetComplexParts(clhs, lhs_re, lhs_im);
|
||||
DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im);
|
||||
// rhs values
|
||||
DtoGetComplexParts(crhs, rhs_re, rhs_im);
|
||||
DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im);
|
||||
|
||||
// sub up
|
||||
Type* lhstype = lhs->getType();
|
||||
Type* rhstype = rhs->getType();
|
||||
if(hasRe(rhstype))
|
||||
// add up
|
||||
if(lhs_re && rhs_re)
|
||||
res_re = gIR->ir->CreateSub(lhs_re, rhs_re, "tmp");
|
||||
else
|
||||
else if(lhs_re)
|
||||
res_re = lhs_re;
|
||||
else // either rhs_re or no re at all (then use any)
|
||||
res_re = gIR->ir->CreateNeg(rhs_re, "neg");
|
||||
|
||||
if(hasIm(rhstype))
|
||||
if(lhs_im && rhs_im)
|
||||
res_im = gIR->ir->CreateSub(lhs_im, rhs_im, "tmp");
|
||||
else
|
||||
else if(lhs_im)
|
||||
res_im = lhs_im;
|
||||
else // either rhs_im or no im at all (then use any)
|
||||
res_im = gIR->ir->CreateNeg(rhs_im, "neg");
|
||||
|
||||
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
|
||||
return new DImValue(type, res);
|
||||
@@ -251,31 +242,26 @@ DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
|
||||
DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
{
|
||||
DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true));
|
||||
DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false));
|
||||
|
||||
llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im;
|
||||
|
||||
// lhs values
|
||||
DtoGetComplexParts(clhs, lhs_re, lhs_im);
|
||||
DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im);
|
||||
// rhs values
|
||||
DtoGetComplexParts(crhs, rhs_re, rhs_im);
|
||||
DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im);
|
||||
|
||||
// mul up
|
||||
llvm::Value *rere = NULL;
|
||||
llvm::Value *reim = NULL;
|
||||
llvm::Value *imre = NULL;
|
||||
llvm::Value *imim = NULL;
|
||||
Type* lhstype = lhs->getType();
|
||||
Type* rhstype = rhs->getType();
|
||||
|
||||
if(hasRe(lhstype) && hasRe(rhstype))
|
||||
if(lhs_re && rhs_re)
|
||||
rere = gIR->ir->CreateMul(lhs_re, rhs_re, "rere_mul");
|
||||
if(hasRe(lhstype) && hasIm(rhstype))
|
||||
if(lhs_re && rhs_im)
|
||||
reim = gIR->ir->CreateMul(lhs_re, rhs_im, "reim_mul");
|
||||
if(hasIm(lhstype) && hasRe(rhstype))
|
||||
if(lhs_im && rhs_re)
|
||||
imre = gIR->ir->CreateMul(lhs_im, rhs_re, "imre_mul");
|
||||
if(hasIm(lhstype) && hasIm(rhstype))
|
||||
if(lhs_im && rhs_im)
|
||||
imim = gIR->ir->CreateMul(lhs_im, rhs_im, "imim_mul");
|
||||
|
||||
if(rere && imim)
|
||||
@@ -285,7 +271,7 @@ DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
else if(imim)
|
||||
res_re = gIR->ir->CreateNeg(imim, "imim_neg");
|
||||
else
|
||||
res_re = hasRe(lhstype) ? rhs_re : lhs_re; // null!
|
||||
res_re = lhs_re ? rhs_re : lhs_re; // null!
|
||||
|
||||
if(reim && imre)
|
||||
res_im = gIR->ir->CreateAdd(reim, imre, "reim_imre_add");
|
||||
@@ -294,7 +280,7 @@ DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
else if(imre)
|
||||
res_im = imre;
|
||||
else
|
||||
res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null!
|
||||
res_im = lhs_re ? rhs_im : lhs_re; // null!
|
||||
|
||||
LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im);
|
||||
return new DImValue(type, res);
|
||||
@@ -304,37 +290,31 @@ DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
|
||||
DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
{
|
||||
DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true));
|
||||
DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false));
|
||||
|
||||
llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im;
|
||||
|
||||
// lhs values
|
||||
DtoGetComplexParts(clhs, lhs_re, lhs_im);
|
||||
DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im);
|
||||
// rhs values
|
||||
DtoGetComplexParts(crhs, rhs_re, rhs_im);
|
||||
|
||||
Type* lhstype = lhs->getType();
|
||||
Type* rhstype = rhs->getType();
|
||||
DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im);
|
||||
|
||||
// if divisor is only real, division is simple
|
||||
if(hasRe(rhstype) && !hasIm(rhstype)) {
|
||||
if(hasRe(lhstype))
|
||||
if(rhs_re && !rhs_im) {
|
||||
if(lhs_re)
|
||||
res_re = gIR->ir->CreateFDiv(lhs_re, rhs_re, "re_divby_re");
|
||||
else
|
||||
res_re = lhs_re;
|
||||
if(hasIm(lhstype))
|
||||
if(lhs_im)
|
||||
res_im = gIR->ir->CreateFDiv(lhs_im, rhs_re, "im_divby_re");
|
||||
else
|
||||
res_im = lhs_im;
|
||||
}
|
||||
// if divisor is only imaginary, division is simple too
|
||||
else if(!hasRe(rhstype) && hasIm(rhstype)) {
|
||||
if(hasRe(lhstype))
|
||||
else if(!rhs_re && rhs_im) {
|
||||
if(lhs_re)
|
||||
res_im = gIR->ir->CreateNeg(gIR->ir->CreateFDiv(lhs_re, rhs_im, "re_divby_im"), "neg");
|
||||
else
|
||||
res_im = lhs_re;
|
||||
if(hasIm(lhstype))
|
||||
if(lhs_im)
|
||||
res_re = gIR->ir->CreateFDiv(lhs_im, rhs_im, "im_divby_im");
|
||||
else
|
||||
res_re = lhs_im;
|
||||
@@ -343,7 +323,7 @@ DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
else {
|
||||
llvm::Value *tmp1, *tmp2, *denom;
|
||||
|
||||
if(hasRe(lhstype) && hasIm(lhstype)) {
|
||||
if(lhs_re && lhs_im) {
|
||||
tmp1 = gIR->ir->CreateMul(lhs_re, rhs_re, "rere");
|
||||
tmp2 = gIR->ir->CreateMul(lhs_im, rhs_im, "imim");
|
||||
res_re = gIR->ir->CreateAdd(tmp1, tmp2, "rere_plus_imim");
|
||||
@@ -352,13 +332,13 @@ DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
tmp2 = gIR->ir->CreateMul(lhs_im, rhs_re, "imre");
|
||||
res_im = gIR->ir->CreateSub(tmp2, tmp1, "imre_sub_reim");
|
||||
}
|
||||
else if(hasRe(lhstype)) {
|
||||
else if(lhs_re) {
|
||||
res_re = gIR->ir->CreateMul(lhs_re, rhs_re, "rere");
|
||||
|
||||
res_im = gIR->ir->CreateMul(lhs_re, rhs_im, "reim");
|
||||
res_im = gIR->ir->CreateNeg(res_im);
|
||||
}
|
||||
else if(hasIm(lhstype)) {
|
||||
else if(lhs_im) {
|
||||
res_re = gIR->ir->CreateMul(lhs_im, rhs_im, "imim");
|
||||
res_im = gIR->ir->CreateMul(lhs_im, rhs_re, "imre");
|
||||
}
|
||||
@@ -381,14 +361,13 @@ DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs)
|
||||
|
||||
DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val)
|
||||
{
|
||||
val = DtoComplex(loc, type, resolveLR(val, false));
|
||||
|
||||
llvm::Value *a, *b, *re, *im;
|
||||
|
||||
// values
|
||||
DtoGetComplexParts(val, a, b);
|
||||
DtoGetComplexParts(loc, type, val, a, b);
|
||||
|
||||
// sub up
|
||||
// neg up
|
||||
assert(a && b);
|
||||
re = gIR->ir->CreateNeg(a, "tmp");
|
||||
im = gIR->ir->CreateNeg(b, "tmp");
|
||||
|
||||
@@ -402,15 +381,12 @@ LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs)
|
||||
{
|
||||
Type* type = lhs->getType();
|
||||
|
||||
lhs = DtoComplex(loc, type, resolveLR(lhs, false));
|
||||
rhs = DtoComplex(loc, type, resolveLR(rhs, false));
|
||||
|
||||
llvm::Value *a, *b, *c, *d;
|
||||
llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im;
|
||||
|
||||
// lhs values
|
||||
DtoGetComplexParts(lhs, a, b);
|
||||
DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im);
|
||||
// rhs values
|
||||
DtoGetComplexParts(rhs, c, d);
|
||||
DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im);
|
||||
|
||||
// select predicate
|
||||
llvm::FCmpInst::Predicate cmpop;
|
||||
@@ -420,8 +396,8 @@ LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs)
|
||||
cmpop = llvm::FCmpInst::FCMP_UNE;
|
||||
|
||||
// (l.re==r.re && l.im==r.im) or (l.re!=r.re || l.im!=r.im)
|
||||
LLValue* b1 = new llvm::FCmpInst(cmpop, a, c, "tmp", gIR->scopebb());
|
||||
LLValue* b2 = new llvm::FCmpInst(cmpop, b, d, "tmp", gIR->scopebb());
|
||||
LLValue* b1 = new llvm::FCmpInst(cmpop, lhs_re, rhs_re, "tmp", gIR->scopebb());
|
||||
LLValue* b2 = new llvm::FCmpInst(cmpop, lhs_im, rhs_im, "tmp", gIR->scopebb());
|
||||
|
||||
if (op == TOKequal)
|
||||
return gIR->ir->CreateAnd(b1,b2,"tmp");
|
||||
@@ -440,7 +416,7 @@ DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
|
||||
return val;
|
||||
|
||||
llvm::Value *re, *im;
|
||||
DtoGetComplexParts(val, re, im);
|
||||
DtoGetComplexParts(loc, val->getType(), val, re, im);
|
||||
const LLType* toty = DtoComplexBaseType(to);
|
||||
|
||||
if (to->size() < vty->size()) {
|
||||
|
||||
Reference in New Issue
Block a user