type *type_fake(tym_t ty) { type *t; #if MARS assert(ty != TYstruct); #endif t = type_alloc(ty); if (typtr(ty) || tyfunc(ty)) { t->Tnext = type_alloc(TYvoid); /* fake with pointer to void */ t->Tnext->Tcount = 1; } return t; }
/************************************** * Create a struct/union/class type. * Params: * name = name of struct (this function makes its own copy of the string) * Returns: * Tcount already incremented */ type *type_struct_class(const char *name, unsigned alignsize, unsigned structsize, type *arg1type, type *arg2type, bool isUnion, bool isClass, bool isPOD) { Symbol *s = symbol_calloc(name); s->Sclass = SCstruct; s->Sstruct = struct_calloc(); s->Sstruct->Salignsize = alignsize; s->Sstruct->Sstructalign = alignsize; s->Sstruct->Sstructsize = structsize; s->Sstruct->Sarg1type = arg1type; s->Sstruct->Sarg2type = arg2type; if (!isPOD) s->Sstruct->Sflags |= STRnotpod; if (isUnion) s->Sstruct->Sflags |= STRunion; if (isClass) { s->Sstruct->Sflags |= STRclass; assert(!isUnion && isPOD); } type *t = type_alloc(TYstruct); t->Ttag = (Classsym *)s; // structure tag name t->Tcount++; s->Stype = t; t->Tcount++; return t; }
Symbol *Dsymbol::toImport(Symbol *sym) { char *id; char *n; Symbol *s; type *t; //printf("Dsymbol::toImport('%s')\n", sym->Sident); n = sym->Sident; id = (char *) alloca(6 + strlen(n) + 1 + sizeof(type_paramsize(sym->Stype))*3 + 1); if (sym->Stype->Tmangle == mTYman_std && tyfunc(sym->Stype->Tty)) { if (config.exe == EX_WIN64) sprintf(id,"__imp_%s",n); else sprintf(id,"_imp__%s@%lu",n,(unsigned long)type_paramsize(sym->Stype)); } else if (sym->Stype->Tmangle == mTYman_d) sprintf(id,"_imp_%s",n); else sprintf(id,"_imp__%s",n); t = type_alloc(TYnptr | mTYconst); t->Tnext = sym->Stype; t->Tnext->Tcount++; t->Tmangle = mTYman_c; t->Tcount++; s = symbol_calloc(id); s->Stype = t; s->Sclass = SCextern; s->Sfl = FLextern; slist_add(s); return s; }
void nteh_declarvars(Blockx *bx) { symbol *s; #if MARS if (!(bx->funcsym->Sfunc->Fflags3 & Fnteh)) // if haven't already done it { bx->funcsym->Sfunc->Fflags3 |= Fnteh; s = symbol_name(s_name_context,SCbprel,tsint); s->Soffset = -5 * 4; // -6 * 4 for C __try, __except, __finally s->Sflags |= SFLfree | SFLnodebug; type_setty(&s->Stype,mTYvolatile | TYint); symbol_add(s); bx->context = s; } #else if (!(funcsym_p->Sfunc->Fflags3 & Fnteh)) // if haven't already done it { funcsym_p->Sfunc->Fflags3 |= Fnteh; if (!s_context) s_context = scope_search(s_name_context_tag,CPP ? SCTglobal : SCTglobaltag); symbol_debug(s_context); s = symbol_name(s_name_context,SCbprel,s_context->Stype); s->Soffset = -6 * 4; // -5 * 4 for C++ s->Sflags |= SFLfree; symbol_add(s); type_setty(&s->Stype,mTYvolatile | TYstruct); s = symbol_name(s_name_ecode,SCauto,type_alloc(mTYvolatile | TYint)); s->Sflags |= SFLfree; symbol_add(s); } #endif }
type *TypeFunction::toCtype() { type *t; if (ctype) return ctype; if (1) { param_t *paramtypes = NULL; size_t nparams = Parameter::dim(parameters); for (size_t i = 0; i < nparams; i++) { Parameter *arg = Parameter::getNth(parameters, i); type *tp = arg->type->toCtype(); if (arg->storageClass & (STCout | STCref)) { // C doesn't have reference types, so it's really a pointer // to the parameter type tp = type_allocn(TYref, tp); } param_append_type(¶mtypes,tp); } tym_t tyf = totym(); t = type_alloc(tyf); t->Tflags |= TFprototype; if (varargs != 1) t->Tflags |= TFfixed; ctype = t; assert(next); // function return type should exist t->Tnext = next->toCtype(); t->Tnext->Tcount++; t->Tparamtypes = paramtypes; } ctype = t; return t; }
Symbol *Dsymbol::toImport(Symbol *sym) { char *id; char *n; Symbol *s; type *t; //printf("Dsymbol::toImport('%s')\n", sym->Sident); n = sym->Sident; id = (char *) alloca(6 + strlen(n) + 5 + 1); if (sym->Stype->Tmangle == mTYman_std) { sprintf(id,"_imp__%s@%d",n,type_paramsize(sym->Stype)); } else if (sym->Stype->Tmangle == mTYman_d) sprintf(id,"_imp_%s",n); else sprintf(id,"_imp__%s",n); t = type_alloc(TYnptr | mTYconst); t->Tnext = sym->Stype; t->Tnext->Tcount++; t->Tmangle = mTYman_c; t->Tcount++; s = symbol_calloc(id); s->Stype = t; s->Sclass = SCextern; s->Sfl = FLextern; slist_add(s); return s; }
type *type_copy(type *t) { type *tn; param_t *p; type_debug(t); if (tybasic(t->Tty) == TYtemplate) { tn = type_alloc_template(((typetemp_t *)t)->Tsym); } else tn = type_alloc(t->Tty); *tn = *t; switch (tybasic(tn->Tty)) { case TYtemplate: ((typetemp_t *)tn)->Tsym = ((typetemp_t *)t)->Tsym; goto L1; case TYident: tn->Tident = (char *)MEM_PH_STRDUP(t->Tident); break; case TYarray: if (tn->Tflags & TFvla) tn->Tel = el_copytree(tn->Tel); break; default: if (tyfunc(tn->Tty)) { L1: tn->Tparamtypes = NULL; for (p = t->Tparamtypes; p; p = p->Pnext) { param_t *pn; pn = param_append_type(&tn->Tparamtypes,p->Ptype); if (p->Pident) { pn->Pident = (char *)MEM_PH_STRDUP(p->Pident); } assert(!p->Pelem); } } #if SCPP else if (tn->Talternate && typtr(tn->Tty)) tn->Talternate->Tcount++; #endif #if MARS else if (tn->Tkey && typtr(tn->Tty)) tn->Tkey->Tcount++; #endif break; } if (tn->Tnext) { type_debug(tn->Tnext); tn->Tnext->Tcount++; } tn->Tcount = 0; return tn; }
STATIC type * __near type_allocbasic(tym_t ty) { type *t; t = type_alloc(ty); t->Tmangle = mTYman_c; t->Tcount = 1; /* so it is not inadvertantly free'd */ return t; }
type *TypeAArray::toCtype() { type *t; if (ctype) return ctype; if (0 && global.params.symdebug) { /* An associative array is represented by: * struct AArray { size_t length; void* ptr; } */ static Symbol *s; if (!s) { s = symbol_calloc("_AArray"); s->Sclass = SCstruct; s->Sstruct = struct_calloc(); s->Sstruct->Sflags |= 0; s->Sstruct->Salignsize = alignsize(); s->Sstruct->Sstructalign = global.structalign; s->Sstruct->Sstructsize = size(0); slist_add(s); Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype()); list_append(&s->Sstruct->Sfldlst, s1); Symbol *s2 = symbol_name("data", SCmember, Type::tvoidptr->toCtype()); s2->Smemoff = Type::tsize_t->size(); list_append(&s->Sstruct->Sfldlst, s2); } t = type_alloc(TYstruct); t->Ttag = (Classsym *)s; // structure tag name t->Tcount++; s->Stype = t; } else { if (global.params.symdebug == 1) { /* Generate D symbolic debug info, rather than C * Tnext: element type * Tkey: key type */ t = type_allocn(TYaarray, next->toCtype()); t->Tkey = index->toCtype(); t->Tkey->Tcount++; } else t = type_fake(TYaarray); } t->Tcount++; ctype = t; return t; }
symbol *callFuncsAndGates(Module *m, symbols *sctors, StaticDtorDeclarations *ectorgates, const char *id) { symbol *sctor = NULL; if ((sctors && sctors->dim) || (ectorgates && ectorgates->dim)) { static type *t; if (!t) { /* t will be the type of the functions generated: * extern (C) void func(); */ t = type_alloc(TYnfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_c; t->Tnext = tsvoid; tsvoid->Tcount++; } localgot = NULL; sctor = m->toSymbolX(id, SCglobal, t, "FZv"); cstate.CSpsymtab = &sctor->Sfunc->Flocsym; elem *ector = NULL; if (ectorgates) { for (size_t i = 0; i < ectorgates->dim; i++) { StaticDtorDeclaration *f = (*ectorgates)[i]; Symbol *s = f->vgate->toSymbol(); elem *e = el_var(s); e = el_bin(OPaddass, TYint, e, el_long(TYint, 1)); ector = el_combine(ector, e); } } if (sctors) { for (size_t i = 0; i < sctors->dim; i++) { symbol *s = (*sctors)[i]; elem *e = el_una(OPucall, TYvoid, el_var(s)); ector = el_combine(ector, e); } } block *b = block_calloc(); b->BC = BCret; b->Belem = ector; sctor->Sfunc->Fstartline.Sfilename = m->arg; sctor->Sfunc->Fstartblock = b; writefunc(sctor); } return sctor; }
void visit(TypeEnum *t) { //printf("TypeEnum::toCtype() '%s'\n", t->sym->toChars()); Type *tm = t->mutableOf(); if (tm->ctype && tybasic(tm->ctype->Tty) == TYenum) { Symbol *s = tm->ctype->Ttag; assert(s); t->ctype = type_alloc(TYenum); t->ctype->Ttag = (Classsym *)s; // enum tag name t->ctype->Tcount++; t->ctype->Tnext = tm->ctype->Tnext; t->ctype->Tnext->Tcount++; // Add modifiers switch (t->mod) { case 0: assert(0); break; case MODconst: case MODwild: case MODwildconst: t->ctype->Tty |= mTYconst; break; case MODshared: t->ctype->Tty |= mTYshared; break; case MODshared | MODconst: case MODshared | MODwild: case MODshared | MODwildconst: t->ctype->Tty |= mTYshared | mTYconst; break; case MODimmutable: t->ctype->Tty |= mTYimmutable; break; default: assert(0); } } else if (!t->sym->memtype) { // Bugzilla 13792 t->ctype = Type_toCtype(Type::tvoid); } else if (t->sym->memtype->toBasetype()->ty == Tint32) { t->ctype = type_enum(t->sym->toPrettyChars(true), Type_toCtype(t->sym->memtype)); tm->ctype = t->ctype; } else { t->ctype = Type_toCtype(t->sym->memtype); } //printf("t = %p, Tflags = x%x\n", t, t->Tflags); }
type *TypeDelegate::toCtype() { type *t; if (ctype) return ctype; if (0 && global.params.symdebug) { /* A delegate consists of: * _Delegate { void* frameptr; Function *funcptr; } */ static Symbol *s; if (!s) { s = symbol_calloc("_Delegate"); s->Sclass = SCstruct; s->Sstruct = struct_calloc(); s->Sstruct->Sflags |= 0; s->Sstruct->Salignsize = alignsize(); s->Sstruct->Sstructalign = global.structalign; s->Sstruct->Sstructsize = size(0); slist_add(s); Symbol *s1 = symbol_name("frameptr", SCmember, Type::tvoidptr->toCtype()); list_append(&s->Sstruct->Sfldlst, s1); Symbol *s2 = symbol_name("funcptr", SCmember, Type::tvoidptr->toCtype()); s2->Smemoff = Type::tvoidptr->size(); list_append(&s->Sstruct->Sfldlst, s2); } t = type_alloc(TYstruct); t->Ttag = (Classsym *)s; // structure tag name t->Tcount++; s->Stype = t; } else { if (global.params.symdebug == 1) { // Generate D symbolic debug info, rather than C t = type_allocn(TYdelegate, next->toCtype()); } else t = type_fake(TYdelegate); } t->Tcount++; ctype = t; return t; }
type *type_allocn(tym_t ty,type *tn) { type *t; //printf("type_allocn(ty = x%x, tn = %p)\n", ty, tn); assert(tn); type_debug(tn); t = type_alloc(ty); t->Tnext = tn; tn->Tcount++; //printf("\tt = %p\n", t); return t; }
type *TypeDArray::toCtype() { type *t; if (ctype) return ctype; if (0 && global.params.symdebug) { /* Create a C type out of: * struct _Array_T { size_t length; T* data; } */ Symbol *s; char *id; assert(next->deco); id = (char *) alloca(7 + strlen(next->deco) + 1); sprintf(id, "_Array_%s", next->deco); s = symbol_calloc(id); s->Sclass = SCstruct; s->Sstruct = struct_calloc(); s->Sstruct->Sflags |= 0; s->Sstruct->Salignsize = alignsize(); s->Sstruct->Sstructalign = global.structalign; s->Sstruct->Sstructsize = size(0); slist_add(s); Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype()); list_append(&s->Sstruct->Sfldlst, s1); Symbol *s2 = symbol_name("data", SCmember, next->pointerTo()->toCtype()); s2->Smemoff = Type::tsize_t->size(); list_append(&s->Sstruct->Sfldlst, s2); t = type_alloc(TYstruct); t->Ttag = (Classsym *)s; // structure tag name t->Tcount++; s->Stype = t; } else { if (global.params.symdebug == 1) { // Generate D symbolic debug info, rather than C t = type_allocn(TYdarray, next->toCtype()); } else t = type_fake(TYdarray); } t->Tcount++; ctype = t; return t; }
/************************************* * Create a reference to another dt. */ void DtBuilder::dtoff(dt_t *dt, unsigned offset) { type *t = type_alloc(TYint); t->Tcount++; Symbol *s = symbol_calloc("internal"); s->Sclass = SCstatic; s->Sfl = FLextern; s->Sflags |= SFLnodebug; s->Stype = t; s->Sdt = dt; outdata(s); xoff(s, offset); }
STATIC symbol *nteh_scopetable() { symbol *s; type *t; if (!s_table) { t = type_alloc(TYint); s = symbol_generate(SCstatic,t); s->Sseg = UNKNOWN; symbol_keep(s); s_table = s; } return s_table; }
Symbol *static_sym() { Symbol *s; type *t; t = type_alloc(TYint); t->Tcount++; s = symbol_calloc("internal"); s->Sclass = SCstatic; s->Sfl = FLextern; s->Sflags |= SFLnodebug; s->Stype = t; slist_add(s); return s; }
struct type *type_function_create( struct module *m, struct type *arg_type, struct type *ret_type ) { struct type *t; t = type_alloc(m); if (!t) { RF_ERROR("Type allocation failed"); return NULL; } type_function_init(t, arg_type, ret_type); return t; }
type *TypeClass::toCtype() { type *t; Symbol *s; //printf("TypeClass::toCtype() %s\n", toChars()); if (ctype) return ctype; /* Need this symbol to do C++ name mangling */ const char *name = sym->isCPPinterface() ? sym->ident->toChars() : sym->toPrettyChars(); s = symbol_calloc(name); s->Sclass = SCstruct; s->Sstruct = struct_calloc(); s->Sstruct->Sflags |= STRclass; s->Sstruct->Salignsize = sym->alignsize; s->Sstruct->Sstructalign = sym->structalign; s->Sstruct->Sstructsize = sym->structsize; t = type_alloc(TYstruct); t->Ttag = (Classsym *)s; // structure tag name t->Tcount++; s->Stype = t; slist_add(s); t = type_allocn(TYnptr, t); t->Tcount++; ctype = t; /* Add in fields of the class * (after setting ctype to avoid infinite recursion) */ if (global.params.symdebug) for (int i = 0; i < sym->fields.dim; i++) { VarDeclaration *v = sym->fields.tdata()[i]; Symbol *s2 = symbol_name(v->ident->toChars(), SCmember, v->type->toCtype()); s2->Smemoff = v->offset; list_append(&s->Sstruct->Sfldlst, s2); } return t; }
Symbol* ClassReferenceExp::toSymbol() { if (value->sym) return value->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; value->sym = s; dt_t *d = NULL; toInstanceDt(&d); s->Sdt = d; slist_add(s); outdata(s); return value->sym; }
Symbol *static_sym() { Symbol *s; type *t; t = type_alloc(TYint); t->Tcount++; s = symbol_calloc("internal"); s->Sclass = SCstatic; s->Sfl = FLextern; s->Sflags |= SFLnodebug; s->Stype = t; #if ELFOBJ // Burton s->Sseg = DATA; #endif /* ELFOBJ */ slist_add(s); return s; }
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; }
Symbol *Module::toModuleAssert() { if (!massert) { type *t; t = type_alloc(TYjfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_d; t->Tnext = tsvoid; tsvoid->Tcount++; massert = toSymbolX("__assert", SCextern, t, "FiZv"); massert->Sfl = FLextern; massert->Sflags |= SFLnodebug; slist_add(massert); } return massert; }
Symbol *Module::toModuleArray() { if (!marray) { type *t; t = type_alloc(TYjfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_d; t->Tnext = tsvoid; tsvoid->Tcount++; marray = toSymbolX("_array_", SCextern, t); marray->Sfl = FLextern; marray->Sflags |= SFLnodebug; slist_add(marray); } return marray; }
Symbol *Module::toModuleUnittest() { if (!munittest) { type *t; t = type_alloc(TYjfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_d; t->Tnext = tsvoid; tsvoid->Tcount++; munittest = toSymbolX("__unittest_fail", SCextern, t, "FiZv"); munittest->Sfl = FLextern; munittest->Sflags |= SFLnodebug; slist_add(munittest); } return munittest; }
Classsym *fake_classsym(char *name) { TYPE *t; Classsym *scc; scc = (Classsym *)symbol_calloc("ClassInfo"); scc->Sclass = SCstruct; scc->Sstruct = struct_calloc(); scc->Sstruct->Sstructalign = 8; //scc->Sstruct->ptrtype = TYnptr; scc->Sstruct->Sflags = STRglobal; t = type_alloc(TYstruct); t->Tflags |= TFsizeunknown | TFforward; t->Ttag = scc; // structure tag name assert(t->Tmangle == 0); t->Tmangle = mTYman_c; t->Tcount++; scc->Stype = t; slist_add(scc); return scc; }
Symbol *ClassDeclaration::toVtblSymbol() { if (!vtblsym) { Symbol *s; TYPE *t; if (!csym) toSymbol(); t = type_alloc(TYnptr | mTYconst); t->Tnext = tsvoid; t->Tnext->Tcount++; t->Tmangle = mTYman_c; s = toSymbolX("_vtbl_", SCextern, t); s->Sflags |= SFLnodebug; s->Sfl = FLextern; vtblsym = s; slist_add(s); } return vtblsym; }
type *TypePointer::toCtype() { type *tn; type *t; //printf("TypePointer::toCtype() %s\n", toChars()); if (ctype) return ctype; if (1 || global.params.symdebug) { /* Need to always do this, otherwise C++ name mangling * goes awry. */ t = type_alloc(TYnptr); ctype = t; tn = next->toCtype(); t->Tnext = tn; tn->Tcount++; } else t = type_fake(totym()); t->Tcount++; ctype = t; return t; }
void type_init() { int i; tsbool = type_allocbasic(TYbool); tswchar_t = type_allocbasic(TYwchar_t); tsdchar = type_allocbasic(TYdchar); tsvoid = type_allocbasic(TYvoid); tsnullptr = type_allocbasic(TYnullptr); tschar16 = type_allocbasic(TYchar16); tsuchar = type_allocbasic(TYuchar); tsschar = type_allocbasic(TYschar); tschar = type_allocbasic(TYchar); tsshort = type_allocbasic(TYshort); tsushort = type_allocbasic(TYushort); tsint = type_allocbasic(TYint); tsuns = type_allocbasic(TYuint); tslong = type_allocbasic(TYlong); tsulong = type_allocbasic(TYulong); tsllong = type_allocbasic(TYllong); tsullong = type_allocbasic(TYullong); tsfloat = type_allocbasic(TYfloat); tsdouble = type_allocbasic(TYdouble); tsifloat = type_allocbasic(TYifloat); tsidouble = type_allocbasic(TYidouble); tscfloat = type_allocbasic(TYcfloat); tscdouble = type_allocbasic(TYcdouble); #if TX86 tsreal64 = type_allocbasic(TYdouble_alias); tsldouble = type_allocbasic(TYldouble); tsildouble = type_allocbasic(TYildouble); tscldouble = type_allocbasic(TYcldouble); #else tsldouble = type_allocbasic(TYldouble); tscomp = type_allocbasic(TYcomp); chartype = tschar; /* default is signed chars */ #endif if (I64) { TYptrdiff = TYllong; TYsize = TYullong; tsptrdiff = tsllong; tssize = tsullong; } else { TYptrdiff = TYint; TYsize = TYuint; tsptrdiff = tsint; tssize = tsuns; } #if TX86 chartype = (config.flags3 & CFG3ju) ? tsuchar : tschar; // Type of far library function tsclib = type_fake(LARGECODE ? TYfpfunc : TYnpfunc); tsclib->Tmangle = mTYman_c; tsclib->Tcount++; // Type of trace function tstrace = type_fake(I16 ? TYffunc : TYnfunc); tstrace->Tmangle = mTYman_c; tstrace->Tcount++; tspvoid = type_allocn(pointertype,tsvoid); tspvoid->Tmangle = mTYman_c; tspvoid->Tcount++; // Type of far library function tsjlib = type_fake(TYjfunc); tsjlib->Tmangle = mTYman_c; tsjlib->Tcount++; tsdlib = tsjlib; #if SCPP tspcvoid = type_alloc(mTYconst | TYvoid); tspcvoid = newpointer(tspcvoid); tspcvoid->Tmangle = mTYman_c; tspcvoid->Tcount++; #endif // Type of logical expression tslogical = (config.flags4 & CFG4bool) ? tsbool : tsint; for (i = 0; i < TYMAX; i++) { if (tstypes[i]) { tsptr2types[i] = type_allocn(pointertype,tstypes[i]); tsptr2types[i]->Tcount++; } } #else type_list = NULL; tsclib = type_fake( TYffunc ); tsclib->Tmangle = mTYman_c; tsclib->Tcount++; #ifdef DEBUG type_num = 0; type_max = 0; #endif /* DEBUG */ #endif /* TX86 */ }
void Module::genobjfile(int multiobj) { //EEcontext *ee = env->getEEcontext(); //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars()); lastmname = srcfile->toChars(); obj_initfile(lastmname, NULL, toPrettyChars()); eictor = NULL; ictorlocalgot = NULL; ector = NULL; ectorgates.setDim(0); edtor = NULL; etest = NULL; dtorcount = 0; if (doppelganger) { /* Generate a reference to the moduleinfo, so the module constructors * and destructors get linked in. */ Module *m = (Module *)aimports.data[0]; assert(m); if (m->sictor || m->sctor || m->sdtor) { Symbol *s = m->toSymbol(); //objextern(s); //if (!s->Sxtrnnum) objextdef(s->Sident); if (!s->Sxtrnnum) { //printf("%s\n", s->Sident); #if 0 /* This should work, but causes optlink to fail in common/newlib.asm */ objextdef(s->Sident); #else #if ELFOBJ || MACHOBJ int nbytes = reftoident(DATA, Offset(DATA), s, 0, CFoff); Offset(DATA) += nbytes; #else int nbytes = reftoident(DATA, Doffset, s, 0, CFoff); Doffset += nbytes; #endif #endif } } } if (global.params.cov) { /* Create coverage identifier: * private uint[numlines] __coverage; */ cov = symbol_calloc("__coverage"); cov->Stype = type_fake(TYint); cov->Stype->Tmangle = mTYman_c; cov->Stype->Tcount++; cov->Sclass = SCstatic; cov->Sfl = FLdata; #if ELFOBJ || MACHOBJ cov->Sseg = UDATA; #endif dtnzeros(&cov->Sdt, 4 * numlines); outdata(cov); slist_add(cov); covb = (unsigned *)calloc((numlines + 32) / 32, sizeof(*covb)); } for (int i = 0; i < members->dim; i++) { Dsymbol *member = (Dsymbol *)members->data[i]; member->toObjFile(multiobj); } if (global.params.cov) { /* Generate * bit[numlines] __bcoverage; */ Symbol *bcov = symbol_calloc("__bcoverage"); bcov->Stype = type_fake(TYuint); bcov->Stype->Tcount++; bcov->Sclass = SCstatic; bcov->Sfl = FLdata; #if ELFOBJ || MACHOBJ bcov->Sseg = DATA; #endif dtnbytes(&bcov->Sdt, (numlines + 32) / 32 * sizeof(*covb), (char *)covb); outdata(bcov); free(covb); covb = NULL; /* Generate: * _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename); * and prepend it to the static constructor. */ /* t will be the type of the functions generated: * extern (C) void func(); */ type *t = type_alloc(TYnfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_c; t->Tnext = tsvoid; tsvoid->Tcount++; sictor = toSymbolX("__modictor", SCglobal, t, "FZv"); cstate.CSpsymtab = &sictor->Sfunc->Flocsym; localgot = ictorlocalgot; elem *e; e = el_params(el_ptr(cov), el_long(TYuint, numlines), el_ptr(bcov), el_long(TYuint, numlines), toEfilename(), NULL); e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER]), e); eictor = el_combine(e, eictor); ictorlocalgot = localgot; } // If coverage / static constructor / destructor / unittest calls if (eictor || ector || ectorgates.dim || edtor || etest) { /* t will be the type of the functions generated: * extern (C) void func(); */ type *t = type_alloc(TYnfunc); t->Tflags |= TFprototype | TFfixed; t->Tmangle = mTYman_c; t->Tnext = tsvoid; tsvoid->Tcount++; static char moddeco[] = "FZv"; if (eictor) { localgot = ictorlocalgot; block *b = block_calloc(); b->BC = BCret; b->Belem = eictor; sictor->Sfunc->Fstartblock = b; writefunc(sictor); } if (ector || ectorgates.dim) { localgot = NULL; sctor = toSymbolX("__modctor", SCglobal, t, moddeco); cstate.CSpsymtab = &sctor->Sfunc->Flocsym; for (int i = 0; i < ectorgates.dim; i++) { StaticDtorDeclaration *f = (StaticDtorDeclaration *)ectorgates.data[i]; Symbol *s = f->vgate->toSymbol(); elem *e = el_var(s); e = el_bin(OPaddass, TYint, e, el_long(TYint, 1)); ector = el_combine(ector, e); } block *b = block_calloc(); b->BC = BCret; b->Belem = ector; sctor->Sfunc->Fstartblock = b; writefunc(sctor); #if STATICCTOR obj_staticctor(sctor, dtorcount, 1); #endif } if (edtor) { localgot = NULL; sdtor = toSymbolX("__moddtor", SCglobal, t, moddeco); block *b = block_calloc(); b->BC = BCret; b->Belem = edtor; sdtor->Sfunc->Fstartblock = b; writefunc(sdtor); } if (etest) { localgot = NULL; stest = toSymbolX("__modtest", SCglobal, t, moddeco); block *b = block_calloc(); b->BC = BCret; b->Belem = etest; stest->Sfunc->Fstartblock = b; writefunc(stest); } if (doppelganger) genmoduleinfo(); } if (doppelganger) { obj_termfile(); return; } if (global.params.multiobj) { /* This is necessary because the main .obj for this module is written * first, but determining whether marray or massert are needed is done * possibly later in the doppelganger modules. * Another way to fix it is do the main one last. */ toModuleAssert(); toModuleArray(); } // If module assert for (int i = 0; i < 2; i++) { Symbol *ma = i ? marray : massert; if (ma) { elem *elinnum; elem *efilename; localgot = NULL; // Call dassert(filename, line) // Get sole parameter, linnum { Symbol *sp; sp = symbol_calloc("linnum"); sp->Stype = type_fake(TYint); sp->Stype->Tcount++; sp->Sclass = SCfastpar; sp->Spreg = AX; sp->Sflags &= ~SFLspill; sp->Sfl = FLpara; // FLauto? cstate.CSpsymtab = &ma->Sfunc->Flocsym; symbol_add(sp); elinnum = el_var(sp); } efilename = toEmodulename(); elem *e = el_var(rtlsym[i ? RTLSYM_DARRAY : RTLSYM_DASSERT]); e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename)); block *b = block_calloc(); b->BC = BCret; b->Belem = e; ma->Sfunc->Fstartblock = b; ma->Sclass = SCglobal; ma->Sfl = 0; writefunc(ma); } } #if 1 // Always generate module info, because of templates and -cov if (1 || needModuleInfo()) genmoduleinfo(); #endif obj_termfile(); }