示例#1
0
文件: typinf.cpp 项目: wilzbach/ldc
  void visit(TypeInfoStructDeclaration *decl) override {
    IF_LOG Logger::println("TypeInfoStructDeclaration::llvmDefine() %s",
                           decl->toChars());
    LOG_SCOPE;

    // make sure struct is resolved
    assert(decl->tinfo->ty == Tstruct);
    TypeStruct *tc = static_cast<TypeStruct *>(decl->tinfo);
    StructDeclaration *sd = tc->sym;

    // check declaration in object.d
    const auto structTypeInfoType = getStructTypeInfoType();
    const auto structTypeInfoDecl = Type::typeinfostruct;

    // On x86_64, class TypeInfo_Struct contains 2 additional fields
    // (m_arg1/m_arg2) which are used for the X86_64 System V ABI varargs
    // implementation. They are not present on any other cpu/os.
    const bool isX86_64 =
        global.params.targetTriple->getArch() == llvm::Triple::x86_64;
    const unsigned expectedFields = 11 + (isX86_64 ? 2 : 0);
    const unsigned actualFields =
        structTypeInfoDecl->fields.dim -
        1; // union of xdtor/xdtorti counts as 2 overlapping fields
    if (actualFields != expectedFields) {
      error(Loc(), "Unexpected number of `object.TypeInfo_Struct` fields; "
                   "druntime version does not match compiler");
      fatal();
    }

    RTTIBuilder b(structTypeInfoType);

    // handle opaque structs
    if (!sd->members) {
      Logger::println("is opaque struct, emitting dummy TypeInfo_Struct");

      b.push_null_void_array(); // name
      b.push_null_void_array(); // m_init
      b.push_null_vp();         // xtoHash
      b.push_null_vp();         // xopEquals
      b.push_null_vp();         // xopCmp
      b.push_null_vp();         // xtoString
      b.push_uint(0);           // m_flags
      b.push_null_vp();         // xdtor/xdtorti
      b.push_null_vp();         // xpostblit
      b.push_uint(0);           // m_align
      if (isX86_64) {
        b.push_null_vp();       // m_arg1
        b.push_null_vp();       // m_arg2
      }
      b.push_null_vp();         // m_RTInfo

      b.finalize(gvar);
      return;
    }

    // can't emit typeinfo for forward declarations
    if (sd->sizeok != SIZEOKdone) {
      sd->error("cannot emit `TypeInfo` for forward declaration");
      fatal();
    }

    DtoResolveStruct(sd);

    if (TemplateInstance *ti = sd->isInstantiated()) {
      if (!ti->needsCodegen()) {
        assert(ti->minst || sd->requestTypeInfo);

        // We won't emit ti, so emit the special member functions in here.
        if (sd->xeq && sd->xeq != StructDeclaration::xerreq &&
            sd->xeq->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->xeq);
        }
        if (sd->xcmp && sd->xcmp != StructDeclaration::xerrcmp &&
            sd->xcmp->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->xcmp);
        }
        if (FuncDeclaration *ftostr = search_toString(sd)) {
          if (ftostr->semanticRun >= PASSsemantic3)
            Declaration_codegen(ftostr);
        }
        if (sd->xhash && sd->xhash->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->xhash);
        }
        if (sd->postblit && sd->postblit->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->postblit);
        }
        if (sd->dtor && sd->dtor->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->dtor);
        }
        if (sd->tidtor && sd->tidtor->semanticRun >= PASSsemantic3) {
          Declaration_codegen(sd->tidtor);
        }
      }
    }

    IrAggr *iraggr = getIrAggr(sd);

    // string name
    b.push_string(sd->toPrettyChars());

    // void[] m_init
    // The protocol is to write a null pointer for zero-initialized arrays. The
    // length field is always needed for tsize().
    llvm::Constant *initPtr;
    if (tc->isZeroInit(Loc())) {
      initPtr = getNullValue(getVoidPtrType());
    } else {
      initPtr = iraggr->getInitSymbol();
    }
    b.push_void_array(getTypeStoreSize(DtoType(tc)), initPtr);

    // function xtoHash
    FuncDeclaration *fd = sd->xhash;
    b.push_funcptr(fd);

    // function xopEquals
    fd = sd->xeq;
    b.push_funcptr(fd);

    // function xopCmp
    fd = sd->xcmp;
    b.push_funcptr(fd);

    // function xtoString
    fd = search_toString(sd);
    b.push_funcptr(fd);

    // uint m_flags
    unsigned hasptrs = tc->hasPointers() ? 1 : 0;
    b.push_uint(hasptrs);

    // function xdtor/xdtorti
    b.push_funcptr(sd->tidtor);

    // function xpostblit
    FuncDeclaration *xpostblit = sd->postblit;
    if (xpostblit && sd->postblit->storage_class & STCdisable) {
      xpostblit = nullptr;
    }
    b.push_funcptr(xpostblit);

    // uint m_align
    b.push_uint(DtoAlignment(tc));

    if (isX86_64) {
      // TypeInfo m_arg1
      // TypeInfo m_arg2
      Type *t = sd->arg1type;
      for (unsigned i = 0; i < 2; i++) {
        if (t) {
          t = merge(t);
          b.push_typeinfo(t);
        } else {
          b.push_null(getTypeInfoType());
        }

        t = sd->arg2type;
      }
    }

    // immutable(void)* m_RTInfo
    // The cases where getRTInfo is null are not quite here, but the code is
    // modelled after what DMD does.
    if (sd->getRTInfo) {
      b.push(toConstElem(sd->getRTInfo, gIR));
    } else if (!tc->hasPointers()) {
      b.push_size_as_vp(0); // no pointers
    } else {
      b.push_size_as_vp(1); // has pointers
    }

    // finish
    b.finalize(gvar);
  }
示例#2
0
文件: typinf.cpp 项目: Philpax/ldc
    void visit(TypeInfoStructDeclaration *decl)
    {
        IF_LOG Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", decl->toChars());
        LOG_SCOPE;

        // make sure struct is resolved
        assert(decl->tinfo->ty == Tstruct);
        TypeStruct *tc = static_cast<TypeStruct *>(decl->tinfo);
        StructDeclaration *sd = tc->sym;

        // handle opaque structs
        if (!sd->members) {
            RTTIBuilder b(Type::typeinfostruct);
            b.finalize(getIrGlobal(decl));
            return;
        }

        // can't emit typeinfo for forward declarations
        if (sd->sizeok != SIZEOKdone)
        {
            sd->error("cannot emit TypeInfo for forward declaration");
            fatal();
        }

        DtoResolveStruct(sd);
        IrAggr* iraggr = getIrAggr(sd);

        RTTIBuilder b(Type::typeinfostruct);

        // char[] name
        b.push_string(sd->toPrettyChars());

        // void[] init
        // The protocol is to write a null pointer for zero-initialized arrays. The
        // length field is always needed for tsize().
        llvm::Constant *initPtr;
        if (tc->isZeroInit(Loc()))
            initPtr = getNullValue(getVoidPtrType());
        else
            initPtr = iraggr->getInitSymbol();
        b.push_void_array(getTypeStoreSize(DtoType(tc)), initPtr);

        // well use this module for all overload lookups

        // toHash
        FuncDeclaration* fd = sd->xhash;
        b.push_funcptr(fd);

        // opEquals
        fd = sd->xeq;
        b.push_funcptr(fd);

        // opCmp
        fd = sd->xcmp;
        b.push_funcptr(fd);

        // toString
        fd = search_toString(sd);
        b.push_funcptr(fd);

        // uint m_flags;
        unsigned hasptrs = tc->hasPointers() ? 1 : 0;
        b.push_uint(hasptrs);

        // On x86_64, class TypeInfo_Struct contains 2 additional fields
        // (m_arg1/m_arg2) which are used for the X86_64 System V ABI varargs
        // implementation. They are not present on any other cpu/os.
        assert((global.params.targetTriple.getArch() != llvm::Triple::x86_64 && Type::typeinfostruct->fields.dim == 11) ||
               (global.params.targetTriple.getArch() == llvm::Triple::x86_64 && Type::typeinfostruct->fields.dim == 13));

        //void function(void*)                    xdtor;
        b.push_funcptr(sd->dtor);

        //void function(void*)                    xpostblit;
        FuncDeclaration *xpostblit = sd->postblit;
        if (xpostblit && sd->postblit->storage_class & STCdisable)
            xpostblit = 0;
        b.push_funcptr(xpostblit);

        //uint m_align;
        b.push_uint(tc->alignsize());

        if (global.params.is64bit)
        {
            // TypeInfo m_arg1;
            // TypeInfo m_arg2;
            Type *t = sd->arg1type;
            for (unsigned i = 0; i < 2; i++)
            {
                if (t)
                {
                    t = t->merge();
                    b.push_typeinfo(t);
                }
                else
                    b.push_null(Type::dtypeinfo->type);

                t = sd->arg2type;
            }
        }

        // immutable(void)* m_RTInfo;
        // The cases where getRTInfo is null are not quite here, but the code is
        // modelled after what DMD does.
        if (sd->getRTInfo)
            b.push(toConstElem(sd->getRTInfo, gIR));
        else if (!tc->hasPointers())
            b.push_size_as_vp(0);       // no pointers
        else
            b.push_size_as_vp(1);       // has pointers

        // finish
        b.finalize(getIrGlobal(decl));
    }