void TypeInfoTupleDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars()); dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface dtdword(pdt, 0); // monitor assert(tinfo->ty == Ttuple); TypeTuple *tu = (TypeTuple *)tinfo; size_t dim = tu->arguments->dim; dtdword(pdt, dim); // elements.length dt_t *d = NULL; for (size_t i = 0; i < dim; i++) { Parameter *arg = (Parameter *)tu->arguments->data[i]; Expression *e = arg->type->getTypeInfo(NULL); e = e->optimize(WANTvalue); e->toDt(&d); } Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); dtxoff(pdt, s, 0, TYnptr); // elements.ptr }
void nteh_gentables() { symbol *s = s_table; symbol_debug(s); #if MARS //except_fillInEHTable(s); #else /* NTEH table for C. * The table consists of triples: * parent index * filter address * handler address */ unsigned fsize = 4; // target size of function pointer dt_t **pdt = &s->Sdt; int sz = 0; // size so far for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { dt_t *dt; block *bhandler; pdt = dtdword(pdt,b->Blast_index); // parent index // If try-finally if (list_nitems(b->Bsucc) == 2) { pdt = dtdword(pdt,0); // filter address bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); } else // try-except { bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_filter); pdt = dtcoff(pdt,bhandler->Boffset); // filter address bhandler = list_block(list_next(list_next(b->Bsucc))); assert(bhandler->BC == BC_except); } pdt = dtcoff(pdt,bhandler->Boffset); // handler address sz += 4 + fsize * 2; } } assert(sz != 0); #endif outdata(s); // output the scope table #if MARS nteh_framehandler(s); #endif s_table = NULL; }
void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStaticArrayDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray dtdword(pdt, 0); // monitor assert(tinfo->ty == Tsarray); TypeSArray *tc = (TypeSArray *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type dtdword(pdt, tc->dim->toInteger()); // length }
Symbol *objc_getImageInfo() { assert(!objc_simageInfo); // only allow once per object file objc_hasSymbols = true; dt_t *dt = NULL; dtdword(&dt, 0); // version dtdword(&dt, 0); // flags objc_simageInfo = symbol_name("L_OBJC_IMAGE_INFO", SCstatic, type_allocn(TYarray, tschar)); objc_simageInfo->Sdt = dt; objc_simageInfo->Sseg = objc_getSegment(SEGimage_info); outdata(objc_simageInfo); return objc_simageInfo; }
elem *Module::toEfilename() { elem *efilename; if (!sfilename) { dt_t *dt = NULL; char *id; int len; id = srcfile->toChars(); len = strlen(id); dtdword(&dt, len); dtabytes(&dt,TYnptr, 0, len + 1, id); sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); sfilename->Sdt = dt; sfilename->Sfl = FLdata; #if ELFOBJ sfilename->Sseg = CDATA; #endif #if MACHOBJ // Because of PIC and CDATA being in the _TEXT segment, cannot // have pointers in CDATA sfilename->Sseg = DATA; #endif outdata(sfilename); } efilename = el_var(sfilename); return efilename; }
void TypeInfoInvariantDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfoinvariant->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Invariant dtdword(pdt, 0); // monitor Type *tm = tinfo->mutableOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); }
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef dtdword(pdt, 0); // monitor assert(tinfo->ty == Ttypedef); TypeTypedef *tc = (TypeTypedef *)tinfo; TypedefDeclaration *sd = tc->sym; //printf("basetype = %s\n", sd->basetype->toChars()); /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ sd->basetype = sd->basetype->merge(); sd->basetype->getTypeInfo(NULL); // generate vtinfo assert(sd->basetype->vtinfo); dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; if (tinfo->isZeroInit() || !sd->init) { // 0 initializer, or the same as the base type dtdword(pdt, 0); // init.length dtdword(pdt, 0); // init.ptr } else { dtdword(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr } }
void ClassDeclaration::toDt(dt_t **pdt) { //printf("ClassDeclaration::toDt(this = '%s')\n", toChars()); // Put in first two members, the vtbl[] and the monitor dtxoff(pdt, toVtblSymbol(), 0, TYnptr); dtdword(pdt, 0); // monitor // Put in the rest toDt2(pdt, this); //printf("-ClassDeclaration::toDt(this = '%s')\n", toChars()); }
void TypeInfoPointerDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoPointerDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Pointer dtdword(pdt, 0); // monitor assert(tinfo->ty == Tpointer); TypePointer *tc = (TypePointer *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for type being pointed to }
void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoFunctionDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function dtdword(pdt, 0); // monitor assert(tinfo->ty == Tfunction); TypeFunction *tc = (TypeFunction *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for function return value }
void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoDelegateDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate dtdword(pdt, 0); // monitor assert(tinfo->ty == Tdelegate); TypeDelegate *tc = (TypeDelegate *)tinfo; tc->next->nextOf()->getTypeInfo(NULL); dtxoff(pdt, tc->next->nextOf()->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for delegate return value }
void TypeInfoArrayDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoArrayDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Array dtdword(pdt, 0); // monitor assert(tinfo->ty == Tarray); TypeDArray *tc = (TypeDArray *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type }
void TypeInfoSharedDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfoshared->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Shared dtdword(pdt, 0); // monitor Type *tm; if (tinfo->isConst()) // it was 'shared const' tm = tinfo->constOf(); else // it was just 'shared' tm = tinfo->mutableOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); }
void TypeInfoEnumDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoEnumDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum dtdword(pdt, 0); // monitor assert(tinfo->ty == Tenum); TypeEnum *tc = (TypeEnum *)tinfo; EnumDeclaration *sd = tc->sym; /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ sd->memtype->getTypeInfo(NULL); dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; if (!sd->defaultval || tinfo->isZeroInit()) { // 0 initializer, or the same as the base type dtdword(pdt, 0); // init.length dtdword(pdt, 0); // init.ptr } else { dtdword(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr } }
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars()); dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface dtdword(pdt, 0); // monitor assert(tinfo->ty == Tclass); TypeClass *tc = (TypeClass *)tinfo; Symbol *s; if (!tc->sym->vclassinfo) tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); s = tc->sym->vclassinfo->toSymbol(); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); Type *tn = tb->nextOf()->toBasetype(); Array dts; unsigned size; unsigned length; unsigned i; dt_t *dt; dt_t *d; dt_t **pdtend; //printf("\tdim = %d\n", dim); dts.setDim(dim); dts.zero(); size = tn->size(); length = 0; for (i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = (Expression *)index.data[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = (Initializer *)value.data[i]; dt = val->toDt(); if (dts.data[length]) error(loc, "duplicate initializations for index %d", length); dts.data[length] = (void *)dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } d = NULL; pdtend = &d; for (i = 0; i < dim; i++) { dt = (dt_t *)dts.data[i]; if (dt) pdtend = dtcat(pdtend, dt); else { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { if (edefault->isBool(FALSE)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (i = dim; i < tadim; i++) { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } } else if (dim > tadim) { #ifdef DEBUG printf("1: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; } case Tpointer: case Tarray: // Create symbol, and then refer to it Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtdword(&d, dim); dtxoff(&d, s, 0, TYnptr); break; default: assert(0); } return d; }
void except_fillInEHTable(symbol *s) { unsigned fsize = NPTRSIZE; // target size of function pointer dt_t **pdt = &s->Sdt; /* void* pointer to start of function unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] (Linux) Guard guard[]; catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ /* Be careful of this, as we need the sizeof Guard on the target, not * in the compiler. */ #if OUREH #define GUARD_SIZE (I64 ? 3*8 : 5*4) // sizeof(Guard) #else #define GUARD_SIZE (sizeof(Guard)) #endif int sz = 0; // Address of start of function symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP long spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset int guarddim = 0; // max dimension of guard[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); } #if OUREH pdt = dtsize_t(pdt,guarddim); sz += NPTRSIZE; #endif unsigned catchoffset = sz + guarddim * GUARD_SIZE; // Generate guard[] int i = 0; for (block *b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * GUARD_SIZE; pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; int nsucc = list_nitems(b->Bsucc); #if OUREH //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset)); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset unsigned endoffset; for (block *bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index); pdt = dtdword(pdt,endoffset); // offset past end of guarded block #endif pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { pdt = dtdword(pdt,catchoffset); pdt = dtsize_t(pdt,0); // no finally handler catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset block *bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); #if OUREH pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr); // finally handler address #else pdt = dtcoff(pdt,bhandler->Boffset); // finally handler address #endif } sz += GUARD_SIZE; } } // Generate catch[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { block *bhandler; int nsucc; if (b->jcatchvar) // if try-catch { list_t bl; nsucc = list_nitems(b->Bsucc); pdt = dtsize_t(pdt,nsucc - 1); // # of catch blocks sz += NPTRSIZE; for (bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset #if OUREH pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr); // catch handler address #else pdt = dtcoff(pdt,bcatch->Boffset); // catch handler address #endif sz += 3 * NPTRSIZE; } } } } assert(sz != 0); }
void genModuleInfo(Module *m) { //printf("Module::genmoduleinfo() %s\n", m->toChars()); if (!Module::moduleinfo) { ObjectNotFound(Id::ModuleInfo); } Symbol *msym = toSymbol(m); ////////////////////////////////////////////// m->csym->Sclass = SCglobal; m->csym->Sfl = FLdata; dt_t *dt = NULL; ClassDeclarations aclasses; //printf("members->dim = %d\n", members->dim); for (size_t i = 0; i < m->members->dim; i++) { Dsymbol *member = (*m->members)[i]; //printf("\tmember '%s'\n", member->toChars()); member->addLocalClass(&aclasses); } // importedModules[] size_t aimports_dim = m->aimports.dim; for (size_t i = 0; i < m->aimports.dim; i++) { Module *mod = m->aimports[i]; if (!mod->needmoduleinfo) aimports_dim--; } FuncDeclaration *sgetmembers = m->findGetMembers(); // These must match the values in druntime/src/object_.d #define MIstandalone 0x4 #define MItlsctor 0x8 #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 MIname 0x1000 unsigned flags = 0; if (!m->needmoduleinfo) flags |= MIstandalone; if (m->sctor) flags |= MItlsctor; if (m->sdtor) flags |= MItlsdtor; if (m->ssharedctor) flags |= MIctor; if (m->sshareddtor) flags |= MIdtor; if (sgetmembers) flags |= MIxgetMembers; if (m->sictor) flags |= MIictor; if (m->stest) flags |= MIunitTest; if (aimports_dim) flags |= MIimportedModules; if (aclasses.dim) flags |= MIlocalClasses; flags |= MIname; dtdword(&dt, flags); // _flags dtdword(&dt, 0); // _index if (flags & MItlsctor) dtxoff(&dt, m->sctor, 0, TYnptr); if (flags & MItlsdtor) dtxoff(&dt, m->sdtor, 0, TYnptr); if (flags & MIctor) dtxoff(&dt, m->ssharedctor, 0, TYnptr); if (flags & MIdtor) dtxoff(&dt, m->sshareddtor, 0, TYnptr); if (flags & MIxgetMembers) dtxoff(&dt, toSymbol(sgetmembers), 0, TYnptr); if (flags & MIictor) dtxoff(&dt, m->sictor, 0, TYnptr); if (flags & MIunitTest) dtxoff(&dt, m->stest, 0, TYnptr); if (flags & MIimportedModules) { dtsize_t(&dt, aimports_dim); for (size_t i = 0; i < m->aimports.dim; i++) { Module *mod = m->aimports[i]; if (!mod->needmoduleinfo) continue; Symbol *s = toSymbol(mod); /* Weak references don't pull objects in from the library, * they resolve to 0 if not pulled in by something else. * Don't pull in a module just because it was imported. */ s->Sflags |= SFLweak; dtxoff(&dt, s, 0, TYnptr); } } if (flags & MIlocalClasses) { dtsize_t(&dt, aclasses.dim); for (size_t i = 0; i < aclasses.dim; i++) { ClassDeclaration *cd = aclasses[i]; dtxoff(&dt, toSymbol(cd), 0, TYnptr); } } if (flags & MIname) { // Put out module name as a 0-terminated string, to save bytes m->nameoffset = dt_size(dt); const char *name = m->toPrettyChars(); m->namelen = strlen(name); dtnbytes(&dt, m->namelen + 1, name); //printf("nameoffset = x%x\n", nameoffset); } objc_Module_genmoduleinfo_classes(); m->csym->Sdt = dt; out_readonly(m->csym); outdata(m->csym); ////////////////////////////////////////////// objmod->moduleinfo(msym); }
void except_fillInEHTable(symbol *s) { unsigned fsize = NPTRSIZE; // target size of function pointer dt_t **pdt = &s->Sdt; /* void* pointer to start of function (Windows) unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] (Linux) Guard guard[]; // sorted such that the enclosing guarded sections come first catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ /* Be careful of this, as we need the sizeof Guard on the target, not * in the compiler. */ unsigned GUARD_SIZE; if (config.ehmethod == EH_DM) GUARD_SIZE = (I64 ? 3*8 : 5*4); else if (config.ehmethod == EH_WIN32) GUARD_SIZE = 3*4; else assert(0); int sz = 0; // Address of start of function if (config.ehmethod == EH_WIN32) { symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; } //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP long spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset int guarddim = 0; // max dimension of guard[] int ndctors = 0; // number of ESCdctor's for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); if (usednteh & EHcleanup) for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCddtor)) ndctors++; } } //printf("guarddim = %d, ndctors = %d\n", guarddim, ndctors); if (config.ehmethod == EH_DM) { pdt = dtsize_t(pdt,guarddim + ndctors); sz += NPTRSIZE; } unsigned catchoffset = sz + (guarddim + ndctors) * GUARD_SIZE; // Generate guard[] int i = 0; for (block *b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * GUARD_SIZE; pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; int nsucc = b->numSucc(); if (config.ehmethod == EH_DM) { //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset)); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset unsigned endoffset; for (block *bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index); pdt = dtdword(pdt,endoffset); // offset past end of guarded block } pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { assert(catchoffset); pdt = dtdword(pdt,catchoffset); pdt = dtsize_t(pdt,0); // no finally handler catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset block *bhandler = b->nthSucc(1); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = bhandler->nthSucc(0); // finally handler address if (config.ehmethod == EH_DM) { assert(bhandler->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bhandler->Boffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,bhandler->Boffset); } sz += GUARD_SIZE; } } /* Append to guard[] the guard blocks for temporaries that are created and destroyed * within a single expression. These are marked by the special instruction pairs * (ESCAPE | ESCdctor) and (ESCAPE | ESCddtor). */ if (usednteh & EHcleanup) { #define STACKINC 16 int stackbuf[STACKINC]; int *stack = stackbuf; int stackmax = STACKINC; int scopeindex = guarddim; for (block *b = startblock; b; b = b->Bnext) { /* Set up stack of scope indices */ stack[0] = b->Btry ? b->Btry->Bscope_index : -1; int stacki = 1; unsigned boffset = b->Boffset; for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCdctor)) { code *c2 = code_next(c); if (config.flags2 & CFG2seh) nteh_patchindex(c2, scopeindex); if (config.ehmethod == EH_DM) pdt = dtdword(pdt,boffset - startblock->Boffset); // guard offset // Find corresponding ddtor instruction int n = 0; unsigned eoffset = boffset; unsigned foffset; for (; 1; c2 = code_next(c2)) { // Bugzilla 13720: optimizer might elide the corresponding ddtor if (!c2) goto Lnodtor; if (c2->Iop == (ESCAPE | ESCddtor)) { if (n) n--; else { foffset = eoffset; code *cf = code_next(c2); if (config.flags2 & CFG2seh) { nteh_patchindex(cf, stack[stacki - 1]); foffset += calccodsize(cf); cf = code_next(cf); } foffset += calccodsize(cf); while (!cf->isJumpOP()) { cf = code_next(cf); foffset += calccodsize(cf); } // issue 9438 //cf = code_next(cf); //foffset += calccodsize(cf); if (config.ehmethod == EH_DM) pdt = dtdword(pdt,eoffset - startblock->Boffset); // guard offset break; } } else if (c2->Iop == (ESCAPE | ESCdctor)) { n++; } else eoffset += calccodsize(c2); } //printf("boffset = %x, eoffset = %x, foffset = %x\n", boffset, eoffset, foffset); pdt = dtdword(pdt,stack[stacki - 1]); // parent index pdt = dtdword(pdt,0); // no catch offset if (config.ehmethod == EH_DM) { assert(foffset > startblock->Boffset); pdt = dtsize_t(pdt,foffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,foffset); // finally handler address if (stacki == stackmax) { // stack[] is out of space; enlarge it int *pi = (int *)malloc((stackmax + STACKINC) * sizeof(int)); assert(pi); memcpy(pi, stack, stackmax * sizeof(int)); if (stack != stackbuf) free(stack); stack = pi; stackmax += STACKINC; } stack[stacki++] = scopeindex; ++scopeindex; sz += GUARD_SIZE; } else if (c->Iop == (ESCAPE | ESCddtor)) { stacki--; assert(stacki != 0); } Lnodtor: boffset += calccodsize(c); } } if (stack != stackbuf) free(stack); } // Generate catch[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->jcatchvar) // if try-catch { int nsucc = b->numSucc(); pdt = dtsize_t(pdt,nsucc - 1); // # of catch blocks sz += NPTRSIZE; for (int i = 1; i < nsucc; ++i) { block *bcatch = b->nthSucc(i); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYnptr); pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset // catch handler address if (config.ehmethod == EH_DM) { assert(bcatch->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bcatch->Boffset - startblock->Boffset); // catch handler offset } else pdt = dtcoff(pdt,bcatch->Boffset); sz += 3 * NPTRSIZE; } } } assert(sz != 0); }
symbol *except_gentables() { //printf("except_gentables()\n"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS symbol *s; int sz; // size so far dt_t **pdt; unsigned fsize; // target size of function pointer long spoff; block *b; int guarddim; int i; // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. assert(!usedalloca); s = symbol_generate(SCstatic,tsint); s->Sseg = UNKNOWN; symbol_keep(s); symbol_debug(s); fsize = 4; pdt = &s->Sdt; sz = 0; /* void* pointer to start of function unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] { unsigned offset; // offset of start of guarded section unsigned endoffset; // ending offset of guarded section int last_index; // previous index (enclosing guarded section) unsigned catchoffset; // offset to catch block from symbol void *finally; // finally code to execute } guard[]; catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ #define GUARD_SIZE 5 // number of 4 byte values in one guard sz = 0; // Address of start of function symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset guarddim = 0; // max dimension of guard[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); } pdt = dtdword(pdt,guarddim); sz += 4; unsigned catchoffset = sz + guarddim * (GUARD_SIZE * 4); // Generate guard[] i = 0; for (b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { dt_t *dt; block *bhandler; int nsucc; unsigned endoffset; block *bn; assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * (GUARD_SIZE * 4); pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset for (bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } pdt = dtdword(pdt,endoffset); // offset past end of guarded block pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { pdt = dtdword(pdt,catchoffset); pdt = dtdword(pdt,0); // no finally handler catchoffset += 4 + (nsucc - 1) * (3 * 4); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr); // finally handler address //pdt = dtcoff(pdt,bhandler->Boffset); // finally handler address } sz += GUARD_SIZE + 4; } } // Generate catch[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { block *bhandler; int nsucc; if (b->jcatchvar) // if try-catch { list_t bl; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,nsucc - 1); // # of catch blocks sz += 4; for (bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtdword(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr); // catch handler address //pdt = dtcoff(pdt,bcatch->Boffset); // catch handler address sz += 3 * 4; } } } } assert(sz != 0); outdata(s); // output the scope table obj_ehtables(funcsym_p,funcsym_p->Ssize,s); #endif return NULL; }
void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); unsigned offset = Type::typeinfostruct->structsize; dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtdword(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; /* Put out: * char[] name; * void[] init; * hash_t function(void*) xtoHash; * int function(void*,void*) xopEquals; * int function(void*,void*) xopCmp; * char[] function(void*) xtoString; * uint m_flags; * * name[] */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); //dtabytes(pdt, TYnptr, 0, namelen + 1, name); dtxoff(pdt, toSymbol(), offset, TYnptr); offset += namelen + 1; // void[] init; dtdword(pdt, sd->structsize); // init.length if (sd->zeroInit) dtdword(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr FuncDeclaration *fd; FuncDeclaration *fdx; TypeFunction *tf; Type *ta; Dsymbol *s; static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfeqptr; { Scope sc; Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); } #if 0 TypeFunction *tfeq; { Scope sc; Array *arguments = new Array; Parameter *arg = new Parameter(In, tc, NULL, NULL); arguments->push(arg); tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfeq = (TypeFunction *)tfeq->semantic(0, &sc); } #endif s = search_function(sd, Id::tohash); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) uint toHash()"); dtdword(pdt, 0); } else dtdword(pdt, 0); s = search_function(sd, Id::eq); fdx = s ? s->isFuncDeclaration() : NULL; for (int i = 0; i < 2; i++) { if (fdx) { fd = fdx->overloadExactMatch(tfeqptr); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtdword(pdt, 0); } else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtdword(pdt, 0); s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; } s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftostring); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) char[] toString()"); dtdword(pdt, 0); } else dtdword(pdt, 0); // uint m_flags; dtdword(pdt, tc->hasPointers()); #if DMDV2 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xgetMembers // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit) dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xpostblit #endif // name[] dtnbytes(pdt, namelen + 1, name); }
void TypeInfoDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo dtdword(pdt, 0); // monitor }
dt_t *ArrayInitializer::toDtBit() { #if DMDV1 unsigned size; unsigned length; unsigned i; unsigned tadim; dt_t *d; dt_t **pdtend; Type *tb = type->toBasetype(); //printf("ArrayInitializer::toDtBit('%s')\n", toChars()); Bits databits; Bits initbits; if (tb->ty == Tsarray) { /* The 'dim' for ArrayInitializer is only the maximum dimension * seen in the initializer, not the type. So, for static arrays, * use instead the dimension of the type in order * to get the whole thing. */ dinteger_t value = ((TypeSArray*)tb)->dim->toInteger(); tadim = value; assert(tadim == value); // truncation overflow should already be checked databits.resize(tadim); initbits.resize(tadim); } else { databits.resize(dim); initbits.resize(dim); } /* The default initializer may be something other than zero. */ if (tb->nextOf()->defaultInit()->toInteger()) databits.set(); size = sizeof(databits.data[0]); length = 0; for (i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; Expression *eval; idx = (Expression *)index.data[i]; if (idx) { dinteger_t value; value = idx->toInteger(); length = value; if (length != value) { error(loc, "index overflow %llu", value); length = 0; } } assert(length < dim); val = (Initializer *)value.data[i]; eval = val->toExpression(); if (initbits.test(length)) error(loc, "duplicate initializations for index %d", length); initbits.set(length); if (eval->toInteger()) // any non-zero value is boolean 'true' databits.set(length); else databits.clear(length); // boolean 'false' length++; } d = NULL; pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data); switch (tb->ty) { case Tsarray: { if (dim > tadim) { #ifdef DEBUG printf("2: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } else { tadim = (tadim + 31) / 32; if (databits.allocdim < tadim) pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim)); // pad out end of array } break; } case Tpointer: case Tarray: // Create symbol, and then refer to it Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtdword(&d, dim); dtxoff(&d, s, 0, TYnptr); break; default: assert(0); } return d; #else return NULL; #endif }