DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to) { Type* to = _to->toBasetype(); Type* vty = val->getType()->toBasetype(); if (to->iscomplex()) { if (vty->size() == to->size()) return val; llvm::Value *re, *im; DtoGetComplexParts(loc, val->getType(), val, re, im); LLType* toty = DtoComplexBaseType(to); if (to->size() < vty->size()) { re = gIR->ir->CreateFPTrunc(re, toty, "tmp"); im = gIR->ir->CreateFPTrunc(im, toty, "tmp"); } else { re = gIR->ir->CreateFPExt(re, toty, "tmp"); im = gIR->ir->CreateFPExt(im, toty, "tmp"); } LLValue* pair = DtoAggrPair(DtoType(_to), re, im); return new DImValue(_to, pair); } else if (to->isimaginary()) { // FIXME: this loads both values, even when we only need one LLValue* v = val->getRVal(); LLValue* impart = gIR->ir->CreateExtractValue(v, 1, ".im_part"); Type *extractty; switch (vty->ty) { default: llvm_unreachable("Unexpected complex floating point type"); case Tcomplex32: extractty = Type::timaginary32; break; case Tcomplex64: extractty = Type::timaginary64; break; case Tcomplex80: extractty = Type::timaginary80; break; } DImValue* im = new DImValue(extractty, impart); return DtoCastFloat(loc, im, to); } else if (to->ty == Tbool) { return new DImValue(_to, DtoComplexEquals(loc, TOKnotequal, val, DtoNullValue(vty))); } else if (to->isfloating() || to->isintegral()) { // FIXME: this loads both values, even when we only need one LLValue* v = val->getRVal(); LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part"); Type *extractty; switch (vty->ty) { default: llvm_unreachable("Unexpected complex floating point type"); case Tcomplex32: extractty = Type::tfloat32; break; case Tcomplex64: extractty = Type::tfloat64; break; case Tcomplex80: extractty = Type::tfloat80; break; } DImValue* re = new DImValue(extractty, repart); return DtoCastFloat(loc, re, to); } else { error(loc, "Don't know how to cast %s to %s", vty->toChars(), to->toChars()); fatal(); } }
void DtoGetComplexParts(Loc &loc, Type *to, DValue *val, DValue *&re, DValue *&im) { Type *baserety; Type *baseimty; switch (to->toBasetype()->ty) { default: llvm_unreachable("Unexpected complex floating point type"); case Tcomplex32: baserety = Type::tfloat32; baseimty = Type::timaginary32; break; case Tcomplex64: baserety = Type::tfloat64; baseimty = Type::timaginary64; break; case Tcomplex80: baserety = Type::tfloat80; baseimty = Type::timaginary80; break; } Type *t = val->getType()->toBasetype(); if (t->iscomplex()) { DValue *v = DtoCastComplex(loc, val, to); if (to->iscomplex()) { if (v->isLVal()) { LLValue *reVal = DtoGEPi(v->getLVal(), 0, 0, ".re_part"); LLValue *imVal = DtoGEPi(v->getLVal(), 0, 1, ".im_part"); re = new DVarValue(baserety, reVal); im = new DVarValue(baseimty, imVal); } else { LLValue *reVal = gIR->ir->CreateExtractValue(v->getRVal(), 0, ".re_part"); LLValue *imVal = gIR->ir->CreateExtractValue(v->getRVal(), 1, ".im_part"); re = new DImValue(baserety, reVal); im = new DImValue(baseimty, imVal); } } else { DtoGetComplexParts(loc, to, v, re, im); } } else if (t->isimaginary()) { re = nullptr; im = DtoCastFloat(loc, val, baseimty); } else if (t->isfloating()) { re = DtoCastFloat(loc, val, baserety); im = nullptr; } else if (t->isintegral()) { re = DtoCastInt(loc, val, baserety); im = nullptr; } else { llvm_unreachable("Unexpected numeric type."); } }