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