Ejemplo n.º 1
0
Archivo: tollvm.cpp Proyecto: Doeme/ldc
LLValue *DtoBitCast(LLValue *v, LLType *t, const llvm::Twine &name) {
  if (v->getType() == t) {
    return v;
  }
  assert(!isaStruct(t));
  return gIR->ir->CreateBitCast(v, t, name);
}
Ejemplo n.º 2
0
LLValue* DtoBitCast(LLValue* v, LLType* t, const char* name)
{
    if (v->getType() == t)
        return v;
    assert(!isaStruct(t));
    return gIR->ir->CreateBitCast(v, t, name);
}
Ejemplo n.º 3
0
llvm::Type* IrTypeClass::buildType()
{
    IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->loc.toChars());
    LOG_SCOPE;
    IF_LOG Logger::println("Instance size: %u", cd->structsize);

    // find the fields that contribute to the default initializer.
    // these will define the default type.

    std::vector<llvm::Type*> defaultTypes;
    defaultTypes.reserve(32);

    // add vtbl
    defaultTypes.push_back(llvm::PointerType::get(vtbl_type, 0));

    // interfaces are just a vtable
    if (cd->isInterfaceDeclaration())
    {
        num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->dim : 0;
    }
    // classes have monitor and fields
    else
    {
        // add monitor
        defaultTypes.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(gIR->context()), 0));

        // we start right after the vtbl and monitor
        size_t offset = PTRSIZE * 2;
        size_t field_index = 2;

        // add data members recursively
        addBaseClassData(defaultTypes, cd, offset, field_index);

#if 1
        // tail padding?
        if (offset < cd->structsize)
        {
            field_index += add_zeros(defaultTypes, cd->structsize - offset);
            offset = cd->structsize;
        }
#endif
    }

    // errors are fatal during codegen
    if (global.errors)
        fatal();

    // set struct body
    isaStruct(type)->setBody(defaultTypes, false);

    // VTBL

    // set vtbl type body
    vtbl_type->setBody(buildVtblType(ClassDeclaration::classinfo->type, &cd->vtbl));

    IF_LOG Logger::cout() << "class type: " << *type << std::endl;

    return get();
}
Ejemplo n.º 4
0
IrTypeStruct *IrTypeStruct::get(StructDeclaration *sd) {
  auto t = new IrTypeStruct(sd);
  sd->type->ctype = t;

  IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(),
                         sd->loc.toChars());
  LOG_SCOPE;

  // if it's a forward declaration, all bets are off, stick with the opaque
  if (sd->sizeok != SIZEOKdone) {
    return t;
  }

  t->packed = isPacked(sd);

  // For ldc.dcomptetypes.Pointer!(uint n,T),
  // emit { T addrspace(gIR->dcomputetarget->mapping[n])* }
    llvm::Optional<DcomputePointer> p;
  if (gIR->dcomputetarget && (p = toDcomputePointer(sd))) {
   
    // Translate the virtual dcompute address space into the real one for
    // the target
    int realAS = gIR->dcomputetarget->mapping[p->addrspace];

    llvm::SmallVector<LLType *, 1> body;
    body.push_back(DtoMemType(p->type)->getPointerTo(realAS));

    isaStruct(t->type)->setBody(body, t->packed);
    VarGEPIndices v;
    v[sd->fields[0]] = 0;
    t->varGEPIndices = v;
  } else {
    AggrTypeBuilder builder(t->packed);
    builder.addAggregate(sd);
    builder.addTailPadding(sd->structsize);
    isaStruct(t->type)->setBody(builder.defaultTypes(), t->packed);
    t->varGEPIndices = builder.varGEPIndices();
  }

  IF_LOG Logger::cout() << "final struct type: " << *t->type << std::endl;

  return t;
}
Ejemplo n.º 5
0
LLValue *DtoBitCast(LLValue *v, LLType *t, const llvm::Twine &name) {
  // Strip addrspace qualifications from v before comparing types by pointer
  // equality. This avoids the case where the pointer in { T addrspace(n)* }
  // is dereferenced and generates a GEP -> (invalid) bitcast -> load sequence.
  // Bitcasting of pointers between addrspaces is invalid in LLVM IR. Even if
  // it were valid, it wouldn't be the desired outcome as we would always load
  // from addrspace(0), instead of the addrspace of the pointer.
  if (stripAddrSpaces(v->getType()) == t) {
    return v;
  }
  assert(!isaStruct(t));
  return gIR->ir->CreateBitCast(v, t, name);
}
Ejemplo n.º 6
0
LLValue *DtoCallableValue(DValue *fn) {
  Type *type = fn->getType()->toBasetype();
  if (type->ty == Tfunction) {
    return fn->getRVal();
  }
  if (type->ty == Tdelegate) {
    if (fn->isLVal()) {
      LLValue *dg = fn->getLVal();
      LLValue *funcptr = DtoGEPi(dg, 0, 1);
      return DtoLoad(funcptr, ".funcptr");
    }
    LLValue *dg = fn->getRVal();
    assert(isaStruct(dg));
    return gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
  }

  llvm_unreachable("Not a callable type.");
}
Ejemplo n.º 7
0
void RTTIBuilder::finalize(LLType* type, LLValue* value)
{
    llvm::ArrayRef<LLConstant*> inits = llvm::makeArrayRef(this->inits);
    LLStructType *st = isaStruct(type);
    assert(st);

    // set struct body
    if (st->isOpaque()) {
        std::vector<LLType*> types;
        for (int i = 0, n = inits.size(); i < n; ++i)
            types.push_back(inits[i]->getType());
        st->setBody(types);
    }

    // create the inititalizer
    LLConstant* tiInit = LLConstantStruct::get(st, inits);

    // set the initializer
    isaGlobalVar(value)->setInitializer(tiInit);
}
Ejemplo n.º 8
0
// build a single element for the OffsetInfo[] of ClassInfo
static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
{
    std::vector<LLConstant*> inits(2);

    // size_t offset;
    //
    assert(vd->ir.irField);
    // grab the offset from llvm and the formal class type
    size_t offset = gDataLayout->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
    // offset nested struct/union fields
    offset += vd->ir.irField->unionOffset;

    // assert that it matches DMD
    Logger::println("offsets: %lu vs %u", offset, vd->offset);
    assert(offset == vd->offset);

    inits[0] = DtoConstSize_t(offset);

    // TypeInfo ti;
    inits[1] = DtoTypeInfoOf(vd->type, true);

    // done
    return llvm::ConstantStruct::get(inits);
}
Ejemplo n.º 9
0
void RTTIBuilder::finalize(LLType* type, LLValue* value)
{
    llvm::ArrayRef<LLConstant*> inits = llvm::makeArrayRef(this->inits);
    LLStructType *st = isaStruct(type);
    assert(st);

    // set struct body
    if (st->isOpaque()) {
        const int n = inits.size();
        std::vector<LLType*> types;
        types.reserve(n);
        for (int i = 0; i < n; ++i)
            types.push_back(inits[i]->getType());
        st->setBody(types);
    }

    // create the inititalizer
    LLConstant* tiInit = LLConstantStruct::get(st, inits);

    // set the initializer
    llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(value);
    gvar->setInitializer(tiInit);
    gvar->setLinkage(TYPEINFO_LINKAGE_TYPE);
}
Ejemplo n.º 10
0
static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
                                 IrFuncTy &irFty, LLFunctionType *callableTy,
                                 const std::vector<DValue *> &argvals,
                                 int numFormalParams) {
  // Number of arguments added to the LLVM type that are implicit on the
  // frontend side of things (this, context pointers, etc.)
  const size_t implicitLLArgCount = args.size();

  // Number of formal arguments in the LLVM type (i.e. excluding varargs).
  const size_t formalLLArgCount = irFty.args.size();

  // The number of explicit arguments in the D call expression (including
  // varargs), not all of which necessarily generate a LLVM argument.
  const size_t explicitDArgCount = argvals.size();

  // construct and initialize an IrFuncTyArg object for each vararg
  std::vector<IrFuncTyArg *> optionalIrArgs;
  for (size_t i = numFormalParams; i < explicitDArgCount; i++) {
    Type *argType = argvals[i]->getType();
    bool passByVal = gABI->passByVal(argType);

    AttrBuilder initialAttrs;
    if (passByVal) {
      initialAttrs.add(LLAttribute::ByVal);
    } else {
      initialAttrs.add(DtoShouldExtend(argType));
    }

    optionalIrArgs.push_back(new IrFuncTyArg(argType, passByVal, initialAttrs));
    optionalIrArgs.back()->parametersIdx = i;
  }

  // let the ABI rewrite the IrFuncTyArg objects
  gABI->rewriteVarargs(irFty, optionalIrArgs);

  const size_t explicitLLArgCount = formalLLArgCount + optionalIrArgs.size();
  args.resize(implicitLLArgCount + explicitLLArgCount,
              static_cast<llvm::Value *>(nullptr));

  // Iterate the explicit arguments from left to right in the D source,
  // which is the reverse of the LLVM order if irFty.reverseParams is true.
  for (size_t i = 0; i < explicitLLArgCount; ++i) {
    const bool isVararg = (i >= irFty.args.size());
    IrFuncTyArg *irArg = nullptr;
    if (isVararg) {
      irArg = optionalIrArgs[i - numFormalParams];
    } else {
      irArg = irFty.args[i];
    }

    DValue *const argval = argvals[irArg->parametersIdx];
    Type *const argType = argval->getType();

    llvm::Value *llVal = nullptr;
    if (isVararg) {
      llVal = irFty.putParam(*irArg, argval);
    } else {
      llVal = irFty.putParam(i, argval);
    }

    const size_t llArgIdx =
        implicitLLArgCount +
        (irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
    llvm::Type *const callableArgType =
        (isVararg ? nullptr : callableTy->getParamType(llArgIdx));

    // Hack around LDC assuming structs and static arrays are in memory:
    // If the function wants a struct, and the argument value is a
    // pointer to a struct, load from it before passing it in.
    if (isaPointer(llVal) && DtoIsPassedByRef(argType) &&
        ((!isVararg && !isaPointer(callableArgType)) ||
         (isVararg && !irArg->byref && !irArg->isByVal()))) {
      Logger::println("Loading struct type for function argument");
      llVal = DtoLoad(llVal);
    }

    // parameter type mismatch, this is hard to get rid of
    if (!isVararg && llVal->getType() != callableArgType) {
      IF_LOG {
        Logger::cout() << "arg:     " << *llVal << '\n';
        Logger::cout() << "expects: " << *callableArgType << '\n';
      }
      if (isaStruct(llVal)) {
        llVal = DtoAggrPaint(llVal, callableArgType);
      } else {
        llVal = DtoBitCast(llVal, callableArgType);
      }
    }

    args[llArgIdx] = llVal;
    // +1 as index 0 contains the function attributes.
    attrs.add(llArgIdx + 1, irArg->attrs);

    if (isVararg) {
      delete irArg;
    }
  }
Ejemplo n.º 11
0
bool X86_64TargetABI::passByVal(Type* t) {
    t = t->toBasetype();
    if (linkage() == LINKd) {
        return t->toBasetype()->ty == Tstruct;
    } else {
        // This implements the C calling convention for x86-64.
        // It might not be correct for other calling conventions.
        Classification cl = classify(t);
        if (cl.isMemory)
            return true;
        
        // Figure out how many registers we want for this arg:
        RegCount wanted = { 0, 0 };
        for (int i = 0 ; i < 2; i++) {
            if (cl.classes[i] == Integer)
                wanted.int_regs++;
            else if (cl.classes[i] == Sse)
                wanted.sse_regs++;
        }
        
        // See if they're available:
        RegCount& state = this->state();
        if (wanted.int_regs <= state.int_regs && wanted.sse_regs <= state.sse_regs) {
            state.int_regs -= wanted.int_regs;
            state.sse_regs -= wanted.sse_regs;
        } else {
            if (keepUnchanged(t)) {
                // Not enough registers available, but this is passed as if it's
                // multiple arguments. Just use the registers there are,
                // automatically spilling the rest to memory.
                if (wanted.int_regs > state.int_regs)
                    state.int_regs = 0;
                else
                    state.int_regs -= wanted.int_regs;
                
                if (wanted.sse_regs > state.sse_regs)
                    state.sse_regs = 0;
                else
                    state.sse_regs -= wanted.sse_regs;
            } else if (t->iscomplex() || t->ty == Tstruct) {
                // Spill entirely to memory, even if some of the registers are
                // available.
                
                // FIXME: Don't do this if *none* of the wanted registers are available,
                //        (i.e. only when absolutely necessary for abi-compliance)
                //        so it gets alloca'd by the callee and -scalarrepl can
                //        more easily break it up?
                // Note: this won't be necessary if the following LLVM bug gets fixed:
                //       http://llvm.org/bugs/show_bug.cgi?id=3741
                return true;
            } else {
                assert(t == Type::tfloat80 || t == Type::timaginary80 || t->ty == Tsarray || t->size() <= 8
                    && "What other big types are there?");
                // In any case, they shouldn't be represented as structs in LLVM:
                assert(!isaStruct(DtoType(t)));
            }
        }
        // Everything else that's passed in memory is handled by LLVM.
        return false;
    }
}
Ejemplo n.º 12
0
LLConstant * IrStruct::getClassInfoInterfaces()
{
    IF_LOG Logger::println("Building ClassInfo.interfaces");
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd);

    size_t n = interfacesWithVtbls.size();
    assert(stripModifiers(type)->irtype->isClass()->getNumInterfaceVtbls() == n &&
        "inconsistent number of interface vtables in this class");

    VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);

    if (n == 0)
        return getNullValue(DtoType(interfaces_idx->type));

// Build array of:
//
//     struct Interface
//     {
//         ClassInfo   classinfo;
//         void*[]     vtbl;
//         ptrdiff_t   offset;
//     }

    LLSmallVector<LLConstant*, 6> constants;
    constants.reserve(cd->vtblInterfaces->dim);

    LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type);
    LLType* voidptrptr_type = DtoType(
        Type::tvoid->pointerTo()->pointerTo());
    VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
    LLStructType* interface_type = isaStruct(DtoType(idx->type->nextOf()));
    assert(interface_type);

    for (size_t i = 0; i < n; ++i)
    {
        BaseClass* it = interfacesWithVtbls[i];

        IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars());

        IrStruct* irinter = it->base->ir.irStruct;
        assert(irinter && "interface has null IrStruct");
        IrTypeClass* itc = stripModifiers(irinter->type)->irtype->isClass();
        assert(itc && "null interface IrTypeClass");

        // classinfo
        LLConstant* ci = irinter->getClassInfoSymbol();
        ci = DtoBitCast(ci, classinfo_type);

        // vtbl
        LLConstant* vtb;
        // interface get a null
        if (cd->isInterfaceDeclaration())
        {
            vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(voidptrptr_type));
        }
        else
        {
            ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base);
            assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
            vtb = itv->second;
            vtb = DtoBitCast(vtb, voidptrptr_type);
            vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
        }

        // offset
        LLConstant* off = DtoConstSize_t(it->offset);

        // create Interface struct
        LLConstant* inits[3] = { ci, vtb, off };
        LLConstant* entry = LLConstantStruct::get(interface_type, llvm::makeArrayRef(inits, 3));
        constants.push_back(entry);
    }

    // create Interface[N]
    LLArrayType* array_type = llvm::ArrayType::get(interface_type, n);

    // create and apply initializer
    LLConstant* arr = LLConstantArray::get(array_type, constants);
    classInterfacesArray->setInitializer(arr);

    // return null, only baseclass provide interfaces
    if (cd->vtblInterfaces->dim == 0)
    {
        return getNullValue(DtoType(interfaces_idx->type));
    }

    // only the interface explicitly implemented by this class
    // (not super classes) should show in ClassInfo
    LLConstant* idxs[2] = {
        DtoConstSize_t(0),
        DtoConstSize_t(n - cd->vtblInterfaces->dim)
    };

    LLConstant* ptr = llvm::ConstantExpr::getGetElementPtr(
        classInterfacesArray, idxs, true);

    // return as a slice
    return DtoConstSlice( DtoConstSize_t(cd->vtblInterfaces->dim), ptr );
}
Ejemplo n.º 13
0
LLConstant * IrStruct::getVtblInit()
{
    if (constVtbl)
        return constVtbl;

    IF_LOG Logger::println("Building vtbl initializer");
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "not class");

    std::vector<llvm::Constant*> constants;
    constants.reserve(cd->vtbl.dim);

    // start with the classinfo
    llvm::Constant* c = getClassInfoSymbol();
    c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type));
    constants.push_back(c);

    // add virtual function pointers
    size_t n = cd->vtbl.dim;
    for (size_t i = 1; i < n; i++)
    {
        Dsymbol* dsym = static_cast<Dsymbol*>(cd->vtbl.data[i]);
        assert(dsym && "null vtbl member");

        FuncDeclaration* fd = dsym->isFuncDeclaration();
        assert(fd && "vtbl entry not a function");

        if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody))
        {
            c = getNullValue(DtoType(fd->type->pointerTo()));
        }
        else
        {
            fd->codegen(Type::sir);
            assert(fd->ir.irFunc && "invalid vtbl function");
            c = fd->ir.irFunc->func;
#if DMDV2
            if (cd->isFuncHidden(fd))
            {   /* fd is hidden from the view of this class.
                 * If fd overlaps with any function in the vtbl[], then
                 * issue 'hidden' error.
                 */
                for (size_t j = 1; j < n; j++)
                {   if (j == i)
                        continue;
                    FuncDeclaration *fd2 = static_cast<Dsymbol *>(cd->vtbl.data[j])->isFuncDeclaration();
                    if (!fd2->ident->equals(fd->ident))
                        continue;
                    if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
                    {
                        if (global.params.warnings)
                        {
                            TypeFunction *tf = static_cast<TypeFunction *>(fd->type);
                            if (tf->ty == Tfunction)
                                error("%s%s is hidden by %s\n", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars());
                            else
                                error("%s is hidden by %s\n", fd->toPrettyChars(), toChars());
                        }
                        c = DtoBitCast(LLVM_D_GetRuntimeFunction(gIR->module, "_d_hidden_func"), c->getType());
                        break;
                    }
                }
            }
#endif
        }
        constants.push_back(c);
    }

    // build the constant struct
    LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
    constVtbl = LLConstantStruct::get(isaStruct(vtblTy), constants);

#if 0
   IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
   IF_LOG Logger::cout() << "vtbl type: " << *stripModifiers(type)->irtype->isClass()->getVtbl() << std::endl;
#endif

#if 0

    size_t nc = constants.size();

    for (size_t i = 0; i < nc; ++i)
    {
        if (constVtbl->getOperand(i)->getType() != vtblTy->getContainedType(i))
        {
            Logger::cout() << "type mismatch for entry # " << i << " in vtbl initializer" << std::endl;

            constVtbl->getOperand(i)->dump();
            vtblTy->getContainedType(i)->dump();
        }
    }

#endif

    assert(constVtbl->getType() == stripModifiers(type)->irtype->isClass()->getVtbl() &&
        "vtbl initializer type mismatch");

    return constVtbl;
}
Ejemplo n.º 14
0
LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
{
//     The layout is:
//        {
//         void **vptr;
//         monitor_t monitor;
//         byte[] initializer;     // static initialization data
//         char[] name;        // class name
//         void *[] vtbl;
//         Interface[] interfaces;
//         ClassInfo *base;        // base class
//         void *destructor;
//         void *invariant;        // class invariant
//         uint flags;
//         void *deallocator;
//         OffsetTypeInfo[] offTi;
//         void *defaultConstructor;
//         version(D_Version2)
//              immutable(void)* m_RTInfo;
//         else
//              TypeInfo typeinfo; // since dmd 1.045
//        }

    Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
    LOG_SCOPE;

    assert(cd->type->ty == Tclass);
    TypeClass* cdty = static_cast<TypeClass*>(cd->type);

    IrStruct* ir = cd->ir.irStruct;
    assert(ir);

    ClassDeclaration* cinfo = ClassDeclaration::classinfo;

    if (cinfo->fields.dim != 12)
    {
        error("object.d ClassInfo class is incorrect");
        fatal();
    }

    // use the rtti builder
    RTTIBuilder b(ClassDeclaration::classinfo);

    LLConstant* c;

    LLType* voidPtr = getVoidPtrType();
    LLType* voidPtrPtr = getPtrToType(voidPtr);

    // byte[] init
    if (cd->isInterfaceDeclaration())
    {
        b.push_null_void_array();
    }
    else
    {
        LLType* cd_type = cdty->irtype->isClass()->getMemoryLLType();
        size_t initsz = getTypePaddedSize(cd_type);
        b.push_void_array(initsz, ir->getInitSymbol());
    }

    // class name
    // code from dmd
    const char *name = cd->ident->toChars();
    size_t namelen = strlen(name);
    if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
    {
        name = cd->toPrettyChars();
        namelen = strlen(name);
    }
    b.push_string(name);

    // vtbl array
    if (cd->isInterfaceDeclaration())
    {
        b.push_array(0, getNullValue(voidPtrPtr));
    }
    else
    {
        c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
        b.push_array(cd->vtbl.dim, c);
    }

    // interfaces array
    b.push(ir->getClassInfoInterfaces());

    // base classinfo
    // interfaces never get a base , just the interfaces[]
    if (cd->baseClass && !cd->isInterfaceDeclaration())
        b.push_classinfo(cd->baseClass);
    else
        b.push_null(cinfo->type);

    // destructor
    if (cd->isInterfaceDeclaration())
        b.push_null_vp();
    else
        b.push(build_class_dtor(cd));

    // invariant
    VarDeclaration* invVar = static_cast<VarDeclaration*>(cinfo->fields.data[6]);
    b.push_funcptr(cd->inv, invVar->type);

    // uint flags
    unsigned flags;
    if (cd->isInterfaceDeclaration())
        flags = 4 | cd->isCOMinterface() | 32;
    else
        flags = build_classinfo_flags(cd);
    b.push_uint(flags);

    // deallocator
    b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());

    // offset typeinfo
    VarDeclaration* offTiVar = static_cast<VarDeclaration*>(cinfo->fields.data[9]);

#if GENERATE_OFFTI

    if (cd->isInterfaceDeclaration())
        b.push_null(offTiVar->type);
    else
        b.push(build_offti_array(cd, DtoType(offTiVar->type)));

#else // GENERATE_OFFTI

    b.push_null(offTiVar->type);

#endif // GENERATE_OFFTI

    // default constructor
    VarDeclaration* defConstructorVar = static_cast<VarDeclaration*>(cinfo->fields.data[10]);
    b.push_funcptr(cd->defaultCtor, defConstructorVar->type);

#if DMDV2
    // immutable(void)* m_RTInfo;
    // The cases where getRTInfo is null are not quite here, but the code is
    // modelled after what DMD does.
    if (cd->getRTInfo)
        b.push(cd->getRTInfo->toConstElem(gIR));
    else if (flags & 2)
        b.push_size_as_vp(0);       // no pointers
    else
        b.push_size_as_vp(1);       // has pointers
#else
    // typeinfo - since 1.045
    b.push_typeinfo(cd->type);
#endif

    /*size_t n = inits.size();
    for (size_t i=0; i<n; ++i)
    {
        Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n';
    }*/

    // build the initializer
    LLType *initType = ir->classInfo->getType()->getContainedType(0);
    LLConstant* finalinit = b.get_constant(isaStruct(initType));

    //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
    ir->constClassInfo = finalinit;

    // sanity check
    assert(finalinit->getType() == initType &&
        "__ClassZ initializer does not match the ClassInfo type");

    // return initializer
    return finalinit;
}
Ejemplo n.º 15
0
IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
  const auto t = new IrTypeClass(cd);
  cd->type->ctype = t;

  IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(),
                         cd->loc.toChars());
  LOG_SCOPE;
  IF_LOG Logger::println("Instance size: %u", cd->structsize);

  // This class may contain an align declaration. See GitHub #726.
  t->packed = false;
  for (auto base = cd; base != nullptr && !t->packed; base = base->baseClass) {
    t->packed = isPacked(base);
  }

  AggrTypeBuilder builder(t->packed);

  // add vtbl
  builder.addType(llvm::PointerType::get(t->vtbl_type, 0), Target::ptrsize);

  if (cd->isInterfaceDeclaration()) {
    // interfaces are just a vtable
    t->num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->dim : 0;
  } else {
    // classes have monitor and fields
    if (!cd->isCPPclass() && !cd->isCPPinterface()) {
      // add monitor
      builder.addType(
          llvm::PointerType::get(llvm::Type::getInt8Ty(gIR->context()), 0),
          Target::ptrsize);
    }

    // add data members recursively
    t->addClassData(builder, cd);

    // add tail padding
    builder.addTailPadding(cd->structsize);
  }

  if (global.errors) {
    fatal();
  }

  // set struct body and copy GEP indices
  isaStruct(t->type)->setBody(builder.defaultTypes(), t->packed);
  t->varGEPIndices = builder.varGEPIndices();

  // set vtbl type body
  FuncDeclarations vtbl;
  vtbl.reserve(cd->vtbl.dim);
  if (!cd->isCPPclass())
    vtbl.push(nullptr);
  for (size_t i = cd->vtblOffset(); i < cd->vtbl.dim; ++i) {
    FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration();
    assert(fd);
    vtbl.push(fd);
  }
  Type* first = cd->isCPPclass() ? nullptr : Type::typeinfoclass->type;
  t->vtbl_type->setBody(t->buildVtblType(first, &vtbl));

  IF_LOG Logger::cout() << "class type: " << *t->type << std::endl;

  return t;
}