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 visit(StructDeclaration *decl) override { IF_LOG Logger::println("StructDeclaration::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; } if (!(decl->members && decl->symtab)) { return; } DtoResolveStruct(decl); decl->ir->setDefined(); for (auto m : *decl->members) { m->accept(this); } // Skip __initZ and typeinfo for @compute device code. // TODO: support global variables and thus __initZ if (!irs->dcomputetarget) { // Define the __initZ symbol. IrAggr *ir = getIrAggr(decl); auto &initZ = ir->getInitSymbol(); auto initGlobal = llvm::cast<LLGlobalVariable>(initZ); initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit()); setLinkage(decl, initGlobal); // emit typeinfo DtoTypeInfoOf(decl->type, /*base=*/false); } // Emit __xopEquals/__xopCmp/__xtoHash. if (decl->xeq && decl->xeq != decl->xerreq) { decl->xeq->accept(this); } if (decl->xcmp && decl->xcmp != decl->xerrcmp) { decl->xcmp->accept(this); } if (decl->xhash) { decl->xhash->accept(this); } }
void visit(ClassDeclaration *decl) override { IF_LOG Logger::println("ClassDeclaration::codegen: '%s'", decl->toPrettyChars()); LOG_SCOPE assert(!irs->dcomputetarget); if (decl->ir->isDefined()) { return; } if (decl->type->ty == Terror) { error(decl->loc, "had semantic errors when compiling"); decl->ir->setDefined(); return; } if (decl->members && decl->symtab) { DtoResolveClass(decl); decl->ir->setDefined(); for (auto m : *decl->members) { m->accept(this); } IrAggr *ir = getIrAggr(decl); const auto lwc = DtoLinkage(decl); auto &initZ = ir->getInitSymbol(); auto initGlobal = llvm::cast<LLGlobalVariable>(initZ); initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit()); setLinkage(lwc, initGlobal); llvm::GlobalVariable *vtbl = ir->getVtblSymbol(); vtbl->setInitializer(ir->getVtblInit()); setLinkage(lwc, vtbl); llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); if (!isSpeculativeType(decl->type)) { classZ->setInitializer(ir->getClassInfoInit()); setLinkage(lwc, classZ); } } }
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 IrAggr assert(cd->ir.irAggr == NULL); IrAggr* irAggr = new IrAggr(cd); cd->ir.irAggr = irAggr; // 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 = irAggr->getClassInfoSymbol(); // emit the interfaceInfosZ symbol if necessary if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0) irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built // interface only emit typeinfo and classinfo if (cd->isInterfaceDeclaration()) { irAggr->initializeInterface(); } else { // emit the initZ symbol LLGlobalVariable* initZ = irAggr->getInitSymbol(); // emit the vtblZ symbol LLGlobalVariable* vtblZ = irAggr->getVtblSymbol(); // perform definition if (needs_def) { // set symbol initializers initZ->setInitializer(irAggr->getDefaultInit()); vtblZ->setInitializer(irAggr->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(irAggr->getClassInfoInit()); } }