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(); }
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; sctors.setDim(0); ectorgates.setDim(0); sdtors.setDim(0); ssharedctors.setDim(0); esharedctorgates.setDim(0); sshareddtors.setDim(0); stests.setDim(0); dtorcount = 0; shareddtorcount = 0; if (doppelganger) { /* Generate a reference to the moduleinfo, so the module constructors * and destructors get linked in. */ Module *m = aimports[0]; assert(m); if (m->sictor || m->sctor || m->sdtor || m->ssharedctor || m->sshareddtor) { 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, I64 ? (CFoff | CFoffset64) : CFoff); #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 (size_t i = 0; i < members->dim; i++) { Dsymbol *member = (*members)[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_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(cov)), el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(bcov)), 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 || sctors.dim || ectorgates.dim || sdtors.dim || ssharedctors.dim || esharedctorgates.dim || sshareddtors.dim || stests.dim) { if (eictor) { localgot = ictorlocalgot; block *b = block_calloc(); b->BC = BCret; b->Belem = eictor; sictor->Sfunc->Fstartline.Sfilename = arg; sictor->Sfunc->Fstartblock = b; writefunc(sictor); } sctor = callFuncsAndGates(this, &sctors, &ectorgates, "__modctor"); sdtor = callFuncsAndGates(this, &sdtors, NULL, "__moddtor"); #if DMDV2 ssharedctor = callFuncsAndGates(this, &ssharedctors, (StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor"); sshareddtor = callFuncsAndGates(this, &sshareddtors, NULL, "__modshareddtor"); #endif stest = callFuncsAndGates(this, &stests, NULL, "__modtest"); 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 or munittest are needed is done * possibly later in the doppelganger modules. * Another way to fix it is do the main one last. */ toModuleAssert(); toModuleUnittest(); toModuleArray(); } #if 1 // Always generate module info, because of templates and -cov if (1 || needModuleInfo()) genmoduleinfo(); #endif // If module assert for (int i = 0; i < 3; i++) { Symbol *ma; unsigned rt; unsigned bc; switch (i) { case 0: ma = marray; rt = RTLSYM_DARRAY; bc = BCexit; break; case 1: ma = massert; rt = RTLSYM_DASSERTM; bc = BCexit; break; case 2: ma = munittest; rt = RTLSYM_DUNITTESTM; bc = BCret; break; default: assert(0); } if (ma) { elem *elinnum; localgot = NULL; // Call dassert(filename, line) // Get sole parameter, linnum { Symbol *sp = symbol_calloc("linnum"); sp->Stype = type_fake(TYint); sp->Stype->Tcount++; sp->Sclass = SCfastpar; size_t num; sp->Spreg = getintegerparamsreglist(TYjfunc, &num)[0]; sp->Sflags &= ~SFLspill; sp->Sfl = FLpara; // FLauto? cstate.CSpsymtab = &ma->Sfunc->Flocsym; symbol_add(sp); elinnum = el_var(sp); } elem *efilename = el_ptr(toSymbol()); elem *e = el_var(rtlsym[rt]); e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename)); block *b = block_calloc(); b->BC = bc; b->Belem = e; ma->Sfunc->Fstartline.Sfilename = arg; ma->Sfunc->Fstartblock = b; ma->Sclass = SCglobal; ma->Sfl = 0; ma->Sflags |= rtlsym[rt]->Sflags & SFLexit; writefunc(ma); } } obj_termfile(); }