void StructDeclaration::toObjFile(int multiobj) { //printf("StructDeclaration::toObjFile('%s')\n", toChars()); if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (multiobj && !hasStaticCtorOrDtor()) { obj_append(this); return; } // Anonymous structs/unions only exist as part of others, // do not output forward referenced structs's if (!isAnonymous() && members) { if (global.params.symdebug) toDebug(); type->getTypeInfo(NULL); // generate TypeInfo if (1) { // Generate static initializer toInitializer(); if (isInstantiated()) { sinit->Sclass = SCcomdat; } else { sinit->Sclass = SCglobal; } sinit->Sfl = FLdata; toDt(&sinit->Sdt); dt_optimize(sinit->Sdt); out_readonly(sinit); // put in read-only segment outdata(sinit); } // Put out the members for (size_t i = 0; i < members->dim; i++) { Dsymbol *member = (*members)[i]; /* There might be static ctors in the members, and they cannot * be put in separate obj files. */ member->toObjFile(multiobj); } if (xeq && xeq != xerreq) xeq->toObjFile(multiobj); if (xcmp && xcmp != xerrcmp) xcmp->toObjFile(multiobj); } }
void TypeInfoDeclaration::toObjFile(int multiobj) { Symbol *s; unsigned sz; Dsymbol *parent; //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); if (multiobj) { obj_append(this); return; } s = toSymbol(); sz = type->size(); parent = this->toParent(); s->Sclass = SCcomdat; s->Sfl = FLdata; toDt(&s->Sdt); dt_optimize(s->Sdt); // See if we can convert a comdat to a comdef, // which saves on exe file space. if (s->Sclass == SCcomdat && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) { s->Sclass = SCglobal; s->Sdt->dt = DT_common; } #if ELFOBJ || MACHOBJ // Burton if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) s->Sseg = UDATA; else s->Sseg = DATA; #endif outdata(s); if (isExport()) obj_export(s,0); }
Symbol* StructLiteralExp::toSymbol() { if (sym) return sym; TYPE *t = type_alloc(TYint); t->Tcount++; Symbol *s = symbol_calloc("internal"); s->Sclass = SCstatic; s->Sfl = FLextern; s->Sflags |= SFLnodebug; s->Stype = t; sym = s; dt_t *d = NULL; toDt(&d); s->Sdt = d; slist_add(s); outdata(s); return sym; }
void ClassDeclaration::toObjFile(int multiobj) { unsigned offset; Symbol *sinit; enum_SC scclass; //printf("ClassDeclaration::toObjFile('%s')\n", toChars()); if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (!members) return; if (multiobj && !hasStaticCtorOrDtor()) { obj_append(this); return; } if (global.params.symdebug) toDebug(); assert(!scope); // semantic() should have been run to completion scclass = SCglobal; if (isInstantiated()) scclass = SCcomdat; // Put out the members for (size_t i = 0; i < members->dim; i++) { Dsymbol *member = (*members)[i]; /* There might be static ctors in the members, and they cannot * be put in separate obj files. */ member->toObjFile(multiobj); } // Generate C symbols toSymbol(); toVtblSymbol(); sinit = toInitializer(); ////////////////////////////////////////////// // Generate static initializer sinit->Sclass = scclass; sinit->Sfl = FLdata; toDt(&sinit->Sdt); out_readonly(sinit); outdata(sinit); ////////////////////////////////////////////// // Put out the TypeInfo type->getTypeInfo(NULL); //type->vtinfo->toObjFile(multiobj); ////////////////////////////////////////////// // Put out the ClassInfo csym->Sclass = scclass; csym->Sfl = FLdata; /* The layout is: { void **vptr; monitor_t monitor; byte[] initializer; // static initialization data char[] name; // class name void *[] vtbl; Interface[] interfaces; ClassInfo *base; // base class void *destructor; void *invariant; // class invariant ClassFlags flags; void *deallocator; OffsetTypeInfo[] offTi; void *defaultConstructor; //const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function void *xgetRTInfo; //TypeInfo typeinfo; } */ dt_t *dt = NULL; unsigned classinfo_size = global.params.isLP64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size offset = classinfo_size; if (Type::typeinfoclass) { if (Type::typeinfoclass->structsize != classinfo_size) { #ifdef DEBUG printf("CLASSINFO_SIZE = x%x, Type::typeinfoclass->structsize = x%x\n", offset, Type::typeinfoclass->structsize); #endif error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch."); fatal(); } } if (Type::typeinfoclass) dtxoff(&dt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo else dtsize_t(&dt, 0); // BUG: should be an assert() dtsize_t(&dt, 0); // monitor // initializer[] assert(structsize >= 8 || (cpp && structsize >= 4)); dtsize_t(&dt, structsize); // size dtxoff(&dt, sinit, 0, TYnptr); // initializer // name[] const char *name = ident->toChars(); size_t namelen = strlen(name); if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0)) { name = toPrettyChars(); namelen = strlen(name); } dtsize_t(&dt, namelen); dtabytes(&dt, TYnptr, 0, namelen + 1, name); // vtbl[] dtsize_t(&dt, vtbl.dim); dtxoff(&dt, vtblsym, 0, TYnptr); // interfaces[] dtsize_t(&dt, vtblInterfaces->dim); if (vtblInterfaces->dim) dtxoff(&dt, csym, offset, TYnptr); // (*) else dtsize_t(&dt, 0); // base if (baseClass) dtxoff(&dt, baseClass->toSymbol(), 0, TYnptr); else dtsize_t(&dt, 0); // destructor if (dtor) dtxoff(&dt, dtor->toSymbol(), 0, TYnptr); else dtsize_t(&dt, 0); // invariant if (inv) dtxoff(&dt, inv->toSymbol(), 0, TYnptr); else dtsize_t(&dt, 0); // flags ClassFlags::Type flags = ClassFlags::hasOffTi; if (isCOMclass()) flags |= ClassFlags::isCOMclass; if (isCPPclass()) flags |= ClassFlags::isCPPclass; flags |= ClassFlags::hasGetMembers; flags |= ClassFlags::hasTypeInfo; if (ctor) flags |= ClassFlags::hasCtor; if (isabstract) flags |= ClassFlags::isAbstract; for (ClassDeclaration *cd = this; cd; cd = cd->baseClass) { if (cd->members) { for (size_t i = 0; i < cd->members->dim; i++) { Dsymbol *sm = (*cd->members)[i]; //printf("sm = %s %s\n", sm->kind(), sm->toChars()); if (sm->hasPointers()) goto L2; } } } flags |= ClassFlags::noPointers; L2: dtsize_t(&dt, flags); // deallocator if (aggDelete) dtxoff(&dt, aggDelete->toSymbol(), 0, TYnptr); else dtsize_t(&dt, 0); // offTi[] dtsize_t(&dt, 0); dtsize_t(&dt, 0); // null for now, fix later // defaultConstructor if (defaultCtor) dtxoff(&dt, defaultCtor->toSymbol(), 0, TYnptr); else dtsize_t(&dt, 0); // xgetRTInfo if (getRTInfo) getRTInfo->toDt(&dt); else if (flags & ClassFlags::noPointers) dtsize_t(&dt, 0); else dtsize_t(&dt, 1); //dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo ////////////////////////////////////////////// // Put out (*vtblInterfaces)[]. Must immediately follow csym, because // of the fixup (*) offset += vtblInterfaces->dim * (4 * Target::ptrsize); for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (*vtblInterfaces)[i]; ClassDeclaration *id = b->base; /* The layout is: * struct Interface * { * ClassInfo *interface; * void *[] vtbl; * size_t offset; * } */ // Fill in vtbl[] b->fillVtbl(this, &b->vtbl, 1); dtxoff(&dt, id->toSymbol(), 0, TYnptr); // ClassInfo // vtbl[] dtsize_t(&dt, id->vtbl.dim); dtxoff(&dt, csym, offset, TYnptr); dtsize_t(&dt, b->offset); // this offset offset += id->vtbl.dim * Target::ptrsize; } // Put out the (*vtblInterfaces)[].vtbl[] // This must be mirrored with ClassDeclaration::baseVtblOffset() //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars()); for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (*vtblInterfaces)[i]; ClassDeclaration *id = b->base; //printf(" interface[%d] is '%s'\n", i, id->toChars()); size_t j = 0; if (id->vtblOffset()) { // First entry is ClassInfo reference //dtxoff(&dt, id->toSymbol(), 0, TYnptr); // First entry is struct Interface reference dtxoff(&dt, csym, classinfo_size + i * (4 * Target::ptrsize), TYnptr); j = 1; } assert(id->vtbl.dim == b->vtbl.dim); for (; j < id->vtbl.dim; j++) { assert(j < b->vtbl.dim); #if 0 RootObject *o = b->vtbl[j]; if (o) { printf("o = %p\n", o); assert(o->dyncast() == DYNCAST_DSYMBOL); Dsymbol *s = (Dsymbol *)o; printf("s->kind() = '%s'\n", s->kind()); } #endif FuncDeclaration *fd = b->vtbl[j]; if (fd) dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr); else dtsize_t(&dt, 0); } } // Put out the overriding interface vtbl[]s. // This must be mirrored with ClassDeclaration::baseVtblOffset() //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset); ClassDeclaration *cd; FuncDeclarations bvtbl; for (cd = this->baseClass; cd; cd = cd->baseClass) { for (size_t k = 0; k < cd->vtblInterfaces->dim; k++) { BaseClass *bs = (*cd->vtblInterfaces)[k]; if (bs->fillVtbl(this, &bvtbl, 0)) { //printf("\toverriding vtbl[] for %s\n", bs->base->toChars()); ClassDeclaration *id = bs->base; size_t j = 0; if (id->vtblOffset()) { // First entry is ClassInfo reference //dtxoff(&dt, id->toSymbol(), 0, TYnptr); // First entry is struct Interface reference dtxoff(&dt, cd->toSymbol(), classinfo_size + k * (4 * Target::ptrsize), TYnptr); j = 1; } for (; j < id->vtbl.dim; j++) { FuncDeclaration *fd; assert(j < bvtbl.dim); fd = bvtbl[j]; if (fd) dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr); else dtsize_t(&dt, 0); } } } } csym->Sdt = dt; // ClassInfo cannot be const data, because we use the monitor on it outdata(csym); if (isExport()) objmod->export_symbol(csym,0); ////////////////////////////////////////////// // Put out the vtbl[] //printf("putting out %s.vtbl[]\n", toChars()); dt = NULL; if (vtblOffset()) dtxoff(&dt, csym, 0, TYnptr); // first entry is ClassInfo reference for (size_t i = vtblOffset(); i < vtbl.dim; i++) { FuncDeclaration *fd = vtbl[i]->isFuncDeclaration(); //printf("\tvtbl[%d] = %p\n", i, fd); if (fd && (fd->fbody || !isAbstract())) { // Ensure function has a return value (Bugzilla 4869) fd->functionSemantic(); Symbol *s = fd->toSymbol(); if (isFuncHidden(fd)) { /* fd is hidden from the view of this class. * If fd overlaps with any function in the vtbl[], then * issue 'hidden' error. */ for (size_t j = 1; j < vtbl.dim; j++) { if (j == i) continue; FuncDeclaration *fd2 = vtbl[j]->isFuncDeclaration(); if (!fd2->ident->equals(fd->ident)) continue; if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd)) { TypeFunction *tf = (TypeFunction *)fd->type; if (tf->ty == Tfunction) deprecation("use of %s%s hidden by %s is deprecated. Use 'alias %s.%s %s;' to introduce base class overload set.", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars(), fd->parent->toChars(), fd->toChars(), fd->toChars()); else deprecation("use of %s hidden by %s is deprecated", fd->toPrettyChars(), toChars()); s = rtlsym[RTLSYM_DHIDDENFUNC]; break; } } } dtxoff(&dt, s, 0, TYnptr); } else dtsize_t(&dt, 0); } vtblsym->Sdt = dt; vtblsym->Sclass = scclass; vtblsym->Sfl = FLdata; out_readonly(vtblsym); outdata(vtblsym); if (isExport()) objmod->export_symbol(vtblsym,0); }