Пример #1
0
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();
    }
}
Пример #2
0
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.");
  }
}