Example #1
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->type->toBasetype();

  if (t->iscomplex()) {
    DValue *v = DtoCastComplex(loc, val, to);
    if (to->iscomplex()) {
      if (v->isLVal()) {
        LLValue *reVal =
            DtoGEPi(DtoLVal(v), 0, 0, ".re_part");
        LLValue *imVal =
            DtoGEPi(DtoLVal(v), 0, 1, ".im_part");
        re = new DLValue(baserety, reVal);
        im = new DLValue(baseimty, imVal);
      } else {
        LLValue *reVal =
            gIR->ir->CreateExtractValue(DtoRVal(v), 0, ".re_part");
        LLValue *imVal =
            gIR->ir->CreateExtractValue(DtoRVal(v), 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.");
  }
}
Example #2
0
 void vaCopy(DLValue *dest, DValue *src) override {
   // Analog to va_start, we first need to allocate a new __va_list struct on
   // the stack and set `dest` to its address.
   LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
   DtoStore(valistmem,
            DtoBitCast(DtoLVal(dest), getPtrToType(valistmem->getType())));
   // Then fill the new struct with a bitcopy of the source struct.
   // `src` is a char* pointer to the source struct.
   DtoMemCpy(valistmem, DtoRVal(src));
 }
Example #3
0
 LLValue *prepareVaStart(DLValue *ap) override {
   // Since the user only created a char* pointer (ap) on the stack before
   // invoking va_start, we first need to allocate the actual __va_list struct
   // and set `ap` to its address.
   LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
   DtoStore(valistmem,
            DtoBitCast(DtoLVal(ap), getPtrToType(valistmem->getType())));
   // Pass a i8* pointer to the actual struct to LLVM's va_start intrinsic.
   return DtoBitCast(valistmem, getVoidPtrType());
 }
Example #4
0
LLValue *DtoCallableValue(DValue *fn) {
  Type *type = fn->type->toBasetype();
  if (type->ty == Tfunction) {
    return DtoRVal(fn);
  }
  if (type->ty == Tdelegate) {
    if (fn->isLVal()) {
      LLValue *dg = DtoLVal(fn);
      LLValue *funcptr = DtoGEPi(dg, 0, 1);
      return DtoLoad(funcptr, ".funcptr");
    }
    LLValue *dg = DtoRVal(fn);
    assert(isaStruct(dg));
    return gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
  }

  llvm_unreachable("Not a callable type.");
}
Example #5
0
DLValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key,
                    bool lvalue) {
  // D2:
  // call:
  // extern(C) void* _aaGetY(AA* aa, TypeInfo aati, size_t valuesize, void*
  // pkey)
  // or
  // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey)

  // first get the runtime function
  llvm::Function *func =
      getRuntimeFunction(loc, gIR->module, lvalue ? "_aaGetY" : "_aaInX");
  LLFunctionType *funcTy = func->getFunctionType();

  // aa param
  LLValue *aaval = lvalue ? DtoLVal(aa) : DtoRVal(aa);
  aaval = DtoBitCast(aaval, funcTy->getParamType(0));

  // pkey param
  LLValue *pkey = makeLValue(loc, key);
  pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2));

  // call runtime
  LLValue *ret;
  if (lvalue) {
    LLValue *rawAATI =
        DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false);
    LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1));
    LLValue *valsize = DtoConstSize_t(getTypeAllocSize(DtoType(type)));
    ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey,
                                  "aa.index")
              .getInstruction();
  } else {
    LLValue *keyti = DtoBitCast(to_keyti(aa), funcTy->getParamType(1));
    ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index")
              .getInstruction();
  }

  // cast return value
  LLType *targettype = DtoPtrToType(type);
  if (ret->getType() != targettype) {
    ret = DtoBitCast(ret, targettype);
  }

  // Only check bounds for rvalues ('aa[key]').
  // Lvalue use ('aa[key] = value') auto-adds an element.
  if (!lvalue && gIR->emitArrayBoundsChecks()) {
    llvm::BasicBlock *okbb = gIR->insertBB("aaboundsok");
    llvm::BasicBlock *failbb = gIR->insertBBAfter(okbb, "aaboundscheckfail");

    LLValue *nullaa = LLConstant::getNullValue(ret->getType());
    LLValue *cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck");
    gIR->ir->CreateCondBr(cond, okbb, failbb);

    // set up failbb to call the array bounds error runtime function

    gIR->scope() = IRScope(failbb);

    llvm::Function *errorfn =
        getRuntimeFunction(loc, gIR->module, "_d_arraybounds");
    gIR->CreateCallOrInvoke(
        errorfn, DtoModuleFileName(gIR->func()->decl->getModule(), loc),
        DtoConstUint(loc.linnum));

    // the function does not return
    gIR->ir->CreateUnreachable();

    // if ok, proceed in okbb
    gIR->scope() = IRScope(okbb);
  }
  return new DLValue(type, ret);
}