Exemplo n.º 1
0
void DtoMemSet(LLValue* dst, LLValue* val, LLValue* nbytes)
{
    dst = DtoBitCast(dst,getVoidPtrType());

    LLType* intTy = DtoSize_t();
    LLType *VoidPtrTy = getVoidPtrType();
    LLType *Tys[2] ={VoidPtrTy, intTy};
    llvm::Function* fn = llvm::Intrinsic::getDeclaration(gIR->module,
                llvm::Intrinsic::memset, llvm::makeArrayRef(Tys, 2));

    gIR->ir->CreateCall5(fn, dst, val, nbytes, DtoConstUint(1), DtoConstBool(false), "");
}
Exemplo n.º 2
0
void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes, unsigned align)
{
    dst = DtoBitCast(dst,getVoidPtrType());
    src = DtoBitCast(src,getVoidPtrType());

    LLType* intTy = DtoSize_t();
    LLType *VoidPtrTy = getVoidPtrType();
    LLType *Tys[3] ={VoidPtrTy, VoidPtrTy, intTy};
    llvm::Function* fn = llvm::Intrinsic::getDeclaration(gIR->module,
        llvm::Intrinsic::memcpy, llvm::makeArrayRef(Tys, 3));

    gIR->ir->CreateCall5(fn, dst, src, nbytes, DtoConstUint(align), DtoConstBool(false), "");
}
Exemplo n.º 3
0
LLValue *DtoMemCmp(LLValue *lhs, LLValue *rhs, LLValue *nbytes) {
  // int memcmp ( const void * ptr1, const void * ptr2, size_t num );

  LLType *VoidPtrTy = getVoidPtrType();
  LLFunction *fn = gIR->module.getFunction("memcmp");
  if (!fn) {
    LLType *Tys[] = {VoidPtrTy, VoidPtrTy, DtoSize_t()};
    LLFunctionType *fty =
        LLFunctionType::get(LLType::getInt32Ty(gIR->context()), Tys, false);
    fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp",
                            &gIR->module);
  }

  lhs = DtoBitCast(lhs, VoidPtrTy);
  rhs = DtoBitCast(rhs, VoidPtrTy);

  return gIR->ir->CreateCall(fn, {lhs, rhs, nbytes});
}
Exemplo n.º 4
0
llvm::Type * IrTypeArray::array2llvm(Type * t)
{
    assert(t->ty == Tarray && "not dynamic array type");

    // get .ptr type
    LLType* elemType = DtoType(t->nextOf());
    if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
        elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
    elemType = llvm::PointerType::get(elemType, 0);

    // create struct type
    llvm::SmallVector<LLType*, 2> types;
    types.push_back(DtoSize_t());
    types.push_back(elemType);
    LLType* at = llvm::StructType::get(llvm::getGlobalContext(), types/*, t->toChars()*/);

    return at;
}
Exemplo n.º 5
0
IrTypeArray* IrTypeArray::get(Type* dt)
{
    assert(!dt->ctype);
    assert(dt->ty == Tarray && "not dynamic array type");

    LLType* elemType = i1ToI8(voidToI8(DtoType(dt->nextOf())));

    // Could have already built the type as part of a struct forward reference,
    // just as for pointers.
    if (!dt->ctype)
    {
        llvm::Type *types[] = { DtoSize_t(), llvm::PointerType::get(elemType, 0) };
        LLType* at = llvm::StructType::get(llvm::getGlobalContext(), types, false);
        dt->ctype = new IrTypeArray(dt, at);
    }

    return dt->ctype->isArray();
}
Exemplo n.º 6
0
IrTypeArray* IrTypeArray::get(Type* dt)
{
    assert(!dt->irtype);
    assert(dt->ty == Tarray && "not dynamic array type");

    LLType* elemType = DtoTypeNotVoid(dt->nextOf());

    // Could have already built the type as part of a struct forward reference,
    // just as for pointers.
    if (!dt->irtype)
    {
        llvm::SmallVector<LLType*, 2> types;
        types.push_back(DtoSize_t());
        types.push_back(llvm::PointerType::get(elemType, 0));
        LLType* at = llvm::StructType::get(llvm::getGlobalContext(), types/*, t->toChars()*/);
        dt->irtype = new IrTypeArray(dt, at);
    }

    return dt->irtype->isArray();
}
Exemplo n.º 7
0
LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes)
{
    // int memcmp ( const void * ptr1, const void * ptr2, size_t num );

    LLFunction* fn = gIR->module->getFunction("memcmp");
    if (!fn)
    {
        std::vector<LLType*> params(3);
        params[0] = getVoidPtrType();
        params[1] = getVoidPtrType();
        params[2] = DtoSize_t();
        LLFunctionType* fty = LLFunctionType::get(LLType::getInt32Ty(gIR->context()), params, false);
        fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", gIR->module);
    }

    lhs = DtoBitCast(lhs,getVoidPtrType());
    rhs = DtoBitCast(rhs,getVoidPtrType());

    return gIR->ir->CreateCall3(fn, lhs, rhs, nbytes, "tmp");
}
Exemplo n.º 8
0
void emitCoverageLinecountInc(Loc &loc) {
  // Only emit coverage increment for locations in the source of the current
  // module
  // (for example, 'inlined' methods from other source files should be skipped).
  if (!global.params.cov || !loc.linnum || !loc.filename ||
      strcmp(gIR->dmodule->srcfile->name->toChars(), loc.filename) != 0) {
    return;
  }

  const unsigned line = loc.linnum - 1; // convert to 0-based line# index
  assert(line < gIR->dmodule->numlines);

  IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line);
  LOG_SCOPE;

  // Get GEP into _d_cover_data array
  LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(line)};
  LLValue *ptr = llvm::ConstantExpr::getGetElementPtr(
#if LDC_LLVM_VER >= 307
      LLArrayType::get(LLType::getInt32Ty(gIR->context()),
                       gIR->dmodule->numlines),
#endif
      gIR->dmodule->d_cover_data, idxs, true);

  // Do an atomic increment, so this works when multiple threads are executed.
  gIR->ir->CreateAtomicRMW(llvm::AtomicRMWInst::Add, ptr, DtoConstUint(1),
#if LDC_LLVM_VER >= 309
                           llvm::AtomicOrdering::Monotonic
#else
                           llvm::Monotonic
#endif
                           );

  unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t());
  unsigned idx = line / num_sizet_bits;
  unsigned bitidx = line % num_sizet_bits;

  IF_LOG Logger::println("_d_cover_valid[%d] |= (1 << %d)", idx, bitidx);

  gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx);
}
Exemplo n.º 9
0
DValue *binMin(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
               bool loadLhsAfterRhs) {
  Type *lhsType = lhs->type->toBasetype();
  Type *rhsType = rhs->type->toBasetype();

  if (lhsType != rhsType && lhsType->ty == Tpointer && rhsType->isintegral()) {
    Logger::println("Subtracting integer from pointer");
    return emitPointerOffset(loc, lhs, rhs, true, type, loadLhsAfterRhs);
  }

  auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);

  if (lhsType->ty == Tpointer && rhsType->ty == Tpointer) {
    LLValue *l = DtoRVal(rvals.lhs);
    LLValue *r = DtoRVal(rvals.rhs);
    LLType *llSizeT = DtoSize_t();
    l = gIR->ir->CreatePtrToInt(l, llSizeT);
    r = gIR->ir->CreatePtrToInt(r, llSizeT);
    LLValue *diff = gIR->ir->CreateSub(l, r);
    LLType *llType = DtoType(type);
    if (diff->getType() != llType)
      diff = gIR->ir->CreateIntToPtr(diff, llType);
    return new DImValue(type, diff);
  }

  if (type->ty == Tnull)
    return DtoNullValue(type, loc);
  if (type->iscomplex())
    return DtoComplexMin(loc, type, rvals.lhs, rvals.rhs);

  LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
  LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));

  if (auto aa = isAssociativeArrayAndNull(type, l, r))
    return aa;

  LLValue *res = (type->isfloating() ? gIR->ir->CreateFSub(l, r)
                                     : gIR->ir->CreateSub(l, r));

  return new DImValue(type, res);
}
Exemplo n.º 10
0
LLStructType* DtoInterfaceInfoType()
{
    if (gIR->interfaceInfoType)
        return gIR->interfaceInfoType;

    // build interface info type
    LLSmallVector<LLType*, 3> types;
    // ClassInfo classinfo
    ClassDeclaration* cd2 = ClassDeclaration::classinfo;
    DtoResolveClass(cd2);
    types.push_back(DtoType(cd2->type));
    // void*[] vtbl
    LLSmallVector<LLType*, 2> vtbltypes;
    vtbltypes.push_back(DtoSize_t());
    LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::getInt8Ty(gIR->context())));
    vtbltypes.push_back(byteptrptrty);
    types.push_back(LLStructType::get(gIR->context(), vtbltypes));
    // int offset
    types.push_back(LLType::getInt32Ty(gIR->context()));
    // create type
    gIR->interfaceInfoType = LLStructType::get(gIR->context(), types);

    return gIR->interfaceInfoType;
}
Exemplo n.º 11
0
LLStructType* DtoMutexType()
{
    if (gIR->mutexType)
        return gIR->mutexType;

    // The structures defined here must be the same as in druntime/src/rt/critical.c

    // Windows
    if (global.params.targetTriple.isOSWindows())
    {
        llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(gIR->context());
        llvm::Type *Int32Ty = llvm::Type::getInt32Ty(gIR->context());

        // Build RTL_CRITICAL_SECTION; size is 24 (32bit) or 40 (64bit)
        LLType *rtl_types[] = {
            VoidPtrTy, // Pointer to DebugInfo
            Int32Ty,   // LockCount
            Int32Ty,   // RecursionCount
            VoidPtrTy, // Handle of OwningThread
            VoidPtrTy, // Handle of LockSemaphore
            VoidPtrTy  // SpinCount
        };
        LLStructType* rtl = LLStructType::create(gIR->context(), rtl_types, "RTL_CRITICAL_SECTION");

        // Build D_CRITICAL_SECTION; size is 28 (32bit) or 48 (64bit)
        LLStructType *mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
        LLType *types[] = { getPtrToType(mutex), rtl };
        mutex->setBody(types);

        // Cache type
        gIR->mutexType = mutex;

        return mutex;
    }

    // FreeBSD
    else if (global.params.targetTriple.getOS() == llvm::Triple::FreeBSD) {
        // Just a pointer
        return LLStructType::get(gIR->context(), DtoSize_t());
    }

    // pthread_fastlock
    LLType *types2[] = {
        DtoSize_t(),
        LLType::getInt32Ty(gIR->context()) 
    };
    LLStructType* fastlock = LLStructType::get(gIR->context(), types2, false);

    // pthread_mutex
    LLType *types1[] = {
        LLType::getInt32Ty(gIR->context()),
        LLType::getInt32Ty(gIR->context()),
        getVoidPtrType(),
        LLType::getInt32Ty(gIR->context()),
        fastlock
    };
    LLStructType* pmutex = LLStructType::get(gIR->context(), types1, false);

    // D_CRITICAL_SECTION
    LLStructType* mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
    LLType *types[] = { getPtrToType(mutex), pmutex };
    mutex->setBody(types);

    // Cache type
    gIR->mutexType = mutex;

    return pmutex;
}
Exemplo n.º 12
0
llvm::ConstantInt* DtoConstSize_t(uint64_t i)
{
    return LLConstantInt::get(DtoSize_t(), i, false);
}
Exemplo n.º 13
0
DValue* DtoCastClass(Loc& loc, DValue* val, Type* _to)
{
    IF_LOG Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars());
    LOG_SCOPE;

    Type* to = _to->toBasetype();

    // class -> pointer
    if (to->ty == Tpointer) {
        IF_LOG Logger::println("to pointer");
        LLType* tolltype = DtoType(_to);
        LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
        return new DImValue(_to, rval);
    }
    // class -> bool
    else if (to->ty == Tbool) {
        IF_LOG Logger::println("to bool");
        LLValue* llval = val->getRVal();
        LLValue* zero = LLConstant::getNullValue(llval->getType());
        return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero));
    }
    // class -> integer
    else if (to->isintegral()) {
        IF_LOG Logger::println("to %s", to->toChars());

        // get class ptr
        LLValue* v = val->getRVal();
        // cast to size_t
        v = gIR->ir->CreatePtrToInt(v, DtoSize_t(), "");
        // cast to the final int type
        DImValue im(Type::tsize_t, v);
        return DtoCastInt(loc, &im, _to);
    }

    // must be class/interface
    assert(to->ty == Tclass);
    TypeClass* tc = static_cast<TypeClass*>(to);

    // from type
    Type* from = val->getType()->toBasetype();
    TypeClass* fc = static_cast<TypeClass*>(from);

    // x -> interface
    if (InterfaceDeclaration* it = tc->sym->isInterfaceDeclaration()) {
        Logger::println("to interface");
        // interface -> interface
        if (fc->sym->isInterfaceDeclaration()) {
            Logger::println("from interface");
            return DtoDynamicCastInterface(loc, val, _to);
        }
        // class -> interface - static cast
        else if (it->isBaseOf(fc->sym,NULL)) {
            Logger::println("static down cast");

            // get the from class
            ClassDeclaration* cd = fc->sym->isClassDeclaration();
            DtoResolveClass(cd); // add this
            IrTypeClass* typeclass = stripModifiers(fc)->ctype->isClass();

            // find interface impl

            size_t i_index = typeclass->getInterfaceIndex(it);
            assert(i_index != ~0UL && "requesting interface that is not implemented by this class");

            // offset pointer
            LLValue* v = val->getRVal();
            LLValue* orig = v;
            v = DtoGEPi(v, 0, i_index);
            LLType* ifType = DtoType(_to);
            IF_LOG {
                Logger::cout() << "V = " << *v << std::endl;
                Logger::cout() << "T = " << *ifType << std::endl;
            }
            v = DtoBitCast(v, ifType);

            // Check whether the original value was null, and return null if so.
            // Sure we could have jumped over the code above in this case, but
            // it's just a GEP and (maybe) a pointer-to-pointer BitCast, so it
            // should be pretty cheap and perfectly safe even if the original was null.
            LLValue* isNull = gIR->ir->CreateICmpEQ(orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
            v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(ifType), v, ".interface");

            // return r-value
            return new DImValue(_to, v);
        }
Exemplo n.º 14
0
static void buildRuntimeModule() {
  Logger::println("building runtime module");
  M = new llvm::Module("ldc internal runtime", gIR->context());

  Type *voidTy = Type::tvoid;
  Type *boolTy = Type::tbool;
  Type *ubyteTy = Type::tuns8;
  Type *intTy = Type::tint32;
  Type *uintTy = Type::tuns32;
  Type *ulongTy = Type::tuns64;
  Type *sizeTy = Type::tsize_t;
  Type *dcharTy = Type::tdchar;

  Type *voidPtrTy = Type::tvoidptr;
  Type *voidArrayTy = Type::tvoid->arrayOf();
  Type *voidArrayPtrTy = voidArrayTy->pointerTo();
  Type *stringTy = Type::tchar->arrayOf();
  Type *wstringTy = Type::twchar->arrayOf();
  Type *dstringTy = Type::tdchar->arrayOf();

  // Ensure that the declarations exist before creating llvm types for them.
  ensureDecl(ClassDeclaration::object, "Object");
  ensureDecl(Type::typeinfoclass, "TypeInfo_Class");
  ensureDecl(Type::dtypeinfo, "DTypeInfo");
  ensureDecl(Type::typeinfoassociativearray, "TypeInfo_AssociativeArray");
  ensureDecl(Module::moduleinfo, "ModuleInfo");

  Type *objectTy = ClassDeclaration::object->type;
  Type *classInfoTy = Type::typeinfoclass->type;
  Type *typeInfoTy = Type::dtypeinfo->type;
  Type *aaTypeInfoTy = Type::typeinfoassociativearray->type;
  Type *moduleInfoPtrTy = Module::moduleinfo->type->pointerTo();
  // The AA type is a struct that only contains a ptr
  Type *aaTy = voidPtrTy;

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // Construct some attribute lists used below (possibly multiple times)
  AttrSet NoAttrs, Attr_NoAlias(NoAttrs, 0, llvm::Attribute::NoAlias),
      Attr_NoUnwind(NoAttrs, ~0U, llvm::Attribute::NoUnwind),
      Attr_ReadOnly(NoAttrs, ~0U, llvm::Attribute::ReadOnly),
      Attr_ReadOnly_NoUnwind(Attr_ReadOnly, ~0U, llvm::Attribute::NoUnwind),
      Attr_ReadOnly_1_NoCapture(Attr_ReadOnly, 1, llvm::Attribute::NoCapture),
      Attr_ReadOnly_1_3_NoCapture(Attr_ReadOnly_1_NoCapture, 3,
                                  llvm::Attribute::NoCapture),
      Attr_ReadOnly_NoUnwind_1_NoCapture(Attr_ReadOnly_1_NoCapture, ~0U,
                                         llvm::Attribute::NoUnwind),
      Attr_ReadNone(NoAttrs, ~0U, llvm::Attribute::ReadNone),
      Attr_1_NoCapture(NoAttrs, 1, llvm::Attribute::NoCapture),
      Attr_NoAlias_1_NoCapture(Attr_1_NoCapture, 0, llvm::Attribute::NoAlias),
      Attr_1_2_NoCapture(Attr_1_NoCapture, 2, llvm::Attribute::NoCapture),
      Attr_1_3_NoCapture(Attr_1_NoCapture, 3, llvm::Attribute::NoCapture),
      Attr_1_4_NoCapture(Attr_1_NoCapture, 4, llvm::Attribute::NoCapture);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void _d_assert(string file, uint line)
  // void _d_arraybounds(string file, uint line)
  createFwdDecl(LINKc, Type::tvoid, {"_d_assert", "_d_arraybounds"},
                {stringTy, uintTy});

  // void _d_assert_msg(string msg, string file, uint line)
  createFwdDecl(LINKc, voidTy, {"_d_assert_msg"}, {stringTy, stringTy, uintTy});

  // void _d_assertm(immutable(ModuleInfo)* m, uint line)
  // void _d_array_bounds(immutable(ModuleInfo)* m, uint line)
  // void _d_switch_error(immutable(ModuleInfo)* m, uint line)
  createFwdDecl(LINKc, voidTy,
                {"_d_assertm", "_d_array_bounds", "_d_switch_error"},
                {moduleInfoPtrTy, uintTy}, {STCimmutable, 0});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void* _d_allocmemory(size_t sz)
  createFwdDecl(LINKc, voidPtrTy, {"_d_allocmemory"}, {sizeTy}, {},
                Attr_NoAlias);

  // void* _d_allocmemoryT(TypeInfo ti)
  createFwdDecl(LINKc, voidPtrTy, {"_d_allocmemoryT"}, {typeInfoTy}, {},
                Attr_NoAlias);

  // void[] _d_newarrayT (const TypeInfo ti, size_t length)
  // void[] _d_newarrayiT(const TypeInfo ti, size_t length)
  // void[] _d_newarrayU (const TypeInfo ti, size_t length)
  createFwdDecl(LINKc, voidArrayTy,
                {"_d_newarrayT", "_d_newarrayiT", "_d_newarrayU"},
                {typeInfoTy, sizeTy}, {STCconst, 0});

  // void[] _d_newarraymTX (const TypeInfo ti, size_t[] dims)
  // void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims)
  createFwdDecl(LINKc, voidArrayTy, {"_d_newarraymTX", "_d_newarraymiTX"},
                {typeInfoTy, sizeTy->arrayOf()}, {STCconst, 0});

  // void[] _d_arraysetlengthT (const TypeInfo ti, size_t newlength, void[]* p)
  // void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p)
  createFwdDecl(LINKc, voidArrayTy,
                {"_d_arraysetlengthT", "_d_arraysetlengthiT"},
                {typeInfoTy, sizeTy, voidArrayPtrTy}, {STCconst, 0, 0});

  // byte[] _d_arrayappendcTX(const TypeInfo ti, ref byte[] px, size_t n)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arrayappendcTX"},
                {typeInfoTy, voidArrayTy, sizeTy}, {STCconst, STCref, 0});

  // void[] _d_arrayappendT(const TypeInfo ti, ref byte[] x, byte[] y)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arrayappendT"},
                {typeInfoTy, voidArrayTy, voidArrayTy}, {STCconst, STCref, 0});

  // void[] _d_arrayappendcd(ref byte[] x, dchar c)
  // void[] _d_arrayappendwd(ref byte[] x, dchar c)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arrayappendcd", "_d_arrayappendwd"},
                {voidArrayTy, dcharTy}, {STCref, 0});

  // byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arraycatT"},
                {typeInfoTy, voidArrayTy, voidArrayTy}, {STCconst, 0, 0});

  // void[] _d_arraycatnTX(const TypeInfo ti, byte[][] arrs)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arraycatnTX"},
                {typeInfoTy, voidArrayTy->arrayOf()}, {STCconst, 0});

  // Object _d_newclass(const ClassInfo ci)
  createFwdDecl(LINKc, objectTy, {"_d_newclass"}, {classInfoTy}, {STCconst},
                Attr_NoAlias);

  // void* _d_newitemT (TypeInfo ti)
  // void* _d_newitemiT(TypeInfo ti)
  createFwdDecl(LINKc, voidPtrTy, {"_d_newitemT", "_d_newitemiT"}, {typeInfoTy},
                {0}, Attr_NoAlias);

  // void _d_delarray_t(void[]* p, const TypeInfo_Struct ti)
  createFwdDecl(LINKc, voidTy, {"_d_delarray_t"},
                {voidArrayPtrTy, Type::typeinfostruct->type}, {0, STCconst});

  // void _d_delmemory(void** p)
  // void _d_delinterface(void** p)
  createFwdDecl(LINKc, voidTy, {"_d_delmemory", "_d_delinterface"},
                {voidPtrTy->pointerTo()});

  // void _d_callfinalizer(void* p)
  createFwdDecl(LINKc, voidTy, {"_d_callfinalizer"}, {voidPtrTy});

  // D2: void _d_delclass(Object* p)
  createFwdDecl(LINKc, voidTy, {"_d_delclass"}, {objectTy->pointerTo()});

  // void _d_delstruct(void** p, TypeInfo_Struct inf)
  createFwdDecl(LINKc, voidTy, {"_d_delstruct"},
                {voidPtrTy->pointerTo(), Type::typeinfostruct->type});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // array slice copy when assertions are on!
  // void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t
  // srclen)
  createFwdDecl(LINKc, voidTy, {"_d_array_slice_copy"},
                {voidPtrTy, sizeTy, voidPtrTy, sizeTy}, {}, Attr_1_3_NoCapture);

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// int _aApplycd1(in char[] aa, dg_t dg)
// int _aApplyRcd1(in char[] aa, dg_t dg)
#define STR_APPLY1(TY, a, b)                                                   \
  {                                                                            \
    const std::string prefix = "_aApply";                                      \
    std::string fname1 = prefix + (a) + '1', fname2 = prefix + (b) + '1',      \
                fname3 = prefix + 'R' + (a) + '1',                             \
                fname4 = prefix + 'R' + (b) + '1';                             \
    createFwdDecl(LINKc, sizeTy, {fname1, fname2, fname3, fname4},             \
                  {TY, rt_dg1()});                                             \
  }
  STR_APPLY1(stringTy, "cw", "cd")
  STR_APPLY1(wstringTy, "wc", "wd")
  STR_APPLY1(dstringTy, "dc", "dw")
#undef STR_APPLY1

// int _aApplycd2(in char[] aa, dg2_t dg)
// int _aApplyRcd2(in char[] aa, dg2_t dg)
#define STR_APPLY2(TY, a, b)                                                   \
  {                                                                            \
    const std::string prefix = "_aApply";                                      \
    std::string fname1 = prefix + (a) + '2', fname2 = prefix + (b) + '2',      \
                fname3 = prefix + 'R' + (a) + '2',                             \
                fname4 = prefix + 'R' + (b) + '2';                             \
    createFwdDecl(LINKc, sizeTy, {fname1, fname2, fname3, fname4},             \
                  {TY, rt_dg2()});                                             \
  }
  STR_APPLY2(stringTy, "cw", "cd")
  STR_APPLY2(wstringTy, "wc", "wd")
  STR_APPLY2(dstringTy, "dc", "dw")
#undef STR_APPLY2

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // fixes the length for dynamic array casts
  // size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
  createFwdDecl(LINKc, sizeTy, {"_d_array_cast_len"}, {sizeTy, sizeTy, sizeTy},
                {}, Attr_ReadNone);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp)
  // void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arrayassign_l", "_d_arrayassign_r"},
                {typeInfoTy, voidArrayTy, voidArrayTy, voidPtrTy});

  // void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
  createFwdDecl(LINKc, voidArrayTy, {"_d_arrayctor"},
                {typeInfoTy, voidArrayTy, voidArrayTy});

  // void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
  // void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
  createFwdDecl(LINKc, voidPtrTy, {"_d_arraysetassign", "_d_arraysetctor"},
                {voidPtrTy, voidPtrTy, intTy, typeInfoTy}, {}, Attr_NoAlias);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // cast interface
  // void* _d_interface_cast(void* p, ClassInfo c)
  createFwdDecl(LINKc, voidPtrTy, {"_d_interface_cast"},
                {voidPtrTy, classInfoTy}, {}, Attr_ReadOnly_NoUnwind);

  // dynamic cast
  // void* _d_dynamic_cast(Object o, ClassInfo c)
  createFwdDecl(LINKc, voidPtrTy, {"_d_dynamic_cast"}, {objectTy, classInfoTy},
                {}, Attr_ReadOnly_NoUnwind);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // char[] _adReverseChar(char[] a)
  // char[] _adSortChar(char[] a)
  createFwdDecl(LINKc, stringTy, {"_adReverseChar", "_adSortChar"}, {stringTy});

  // wchar[] _adReverseWchar(wchar[] a)
  // wchar[] _adSortWchar(wchar[] a)
  createFwdDecl(LINKc, wstringTy, {"_adReverseWchar", "_adSortWchar"},
                {wstringTy});

  // void[] _adReverse(void[] a, size_t szelem)
  createFwdDecl(LINKc, wstringTy, {"_adReverse"}, {voidArrayTy, sizeTy}, {},
                Attr_NoUnwind);

  // int _adEq2(void[] a1, void[] a2, TypeInfo ti)
  // int _adCmp2(void[] a1, void[] a2, TypeInfo ti)
  createFwdDecl(LINKc, intTy, {"_adEq2", "_adCmp2"},
                {voidArrayTy, voidArrayTy, typeInfoTy}, {}, Attr_ReadOnly);

  // int _adCmpChar(void[] a1, void[] a2)
  createFwdDecl(LINKc, intTy, {"_adCmpChar"}, {voidArrayTy, voidArrayTy}, {},
                Attr_ReadOnly_NoUnwind);

  // void[] _adSort(void[] a, TypeInfo ti)
  createFwdDecl(LINKc, voidArrayTy, {"_adSort"}, {voidArrayTy, typeInfoTy});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // size_t _aaLen(in AA aa)
  createFwdDecl(LINKc, sizeTy, {"_aaLen"}, {aaTy}, {STCin},
                Attr_ReadOnly_NoUnwind_1_NoCapture);

  // void* _aaGetY(AA* aa, const TypeInfo aati, in size_t valuesize,
  //               in void* pkey)
  createFwdDecl(LINKc, voidPtrTy, {"_aaGetY"},
                {aaTy->pointerTo(), aaTypeInfoTy, sizeTy, voidPtrTy},
                {0, STCconst, STCin, STCin}, Attr_1_4_NoCapture);

  // inout(void)* _aaInX(inout AA aa, in TypeInfo keyti, in void* pkey)
  // FIXME: "inout" storageclass is not applied to return type
  createFwdDecl(LINKc, voidPtrTy, {"_aaInX"}, {aaTy, typeInfoTy, voidPtrTy},
                {STCin | STCout, STCin, STCin}, Attr_ReadOnly_1_3_NoCapture);

  // bool _aaDelX(AA aa, in TypeInfo keyti, in void* pkey)
  createFwdDecl(LINKc, boolTy, {"_aaDelX"}, {aaTy, typeInfoTy, voidPtrTy},
                {0, STCin, STCin}, Attr_1_3_NoCapture);

  // inout(void[]) _aaValues(inout AA aa, in size_t keysize,
  //                         in size_t valuesize, const TypeInfo tiValueArray)
  createFwdDecl(
      LINKc, voidArrayTy, {"_aaValues"}, {aaTy, sizeTy, sizeTy, typeInfoTy},
      {STCin | STCout, STCin, STCin, STCconst}, Attr_ReadOnly_1_3_NoCapture);

  // void* _aaRehash(AA* paa, in TypeInfo keyti)
  createFwdDecl(LINKc, voidPtrTy, {"_aaRehash"},
                {aaTy->pointerTo(), typeInfoTy}, {0, STCin});

  // inout(void[]) _aaKeys(inout AA aa, in size_t keysize,
  //                       const TypeInfo tiKeyArray)
  createFwdDecl(LINKc, voidArrayTy, {"_aaKeys"}, {aaTy, sizeTy, typeInfoTy},
                {STCin | STCout, STCin, STCconst}, Attr_NoAlias_1_NoCapture);

  // int _aaApply(AA aa, in size_t keysize, dg_t dg)
  createFwdDecl(LINKc, intTy, {"_aaApply"}, {aaTy, sizeTy, rt_dg1()},
                {0, STCin, 0}, Attr_1_NoCapture);

  // int _aaApply2(AA aa, in size_t keysize, dg2_t dg)
  createFwdDecl(LINKc, intTy, {"_aaApply2"}, {aaTy, sizeTy, rt_dg2()},
                {0, STCin, 0}, Attr_1_NoCapture);

  // int _aaEqual(in TypeInfo tiRaw, in AA e1, in AA e2)
  createFwdDecl(LINKc, intTy, {"_aaEqual"}, {typeInfoTy, aaTy, aaTy},
                {STCin, STCin, STCin}, Attr_1_2_NoCapture);

  // AA _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti,
  //                           void[] keys, void[] values)
  createFwdDecl(LINKc, aaTy, {"_d_assocarrayliteralTX"},
                {aaTypeInfoTy, voidArrayTy, voidArrayTy}, {STCconst, 0, 0});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void _moduleCtor()
  // void _moduleDtor()
  createFwdDecl(LINKc, voidTy, {"_moduleCtor", "_moduleDtor"}, {});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void _d_throw_exception(Object e)
  createFwdDecl(LINKc, voidTy, {"_d_throw_exception"}, {objectTy});

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // int _d_switch_string(char[][] table, char[] ca)
  createFwdDecl(LINKc, intTy, {"_d_switch_string"},
                {stringTy->arrayOf(), stringTy}, {}, Attr_ReadOnly);

  // int _d_switch_ustring(wchar[][] table, wchar[] ca)
  createFwdDecl(LINKc, intTy, {"_d_switch_ustring"},
                {wstringTy->arrayOf(), wstringTy}, {}, Attr_ReadOnly);

  // int _d_switch_dstring(dchar[][] table, dchar[] ca)
  createFwdDecl(LINKc, intTy, {"_d_switch_dstring"},
                {dstringTy->arrayOf(), dstringTy}, {}, Attr_ReadOnly);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // int _d_eh_personality(...)
  {
    if (global.params.targetTriple.isWindowsMSVCEnvironment()) {
      // (ptr ExceptionRecord, ptr EstablisherFrame, ptr ContextRecord,
      //  ptr DispatcherContext)
      createFwdDecl(LINKc, intTy, {"_d_eh_personality"},
                    {voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy});
    } else if (global.params.targetTriple.getArch() == llvm::Triple::arm) {
      // (int state, ptr ucb, ptr context)
      createFwdDecl(LINKc, intTy, {"_d_eh_personality"},
                    {intTy, voidPtrTy, voidPtrTy});
    } else {
      // (int ver, int actions, ulong eh_class, ptr eh_info, ptr context)
      createFwdDecl(LINKc, intTy, {"_d_eh_personality"},
                    {intTy, intTy, ulongTy, voidPtrTy, voidPtrTy});
    }
  }

  // void _d_eh_resume_unwind(ptr)
  createFwdDecl(LINKc, voidTy, {"_d_eh_resume_unwind"}, {voidPtrTy});

  // Object _d_eh_enter_catch(ptr)
  createFwdDecl(LINKc, objectTy, {"_d_eh_enter_catch"}, {voidPtrTy}, {},
                Attr_NoUnwind);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // void invariant._d_invariant(Object o)
  createFwdDecl(
      LINKd, voidTy,
      {gABI->mangleForLLVM("_D9invariant12_d_invariantFC6ObjectZv", LINKd)},
      {objectTy});

  // void _d_dso_registry(CompilerDSOData* data)
  llvm::StringRef fname("_d_dso_registry");

  LLType *LLvoidTy = LLType::getVoidTy(gIR->context());
  LLType *LLvoidPtrPtrTy = getPtrToType(getPtrToType(LLvoidTy));
  LLType *moduleInfoPtrPtrTy =
      getPtrToType(getPtrToType(DtoType(Module::moduleinfo->type)));

  llvm::StructType *dsoDataTy =
      llvm::StructType::get(DtoSize_t(),        // version
                            LLvoidPtrPtrTy,     // slot
                            moduleInfoPtrPtrTy, // _minfo_beg
                            moduleInfoPtrPtrTy, // _minfo_end
                            NULL);

  llvm::Type *types[] = {getPtrToType(dsoDataTy)};
  llvm::FunctionType *fty = llvm::FunctionType::get(LLvoidTy, types, false);
  llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);

  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////

  // extern (C) void _d_cover_register2(string filename, size_t[] valid,
  //                                    uint[] data, ubyte minPercent)
  if (global.params.cov) {
    createFwdDecl(LINKc, voidTy, {"_d_cover_register2"},
                  {stringTy, sizeTy->arrayOf(), uintTy->arrayOf(), ubyteTy});
  }
}
Exemplo n.º 15
0
DValue *DtoCastClass(Loc &loc, DValue *val, Type *_to) {
  IF_LOG Logger::println("DtoCastClass(%s, %s)", val->type->toChars(),
                         _to->toChars());
  LOG_SCOPE;

  Type *to = _to->toBasetype();

  // class -> pointer
  if (to->ty == Tpointer) {
    IF_LOG Logger::println("to pointer");
    LLType *tolltype = DtoType(_to);
    LLValue *rval = DtoBitCast(DtoRVal(val), tolltype);
    return new DImValue(_to, rval);
  }
  // class -> bool
  if (to->ty == Tbool) {
    IF_LOG Logger::println("to bool");
    LLValue *llval = DtoRVal(val);
    LLValue *zero = LLConstant::getNullValue(llval->getType());
    return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero));
  }
  // class -> integer
  if (to->isintegral()) {
    IF_LOG Logger::println("to %s", to->toChars());

    // get class ptr
    LLValue *v = DtoRVal(val);
    // cast to size_t
    v = gIR->ir->CreatePtrToInt(v, DtoSize_t(), "");
    // cast to the final int type
    DImValue im(Type::tsize_t, v);
    return DtoCastInt(loc, &im, _to);
  }
  // class -> typeof(null)
  if (to->ty == Tnull) {
    IF_LOG Logger::println("to %s", to->toChars());
    return new DImValue(_to, LLConstant::getNullValue(DtoType(_to)));
  }

  // must be class/interface
  assert(to->ty == Tclass);
  TypeClass *tc = static_cast<TypeClass *>(to);

  // from type
  Type *from = val->type->toBasetype();
  TypeClass *fc = static_cast<TypeClass *>(from);

  // copy DMD logic:
  // if to isBaseOf from with offset:   (to ? to + offset : null)
  // else if from is C++ and to is C++:  to
  // else if from is C++ and to is D:    null
  // else if from is interface:          _d_interface_cast(to)
  // else if from is class:              _d_dynamic_cast(to)

  LLType *toType = DtoType(_to);
  int offset = 0;
  if (tc->sym->isBaseOf(fc->sym, &offset)) {
    Logger::println("static down cast");
    // interface types don't cover the full object in case of multiple inheritence
    //  so GEP on the original type is inappropriate

    // offset pointer
    LLValue *orig = DtoRVal(val);
    LLValue *v = orig;
    if (offset != 0) {
      v = DtoBitCast(v, getVoidPtrType());
      LLValue *off =
          LLConstantInt::get(LLType::getInt32Ty(gIR->context()), offset);
      v = gIR->ir->CreateGEP(v, off);
    }
    IF_LOG {
      Logger::cout() << "V = " << *v << std::endl;
      Logger::cout() << "T = " << *toType << std::endl;
    }
    v = DtoBitCast(v, toType);

    // Check whether the original value was null, and return null if so.
    // Sure we could have jumped over the code above in this case, but
    // it's just a GEP and (maybe) a pointer-to-pointer BitCast, so it
    // should be pretty cheap and perfectly safe even if the original was
    // null.
    LLValue *isNull = gIR->ir->CreateICmpEQ(
        orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
    v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(toType), v,
                              ".interface");
    // return r-value
    return new DImValue(_to, v);
  }
Exemplo n.º 16
0
LLStructType* DtoMutexType()
{
    if (gIR->mutexType)
        return gIR->mutexType;

    // The structures defined here must be the same as in druntime/src/rt/critical.c

    // Windows
    if (global.params.os == OSWindows)
    {
        llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(gIR->context());
        llvm::Type *Int32Ty = llvm::Type::getInt32Ty(gIR->context());

        // Build RTL_CRITICAL_SECTION; size is 24 (32bit) or 40 (64bit)
        std::vector<LLType*> rtl_types;
        rtl_types.push_back(VoidPtrTy); // Pointer to DebugInfo
        rtl_types.push_back(Int32Ty);   // LockCount
        rtl_types.push_back(Int32Ty);   // RecursionCount
        rtl_types.push_back(VoidPtrTy); // Handle of OwningThread
        rtl_types.push_back(VoidPtrTy); // Handle of LockSemaphore
        rtl_types.push_back(VoidPtrTy); // SpinCount
        LLStructType* rtl = LLStructType::create(gIR->context(), rtl_types, "RTL_CRITICAL_SECTION");

        // Build D_CRITICAL_SECTION; size is 28 (32bit) or 48 (64bit)
        LLStructType* mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
        std::vector<LLType*> types;
        types.push_back(getPtrToType(mutex));
        types.push_back(rtl);
        mutex->setBody(types);

        // Cache type
        gIR->mutexType = mutex;

        return mutex;
    }

    // FreeBSD
    else if (global.params.os == OSFreeBSD) {
        // Just a pointer
        return LLStructType::get(gIR->context(), DtoSize_t());
    }

    // pthread_fastlock
    std::vector<LLType*> types2;
    types2.push_back(DtoSize_t());
    types2.push_back(LLType::getInt32Ty(gIR->context()));
    LLStructType* fastlock = LLStructType::get(gIR->context(), types2);

    // pthread_mutex
    std::vector<LLType*> types1;
    types1.push_back(LLType::getInt32Ty(gIR->context()));
    types1.push_back(LLType::getInt32Ty(gIR->context()));
    types1.push_back(getVoidPtrType());
    types1.push_back(LLType::getInt32Ty(gIR->context()));
    types1.push_back(fastlock);
    LLStructType* pmutex = LLStructType::get(gIR->context(), types1);

    // D_CRITICAL_SECTION
    LLStructType* mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
    std::vector<LLType*> types;
    types.push_back(getPtrToType(mutex));
    types.push_back(pmutex);
    mutex->setBody(types);

    // Cache type
    gIR->mutexType = mutex;

    return pmutex;
}