Пример #1
0
// Put out instance of ModuleInfo for this Module
void Module::genmoduleinfo()
{
    // resolve ModuleInfo
    if (!moduleinfo)
    {
        error("object.d is missing the ModuleInfo struct");
        fatal();
    }
    // check for patch
    else
    {
        unsigned sizeof_ModuleInfo = 16 * Target::ptrsize;
        if (sizeof_ModuleInfo != moduleinfo->structsize)
        {
            error("object.d ModuleInfo class is incorrect");
            fatal();
        }
    }

    // use the RTTIBuilder
    RTTIBuilder b(moduleinfo);

    // some types
    LLType* moduleinfoTy = moduleinfo->type->irtype->getLLType();
    LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getLLType();

    // importedModules[]
    std::vector<LLConstant*> importInits;
    LLConstant* importedModules = 0;
    llvm::ArrayType* importedModulesTy = 0;
    for (size_t i = 0; i < aimports.dim; i++)
    {
        Module *m = static_cast<Module *>(aimports.data[i]);
        if (!m->needModuleInfo() || m == this)
            continue;

        // declare the imported module info
        std::string m_name("_D");
        m_name.append(m->mangle());
        m_name.append("12__ModuleInfoZ");
        llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name);
        if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name);
        importInits.push_back(m_gvar);
    }
    // has import array?
    if (!importInits.empty())
    {
        importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
        importedModules = LLConstantArray::get(importedModulesTy, importInits);
    }

    // localClasses[]
    LLConstant* localClasses = 0;
    llvm::ArrayType* localClassesTy = 0;
    ClassDeclarations aclasses;
    //printf("members->dim = %d\n", members->dim);
    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *member;

        member = static_cast<Dsymbol *>(members->data[i]);
        //printf("\tmember '%s'\n", member->toChars());
        member->addLocalClass(&aclasses);
    }
    // fill inits
    std::vector<LLConstant*> classInits;
    for (size_t i = 0; i < aclasses.dim; i++)
    {
        ClassDeclaration* cd = static_cast<ClassDeclaration*>(aclasses.data[i]);
        cd->codegen(Type::sir);

        if (cd->isInterfaceDeclaration())
        {
            Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
            continue;
        }
        else if (cd->sizeok != 1)
        {
            Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars());
            continue;
        }
        Logger::println("class: %s", cd->toPrettyChars());
        LLConstant *c = DtoBitCast(cd->ir.irAggr->getClassInfoSymbol(), classinfoTy);
        classInits.push_back(c);
    }
    // has class array?
    if (!classInits.empty())
    {
        localClassesTy = llvm::ArrayType::get(classinfoTy, classInits.size());
        localClasses = LLConstantArray::get(localClassesTy, classInits);
    }

    // These must match the values in druntime/src/object_.d
    #define MIstandalone      4
    #define MItlsctor         8
    #define MItlsdtor         0x10
    #define MIctor            0x20
    #define MIdtor            0x40
    #define MIxgetMembers     0x80
    #define MIictor           0x100
    #define MIunitTest        0x200
    #define MIimportedModules 0x400
    #define MIlocalClasses    0x800
    #define MInew             0x80000000   // it's the "new" layout

    llvm::Function* fsharedctor = build_module_shared_ctor();
    llvm::Function* fshareddtor = build_module_shared_dtor();
    llvm::Function* funittest = build_module_unittest();
    llvm::Function* fctor = build_module_ctor();
    llvm::Function* fdtor = build_module_dtor();

    unsigned flags = MInew;
    if (fctor)
        flags |= MItlsctor;
    if (fdtor)
        flags |= MItlsdtor;
    if (fsharedctor)
        flags |= MIctor;
    if (fshareddtor)
        flags |= MIdtor;
#if 0
    if (fgetmembers)
        flags |= MIxgetMembers;
    if (fictor)
        flags |= MIictor;
#endif
    if (funittest)
        flags |= MIunitTest;
    if (importedModules)
        flags |= MIimportedModules;
    if (localClasses)
        flags |= MIlocalClasses;

    if (!needmoduleinfo)
        flags |= MIstandalone;

    b.push_uint(flags); // flags
    b.push_uint(0);     // index

    if (fctor)
        b.push(fctor);
    if (fdtor)
        b.push(fdtor);
    if (fsharedctor)
        b.push(fsharedctor);
    if (fshareddtor)
        b.push(fshareddtor);
#if 0
    if (fgetmembers)
        b.push(fgetmembers);
    if (fictor)
        b.push(fictor);
#endif
    if (funittest)
        b.push(funittest);
    if (importedModules) {
        b.push_size(importInits.size());
        b.push(importedModules);
    }
    if (localClasses) {
        b.push_size(classInits.size());
        b.push(localClasses);
    }

    // Put out module name as a 0-terminated string.
    const char *name = toPrettyChars();
    const size_t len = strlen(name) + 1;
    llvm::IntegerType *it = llvm::IntegerType::getInt8Ty(gIR->context());
    llvm::ArrayType *at = llvm::ArrayType::get(it, len);
    b.push(toConstantArray(it, at, name, len, false));

    // create and set initializer
    b.finalize(moduleInfoType, moduleInfoSymbol());

    // build the modulereference and ctor for registering it
    LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSymbol());

    AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true);
}
Пример #2
0
llvm::GlobalVariable *genModuleInfo(Module *m) {
  // check declaration in object.d
  const auto moduleInfoType = getModuleInfoType();
  const auto moduleInfoDecl = Module::moduleinfo;

  // The "new-style" ModuleInfo records are variable-length, with the presence
  // of the various fields indicated by a certain flag bit. The base struct
  // should consist only of the _flags/_index fields (the latter of which is
  // unused).
  if (moduleInfoDecl->structsize != 4 + 4) {
    m->error("Unexpected size of struct `object.ModuleInfo`; "
             "druntime version does not match compiler (see -v)");
    fatal();
  }

  // First, figure out which fields are present and set the flags accordingly.
  unsigned flags = MInew;

  const auto fctor = buildModuleCtor(m);
  if (fctor) {
    flags |= MItlsctor;
  }

  const auto fdtor = buildModuleDtor(m);
  if (fdtor) {
    flags |= MItlsdtor;
  }

  const auto fsharedctor = buildModuleSharedCtor(m);
  if (fsharedctor) {
    flags |= MIctor;
  }

  const auto fshareddtor = buildModuleSharedDtor(m);
  if (fshareddtor) {
    flags |= MIdtor;
  }

#if 0
  if (fgetmembers)
    flags |= MIxgetMembers;
#endif

  const auto fictor = getIrModule(m)->coverageCtor;
  if (fictor)
    flags |= MIictor;

  const auto funittest = buildModuleUnittest(m);
  if (funittest) {
    flags |= MIunitTest;
  }

  size_t importedModulesCount;
  const auto importedModules = buildImportedModules(m, importedModulesCount);
  if (importedModules) {
    flags |= MIimportedModules;
  }

  size_t localClassesCount;
  const auto localClasses = buildLocalClasses(m, localClassesCount);
  if (localClasses) {
    flags |= MIlocalClasses;
  }

  if (!m->needmoduleinfo) {
    flags |= MIstandalone;
  }

  // Now, start building the initialiser for the ModuleInfo instance.
  RTTIBuilder b(moduleInfoType);

  b.push_uint(flags);
  b.push_uint(0); // index

  if (fctor) {
    b.push(fctor);
  }
  if (fdtor) {
    b.push(fdtor);
  }
  if (fsharedctor) {
    b.push(fsharedctor);
  }
  if (fshareddtor) {
    b.push(fshareddtor);
  }
#if 0
    if (fgetmembers)
        b.push(fgetmembers);
#endif
  if (fictor) {
    b.push(fictor);
  }
  if (funittest) {
    b.push(funittest);
  }
  if (importedModules) {
    b.push_size(importedModulesCount);
    b.push(importedModules);
  }
  if (localClasses) {
    b.push_size(localClassesCount);
    b.push(localClasses);
  }

  // Put out module name as a 0-terminated string.
  const char *name = m->toPrettyChars();
  const size_t len = strlen(name) + 1;
  const auto it = llvm::IntegerType::getInt8Ty(gIR->context());
  const auto at = llvm::ArrayType::get(it, len);
  b.push(toConstantArray(it, at, name, len, false));

  // Create a global symbol with the above initialiser.
  LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
  b.finalize(moduleInfoSym);
  setLinkage({LLGlobalValue::ExternalLinkage, supportsCOMDAT()}, moduleInfoSym);
  return moduleInfoSym;
}