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 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()))); }
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); } } }