void DtoDeclareTypeInfo(TypeInfoDeclaration* tid) { DtoResolveTypeInfo(tid); if (tid->ir.declared) return; tid->ir.declared = true; Logger::println("DtoDeclareTypeInfo(%s)", tid->toChars()); LOG_SCOPE; if (Logger::enabled()) { std::string mangled(tid->mangle()); Logger::println("type = '%s'", tid->tinfo->toChars()); Logger::println("typeinfo mangle: %s", mangled.c_str()); } IrGlobal* irg = tid->ir.irGlobal; assert(irg->value != NULL); // this is a declaration of a builtin __initZ var if (tid->tinfo->builtinTypeInfo()) { LLGlobalVariable* g = isaGlobalVar(irg->value); g->setLinkage(llvm::GlobalValue::ExternalLinkage); return; } // define custom typedef tid->llvmDefine(); }
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name) { LLGlobalVariable* gv = target->getNamedGlobal(name); if (gv) { return gv; } if (noruntime) { error("No implicit runtime calls allowed with -noruntime option enabled"); fatal(); } if (!M) { LLVM_D_InitRuntime(); } LLGlobalVariable* g = M->getNamedGlobal(name); if (!g) { error("Runtime global '%s' was not found", name); fatal(); //return NULL; } LLPointerType* t = g->getType(); return new LLGlobalVariable(*target, t->getElementType(), g->isConstant(), g->getLinkage(), NULL, g->getName()); }
void DtoResolveStruct(StructDeclaration* sd) { // Make sure to resolve each struct type exactly once. if (sd->ir.resolved) return; sd->ir.resolved = true; Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(sd->type); // if it's a forward declaration, all bets are off. The type should be enough if (sd->sizeok != 1) return; // create the IrAggr IrAggr* irstruct = new IrAggr(sd); sd->ir.irStruct = irstruct; // Set up our field metadata. for (ArrayIter<VarDeclaration> it(sd->fields); !it.done(); it.next()) { VarDeclaration* vd = it.get(); assert(!vd->ir.irField); (void)new IrField(vd); } // perform definition bool emitGlobalData = mustDefineSymbol(sd); if (emitGlobalData) { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // set initZ initializer initZ->setInitializer(irstruct->getDefaultInit()); } // emit members if (sd->members) { for (ArrayIter<Dsymbol> it(sd->members); !it.done(); it.next()) { it.get()->codegen(Type::sir); } } if (emitGlobalData) { // emit typeinfo DtoTypeInfoOf(sd->type); } }
void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* mangle_sym) { std::string initname(mangle_sym->mangle()); initname.append(".rtti.voidarr.data"); LLGlobalVariable* G = new llvm::GlobalVariable( *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); push_void_array(getTypePaddedSize(CI->getType()), G); }
void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) { IF_LOG Logger::println("TypeInfoDeclaration::codegen(%s)", decl->toPrettyChars()); LOG_SCOPE; if (decl->ir.isDefined()) { return; } decl->ir.setDefined(); std::string mangled(mangle(decl)); IF_LOG { Logger::println("type = '%s'", decl->tinfo->toChars()); Logger::println("typeinfo mangle: %s", mangled.c_str()); } IrGlobal *irg = getIrGlobal(decl, true); irg->value = gIR->module.getGlobalVariable(mangled); if (irg->value) { irg->type = irg->value->getType()->getContainedType(0); assert(irg->type->isStructTy()); } else { if (builtinTypeInfo( decl->tinfo)) { // this is a declaration of a builtin __initZ var irg->type = Type::dtypeinfo->type->ctype->isClass()->getMemoryLLType(); } else { irg->type = LLStructType::create(gIR->context(), decl->toPrettyChars()); } irg->value = new llvm::GlobalVariable(gIR->module, irg->type, true, llvm::GlobalValue::ExternalLinkage, nullptr, mangled); } emitTypeMetadata(decl); // this is a declaration of a builtin __initZ var if (builtinTypeInfo(decl->tinfo)) { LLGlobalVariable *g = isaGlobalVar(irg->value); g->setLinkage(llvm::GlobalValue::ExternalLinkage); return; } // define custom typedef LLVMDefineVisitor v; decl->accept(&v); }
void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, Dsymbol * mangle_sym) { std::string tmpStr(valtype->arrayOf()->toChars()); tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), '[' ), tmpStr.end() ); tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), ']' ), tmpStr.end() ); tmpStr.append("arr"); std::string initname(mangle_sym?mangle_sym->mangle():".ldc"); initname.append(".rtti."); initname.append(tmpStr); initname.append(".data"); LLGlobalVariable* G = new llvm::GlobalVariable( *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo()))); }
llvm::GlobalVariable *getRuntimeGlobal(Loc &loc, llvm::Module &target, const char *name) { LLGlobalVariable *gv = target.getNamedGlobal(name); if (gv) { return gv; } checkForImplicitGCCall(loc, name); if (!M) { initRuntime(); } LLGlobalVariable *g = M->getNamedGlobal(name); if (!g) { error(loc, "Runtime global '%s' was not found", name); fatal(); // return NULL; } LLPointerType *t = g->getType(); return getOrCreateGlobal(loc, target, t->getElementType(), g->isConstant(), g->getLinkage(), nullptr, g->getName()); }
void visit(VarDeclaration *decl) override { IF_LOG Logger::println("VarDeclaration::codegen(): '%s'", decl->toPrettyChars()); LOG_SCOPE; if (decl->ir->isDefined()) { return; } if (decl->type->ty == Terror) { error(decl->loc, "had semantic errors when compiling"); decl->ir->setDefined(); return; } DtoResolveVariable(decl); decl->ir->setDefined(); // just forward aliases if (decl->aliassym) { Logger::println("alias sym"); decl->toAlias()->accept(this); return; } // global variable if (decl->isDataseg()) { Logger::println("data segment"); assert(!(decl->storage_class & STCmanifest) && "manifest constant being codegen'd!"); assert(!irs->dcomputetarget); IrGlobal *irGlobal = getIrGlobal(decl); LLGlobalVariable *gvar = llvm::cast<LLGlobalVariable>(irGlobal->value); assert(gvar && "DtoResolveVariable should have created value"); if (global.params.vtls && gvar->isThreadLocal() && !(decl->storage_class & STCtemp)) { const char *p = decl->loc.toChars(); fprintf(global.stdmsg, "%s: %s is thread local\n", p, decl->toChars()); } // Check if we are defining or just declaring the global in this module. // If we reach here during codegen of an available_externally function, // new variable declarations should stay external and therefore must not // have an initializer. if (!(decl->storage_class & STCextern) && !decl->inNonRoot()) { // Build the initializer. Might use irGlobal->value! LLConstant *initVal = DtoConstInitializer(decl->loc, decl->type, decl->_init); // Cache it. assert(!irGlobal->constInit); irGlobal->constInit = initVal; // Set the initializer, swapping out the variable if the types do not // match. irGlobal->value = irs->setGlobalVarInitializer(gvar, initVal); // Finalize linkage & DLL storage class. const auto lwc = DtoLinkage(decl); setLinkage(lwc, gvar); if (gvar->hasDLLImportStorageClass()) { gvar->setDLLStorageClass(LLGlobalValue::DLLExportStorageClass); } // Also set up the debug info. irs->DBuilder.EmitGlobalVariable(gvar, decl); } // If this global is used from a naked function, we need to create an // artificial "use" for it, or it could be removed by the optimizer if // the only reference to it is in inline asm. if (irGlobal->nakedUse) { irs->usedArray.push_back(gvar); } IF_LOG Logger::cout() << *gvar << '\n'; } }
void VarDeclaration::codegen(Ir* p) { Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; if (type->ty == Terror) { error("had semantic errors when compiling"); return; } // just forward aliases if (aliassym) { Logger::println("alias sym"); toAlias()->codegen(p); return; } // output the parent aggregate first if (AggregateDeclaration* ad = isMember()) ad->codegen(p); // global variable // taken from dmd2/structs if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init)) { Logger::println("data segment"); #if 0 // TODO: assert(!(storage_class & STCmanifest) && "manifest constant being codegen'd!"); #endif // don't duplicate work if (this->ir.resolved) return; this->ir.resolved = true; this->ir.declared = true; this->ir.irGlobal = new IrGlobal(this); Logger::println("parent: %s (%s)", parent->toChars(), parent->kind()); // not sure why this is only needed for d2 bool _isconst = isConst() && init; Logger::println("Creating global variable"); assert(!ir.initialized); ir.initialized = gIR->dmodule; std::string _name(mangle()); LLType *_type = DtoConstInitializerType(type, init); // create the global variable #if LDC_LLVM_VER >= 302 // FIXME: clang uses a command line option for the thread model LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, _type, _isconst, DtoLinkage(this), NULL, _name, 0, isThreadlocal() ? LLGlobalVariable::GeneralDynamicTLSModel : LLGlobalVariable::NotThreadLocal); #else LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, _type, _isconst, DtoLinkage(this), NULL, _name, 0, isThreadlocal()); #endif this->ir.irGlobal->value = gvar; // Set the alignment (it is important not to use type->alignsize because // VarDeclarations can have an align() attribute independent of the type // as well). if (alignment != STRUCTALIGN_DEFAULT) gvar->setAlignment(alignment); if (Logger::enabled()) Logger::cout() << *gvar << '\n'; // if this global is used from a nested function, this is necessary or // optimization could potentially remove the global (if it's the only use) if (nakedUse) gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType())); // assign the initializer if (!(storage_class & STCextern) && mustDefineSymbol(this)) { if (Logger::enabled()) { Logger::println("setting initializer"); Logger::cout() << "global: " << *gvar << '\n'; #if 0 Logger::cout() << "init: " << *initVal << '\n'; #endif } // build the initializer LLConstant *initVal = DtoConstInitializer(loc, type, init); // set the initializer assert(!ir.irGlobal->constInit); ir.irGlobal->constInit = initVal; gvar->setInitializer(initVal); // do debug info DtoDwarfGlobalVariable(gvar, this); } } }
void DtoResolveStruct(StructDeclaration* sd) { // don't do anything if already been here if (sd->ir.resolved) return; // make sure above works :P sd->ir.resolved = true; // log what we're doing Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(sd->type); // if it's a forward declaration, all bets are off. The type should be enough if (sd->sizeok != 1) return; // create the IrStruct IrStruct* irstruct = new IrStruct(sd); sd->ir.irStruct = irstruct; // make sure all fields really get their ir field ArrayIter<VarDeclaration> it(sd->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); if (vd->ir.irField == NULL) { new IrField(vd); } else { IF_LOG Logger::println("struct field already exists!!!"); } } // perform definition bool needs_def = mustDefineSymbol(sd); if (needs_def) { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // set initZ initializer initZ->setInitializer(irstruct->getDefaultInit()); } // emit members if (sd->members) { ArrayIter<Dsymbol> it(*sd->members); while (!it.done()) { Dsymbol* member = it.get(); if (member) member->codegen(Type::sir); it.next(); } } if (needs_def) { // emit typeinfo DtoTypeInfoOf(sd->type); } }
void DtoResolveClass(ClassDeclaration* cd) { // make sure the base classes are processed first ArrayIter<BaseClass> base_iter(cd->baseclasses); while (base_iter.more()) { BaseClass* bc = base_iter.get(); if (bc) { bc->base->codegen(Type::sir); } base_iter.next(); } if (cd->ir.resolved) return; cd->ir.resolved = true; Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); LOG_SCOPE; // make sure type exists DtoType(cd->type); // create IrStruct assert(cd->ir.irStruct == NULL); IrStruct* irstruct = new IrStruct(cd); cd->ir.irStruct = irstruct; // make sure all fields really get their ir field ArrayIter<VarDeclaration> it(cd->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); if (vd->ir.irField == NULL) { new IrField(vd); } else { IF_LOG Logger::println("class field already exists!!!"); } } bool needs_def = mustDefineSymbol(cd); // emit the ClassZ symbol LLGlobalVariable* ClassZ = irstruct->getClassInfoSymbol(); // emit the interfaceInfosZ symbol if necessary if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0) irstruct->getInterfaceArraySymbol(); // initializer is applied when it's built // interface only emit typeinfo and classinfo if (cd->isInterfaceDeclaration()) { irstruct->initializeInterface(); } else { // emit the initZ symbol LLGlobalVariable* initZ = irstruct->getInitSymbol(); // emit the vtblZ symbol LLGlobalVariable* vtblZ = irstruct->getVtblSymbol(); // perform definition if (needs_def) { // set symbol initializers initZ->setInitializer(irstruct->getDefaultInit()); vtblZ->setInitializer(irstruct->getVtblInit()); } } // emit members if (cd->members) { ArrayIter<Dsymbol> it(*cd->members); while (!it.done()) { Dsymbol* member = it.get(); if (member) member->codegen(Type::sir); it.next(); } } if (needs_def) { // emit typeinfo DtoTypeInfoOf(cd->type); // define classinfo ClassZ->setInitializer(irstruct->getClassInfoInit()); } }
// 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 { // The base struct should consist only of _flags/_index. if (moduleinfo->structsize != 4 + 4) { error("object.d ModuleInfo class is incorrect"); fatal(); } } // use the RTTIBuilder RTTIBuilder b(moduleinfo); // some types LLType* moduleinfoTy = moduleinfo->type->irtype->getLLType(); LLType* classinfoTy = Type::typeinfoclass->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 = aclasses[i]; DtoResolveClass(cd); if (cd->isInterfaceDeclaration()) { IF_LOG Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars()); continue; } else if (cd->sizeok != SIZEOKdone) { IF_LOG Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars()); continue; } IF_LOG Logger::println("class: %s", cd->toPrettyChars()); LLConstant *c = DtoBitCast(getIrAggr(cd)->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 LLGlobalVariable *moduleInfoSym = moduleInfoSymbol(); b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym); moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage); if (global.params.isLinux) { build_dso_registry_calls(moduleInfoSym); } else { // build the modulereference and ctor for registering it LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym); AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true); } }