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); }
void FuncDeclaration::toObjFile(int multiobj) { Symbol *s; func_t *f; Symbol *senter; Symbol *sexit; FuncDeclaration *func = this; ClassDeclaration *cd = func->parent->isClassDeclaration(); int reverse; int i; int has_arguments; //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars()); #if 0 //printf("line = %d\n",func->getWhere() / LINEINC); EEcontext *ee = env->getEEcontext(); if (ee->EEcompile == 2) { if (ee->EElinnum < (func->getWhere() / LINEINC) || ee->EElinnum > (func->endwhere / LINEINC) ) return; // don't compile this function ee->EEfunc = func->toSymbol(); } #endif if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration()) { obj_append(this); return; } if (semanticRun >= 5) // if toObjFile() already run return; semanticRun = 5; if (!func->fbody) { return; } if (func->isUnitTestDeclaration() && !global.params.useUnitTests) return; if (global.params.verbose) printf("function %s\n",func->toChars()); s = func->toSymbol(); f = s->Sfunc; #if TARGET_WINDOS /* This is done so that the 'this' pointer on the stack is the same * distance away from the function parameters, so that an overriding * function can call the nested fdensure or fdrequire of its overridden function * and the stack offsets are the same. */ if (isVirtual() && (fensure || frequire)) f->Fflags3 |= Ffakeeh; #endif #if TARGET_OSX s->Sclass = SCcomdat; #else s->Sclass = SCglobal; #endif for (Dsymbol *p = parent; p; p = p->parent) { if (p->isTemplateInstance()) { s->Sclass = SCcomdat; break; } } if (isNested()) { // if (!(config.flags3 & CFG3pic)) // s->Sclass = SCstatic; f->Fflags3 |= Fnested; } else { const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; // Pull in RTL startup code if (func->isMain()) { objextdef("_main"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS obj_ehsections(); // initialize exception handling sections #else objextdef("__acrtused_con"); #endif obj_includelib(libname); s->Sclass = SCglobal; } else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc) s->Sclass = SCglobal; else if (func->isWinMain()) { objextdef("__acrtused"); obj_includelib(libname); s->Sclass = SCglobal; } // Pull in RTL startup code else if (func->isDllMain()) { objextdef("__acrtused_dll"); obj_includelib(libname); s->Sclass = SCglobal; } } cstate.CSpsymtab = &f->Flocsym; // Find module m for this function Module *m = NULL; for (Dsymbol *p = parent; p; p = p->parent) { m = p->isModule(); if (m) break; } IRState irs(m, func); Array deferToObj; // write these to OBJ file later irs.deferToObj = &deferToObj; TypeFunction *tf; enum RET retmethod; symbol *shidden = NULL; Symbol *sthis = NULL; tym_t tyf; tyf = tybasic(s->Stype->Tty); //printf("linkage = %d, tyf = x%x\n", linkage, tyf); reverse = tyrevfunc(s->Stype->Tty); assert(func->type->ty == Tfunction); tf = (TypeFunction *)(func->type); has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1); retmethod = tf->retStyle(); if (retmethod == RETstack) { // If function returns a struct, put a pointer to that // as the first argument ::type *thidden = tf->next->pointerTo()->toCtype(); char hiddenparam[5+4+1]; static int hiddenparami; // how many we've generated so far sprintf(hiddenparam,"__HID%d",++hiddenparami); shidden = symbol_name(hiddenparam,SCparameter,thidden); shidden->Sflags |= SFLtrue | SFLfree; #if DMDV1 if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref) #else if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim) #endif type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile); irs.shidden = shidden; this->shidden = shidden; } if (vthis) { assert(!vthis->csym); sthis = vthis->toSymbol(); irs.sthis = sthis; if (!(f->Fflags3 & Fnested)) f->Fflags3 |= Fmember; } Symbol **params; unsigned pi; // Estimate number of parameters, pi pi = (v_arguments != NULL); if (parameters) pi += parameters->dim; // Allow extra 2 for sthis and shidden params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *)); // Get the actual number of parameters, pi, and fill in the params[] pi = 0; if (v_arguments) { params[pi] = v_arguments->toSymbol(); pi += 1; } if (parameters) { for (i = 0; i < parameters->dim; i++) { VarDeclaration *v = (VarDeclaration *)parameters->data[i]; if (v->csym) { error("compiler error, parameter '%s', bugzilla 2962?", v->toChars()); assert(0); } params[pi + i] = v->toSymbol(); } pi += i; } if (reverse) { // Reverse params[] entries for (i = 0; i < pi/2; i++) { Symbol *sptmp; sptmp = params[i]; params[i] = params[pi - 1 - i]; params[pi - 1 - i] = sptmp; } } if (shidden) { #if 0 // shidden becomes last parameter params[pi] = shidden; #else // shidden becomes first parameter memmove(params + 1, params, pi * sizeof(params[0])); params[0] = shidden; #endif pi++; } if (sthis) { #if 0 // sthis becomes last parameter params[pi] = sthis; #else // sthis becomes first parameter memmove(params + 1, params, pi * sizeof(params[0])); params[0] = sthis; #endif pi++; } if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) && linkage != LINKd && shidden && sthis) { /* swap shidden and sthis */ Symbol *sp = params[0]; params[0] = params[1]; params[1] = sp; } for (i = 0; i < pi; i++) { Symbol *sp = params[i]; sp->Sclass = SCparameter; sp->Sflags &= ~SFLspill; sp->Sfl = FLpara; symbol_add(sp); } // First parameter goes in register if (pi) { Symbol *sp = params[0]; if ((tyf == TYjfunc || tyf == TYmfunc) && type_jparam(sp->Stype)) { sp->Sclass = SCfastpar; sp->Spreg = (tyf == TYjfunc) ? AX : CX; sp->Sfl = FLauto; //printf("'%s' is SCfastpar\n",sp->Sident); } } if (func->fbody) { block *b; Blockx bx; Statement *sbody; localgot = NULL; sbody = func->fbody; memset(&bx,0,sizeof(bx)); bx.startblock = block_calloc(); bx.curblock = bx.startblock; bx.funcsym = s; bx.scope_index = -1; bx.classdec = cd; bx.member = func; bx.module = getModule(); irs.blx = &bx; buildClosure(&irs); #if 0 if (func->isSynchronized()) { if (cd) { elem *esync; if (func->isStatic()) { // monitor is in ClassInfo esync = el_ptr(cd->toSymbol()); } else { // 'this' is the monitor esync = el_var(sthis); } if (func->isStatic() || sbody->usesEH() || !(config.flags2 & CFG2seh)) { // BUG: what if frequire or fensure uses EH? sbody = new SynchronizedStatement(func->loc, esync, sbody); } else { #if TARGET_WINDOS if (config.flags2 & CFG2seh) { /* The "jmonitor" uses an optimized exception handling frame * which is a little shorter than the more general EH frame. * It isn't strictly necessary. */ s->Sfunc->Fflags3 |= Fjmonitor; } #endif el_free(esync); } } else { error("synchronized function %s must be a member of a class", func->toChars()); } } #elif TARGET_WINDOS if (func->isSynchronized() && cd && config.flags2 & CFG2seh && !func->isStatic() && !sbody->usesEH()) { /* The "jmonitor" hack uses an optimized exception handling frame * which is a little shorter than the more general EH frame. */ s->Sfunc->Fflags3 |= Fjmonitor; } #endif sbody->toIR(&irs); bx.curblock->BC = BCret; f->Fstartblock = bx.startblock; // einit = el_combine(einit,bx.init); if (isCtorDeclaration()) { assert(sthis); for (b = f->Fstartblock; b; b = b->Bnext) { if (b->BC == BCret) { b->BC = BCretexp; b->Belem = el_combine(b->Belem, el_var(sthis)); } } } } // If static constructor if (isStaticConstructor()) { elem *e = el_una(OPucall, TYvoid, el_var(s)); ector = el_combine(ector, e); } // If static destructor if (isStaticDestructor()) { elem *e; #if STATICCTOR e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s)); ector = el_combine(ector, e); dtorcount++; #else StaticDtorDeclaration *f = isStaticDtorDeclaration(); assert(f); if (f->vgate) { /* Increment destructor's vgate at construction time */ ectorgates.push(f); } e = el_una(OPucall, TYvoid, el_var(s)); edtor = el_combine(e, edtor); #endif } // If unit test if (isUnitTestDeclaration()) { elem *e = el_una(OPucall, TYvoid, el_var(s)); etest = el_combine(etest, e); } if (global.errors) return; writefunc(s); if (isExport()) obj_export(s, Poffset); for (i = 0; i < irs.deferToObj->dim; i++) { Dsymbol *s = (Dsymbol *)irs.deferToObj->data[i]; s->toObjFile(0); } #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS // A hack to get a pointer to this function put in the .dtors segment if (ident && memcmp(ident->toChars(), "_STD", 4) == 0) obj_staticdtor(s); #endif #if DMDV2 if (irs.startaddress) { printf("Setting start address\n"); obj_startaddress(irs.startaddress); } #endif }
void outdata(symbol *s) { #if HTOD return; #endif dt_t *dtstart,*dt; targ_size_t datasize,a; int seg; targ_size_t offset; int flags; char *p; tym_t ty; int tls; symbol_debug(s); #ifdef DEBUG debugy && dbg_printf("outdata('%s')\n",s->Sident); #endif //printf("outdata('%s', ty=x%x)\n",s->Sident,s->Stype->Tty); //symbol_print(s); // Data segment variables are always live on exit from a function s->Sflags |= SFLlivexit; dtstart = s->Sdt; s->Sdt = NULL; // it will be free'd #if SCPP && TARGET_WINDOS if (eecontext.EEcompile) { s->Sfl = (s->ty() & mTYfar) ? FLfardata : FLextern; s->Sseg = UNKNOWN; goto Lret; // don't output any data } #endif datasize = 0; tls = 0; ty = s->ty(); if (ty & mTYexport && config.wflags & WFexpdef && s->Sclass != SCstatic) obj_export(s,0); // export data definition for (dt = dtstart; dt; dt = dt->DTnext) { //printf("dt = %p, dt = %d\n",dt,dt->dt); switch (dt->dt) { case DT_abytes: { // Put out the data for the string, and // reserve a spot for a pointer to that string #if ELFOBJ || MACHOBJ datasize += size(dt->Dty); dt->DTabytes += elf_data_cdata(dt->DTpbytes,dt->DTnbytes,&dt->DTseg); #else targ_size_t *poffset; datasize += size(dt->Dty); if (tybasic(dt->Dty) == TYcptr) { seg = cseg; poffset = &Coffset; } #if SCPP else if (tybasic(dt->Dty) == TYfptr && dt->DTnbytes > config.threshold) { seg = obj_fardata(s->Sident,dt->DTnbytes,&offset); poffset = &offset; } #endif else { seg = DATA; poffset = &Doffset; } dt->DTseg = seg; dt->DTabytes += *poffset; obj_bytes(seg,*poffset,dt->DTnbytes,dt->DTpbytes); *poffset += dt->DTnbytes; #endif break; } case DT_ibytes: datasize += dt->DTn; break; case DT_nbytes: //printf("DT_nbytes %d\n", dt->DTnbytes); datasize += dt->DTnbytes; break; case DT_symsize: #if MARS assert(0); #else dt->DTazeros = type_size(s->Stype); #endif goto case_azeros; case DT_azeros: /* A block of zeros */ //printf("DT_azeros %d\n", dt->DTazeros); case_azeros: datasize += dt->DTazeros; if (dt == dtstart && !dt->DTnext && s->Sclass != SCcomdat) { /* first and only, so put in BSS segment */ switch (ty & mTYLINK) { #if OMFOBJ case mTYfar: // if far data seg = obj_fardata(s->Sident,datasize,&s->Soffset); s->Sfl = FLfardata; break; #endif case mTYcs: seg = cseg; Coffset = align(datasize,Coffset); s->Soffset = Coffset; Coffset += datasize; s->Sfl = FLcsdata; break; case mTYthread: { seg_data *pseg = obj_tlsseg_bss(); #if ELFOBJ || MACHOBJ s->Sseg = pseg->SDseg; elf_data_start(s, datasize, pseg->SDseg); obj_lidata(pseg->SDseg, pseg->SDoffset, datasize); #else targ_size_t TDoffset = pseg->SDoffset; TDoffset = align(datasize,TDoffset); s->Soffset = TDoffset; TDoffset += datasize; pseg->SDoffset = TDoffset; #endif seg = pseg->SDseg; s->Sfl = FLtlsdata; tls = 1; break; } default: #if ELFOBJ || MACHOBJ seg = elf_data_start(s,datasize,UDATA); obj_lidata(s->Sseg,s->Soffset,datasize); #else seg = UDATA; UDoffset = align(datasize,UDoffset); s->Soffset = UDoffset; UDoffset += datasize; #endif s->Sfl = FLudata; // uninitialized data break; } #if ELFOBJ || MACHOBJ assert(s->Sseg != UNKNOWN); if (s->Sclass == SCglobal || s->Sclass == SCstatic) objpubdef(s->Sseg,s,s->Soffset); /* do the definition */ /* if a pubdef to be done */ #else s->Sseg = seg; if (s->Sclass == SCglobal) /* if a pubdef to be done */ objpubdef(seg,s,s->Soffset); /* do the definition */ #endif searchfixlist(s); if (config.fulltypes && !(s->Sclass == SCstatic && funcsym_p)) // not local static cv_outsym(s); #if SCPP out_extdef(s); #endif goto Lret; } break; case DT_common: assert(!dt->DTnext); outcommon(s,dt->DTazeros); goto Lret; case DT_xoff: { symbol *sb = dt->DTsym; if (tyfunc(sb->ty())) #if SCPP nwc_mustwrite(sb); #else ; #endif else if (sb->Sdt) // if initializer for symbol outdata(sb); // write out data for symbol } case DT_coff: datasize += size(dt->Dty); break; case DT_1byte: datasize++; break; default: #ifdef DEBUG dbg_printf("dt = %p, dt = %d\n",dt,dt->dt); #endif assert(0); } }
void FuncDeclaration::toObjFile(int multiobj) { FuncDeclaration *func = this; ClassDeclaration *cd = func->parent->isClassDeclaration(); int reverse; int has_arguments; //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars()); //if (type) printf("type = %s\n", func->type->toChars()); #if 0 //printf("line = %d\n",func->getWhere() / LINEINC); EEcontext *ee = env->getEEcontext(); if (ee->EEcompile == 2) { if (ee->EElinnum < (func->getWhere() / LINEINC) || ee->EElinnum > (func->endwhere / LINEINC) ) return; // don't compile this function ee->EEfunc = func->toSymbol(); } #endif if (semanticRun >= PASSobj) // if toObjFile() already run return; // If errors occurred compiling it, such as bugzilla 6118 if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror) return; if (!func->fbody) { return; } if (func->isUnitTestDeclaration() && !global.params.useUnitTests) return; if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration()) { obj_append(this); return; } assert(semanticRun == PASSsemantic3done); semanticRun = PASSobj; if (global.params.verbose) printf("function %s\n",func->toChars()); Symbol *s = func->toSymbol(); func_t *f = s->Sfunc; #if TARGET_WINDOS /* This is done so that the 'this' pointer on the stack is the same * distance away from the function parameters, so that an overriding * function can call the nested fdensure or fdrequire of its overridden function * and the stack offsets are the same. */ if (isVirtual() && (fensure || frequire)) f->Fflags3 |= Ffakeeh; #endif #if TARGET_OSX s->Sclass = SCcomdat; #else s->Sclass = SCglobal; #endif for (Dsymbol *p = parent; p; p = p->parent) { if (p->isTemplateInstance()) { s->Sclass = SCcomdat; break; } } /* Vector operations should be comdat's */ if (isArrayOp) s->Sclass = SCcomdat; if (isNested()) { // if (!(config.flags3 & CFG3pic)) // s->Sclass = SCstatic; f->Fflags3 |= Fnested; } else { const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; // Pull in RTL startup code if (func->isMain()) { objextdef("_main"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS obj_ehsections(); // initialize exception handling sections #endif #if TARGET_WINDOS objextdef("__acrtused_con"); #endif obj_includelib(libname); s->Sclass = SCglobal; } else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc) { #if TARGET_WINDOS objextdef("__acrtused_con"); // bring in C startup code obj_includelib("snn.lib"); // bring in C runtime library #endif s->Sclass = SCglobal; } else if (func->isWinMain()) { objextdef("__acrtused"); obj_includelib(libname); s->Sclass = SCglobal; } // Pull in RTL startup code else if (func->isDllMain()) { objextdef("__acrtused_dll"); obj_includelib(libname); s->Sclass = SCglobal; } } cstate.CSpsymtab = &f->Flocsym; // Find module m for this function Module *m = NULL; for (Dsymbol *p = parent; p; p = p->parent) { m = p->isModule(); if (m) break; } IRState irs(m, func); Dsymbols deferToObj; // write these to OBJ file later irs.deferToObj = &deferToObj; TypeFunction *tf; enum RET retmethod; symbol *shidden = NULL; Symbol *sthis = NULL; tym_t tyf; tyf = tybasic(s->Stype->Tty); //printf("linkage = %d, tyf = x%x\n", linkage, tyf); reverse = tyrevfunc(s->Stype->Tty); assert(func->type->ty == Tfunction); tf = (TypeFunction *)(func->type); has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1); retmethod = tf->retStyle(); if (retmethod == RETstack) { // If function returns a struct, put a pointer to that // as the first argument ::type *thidden = tf->next->pointerTo()->toCtype(); char hiddenparam[5+4+1]; static int hiddenparami; // how many we've generated so far sprintf(hiddenparam,"__HID%d",++hiddenparami); shidden = symbol_name(hiddenparam,SCparameter,thidden); shidden->Sflags |= SFLtrue | SFLfree; #if DMDV1 if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref) #else if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim) #endif type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile); irs.shidden = shidden; this->shidden = shidden; } else { // Register return style cannot make nrvo. // Auto functions keep the nrvo_can flag up to here, // so we should eliminate it before entering backend. nrvo_can = 0; } if (vthis) { assert(!vthis->csym); sthis = vthis->toSymbol(); irs.sthis = sthis; if (!(f->Fflags3 & Fnested)) f->Fflags3 |= Fmember; } Symbol **params; unsigned pi; // Estimate number of parameters, pi pi = (v_arguments != NULL); if (parameters) pi += parameters->dim; // Allow extra 2 for sthis and shidden params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *)); // Get the actual number of parameters, pi, and fill in the params[] pi = 0; if (v_arguments) { params[pi] = v_arguments->toSymbol(); pi += 1; } if (parameters) { for (size_t i = 0; i < parameters->dim; i++) { VarDeclaration *v = (*parameters)[i]; if (v->csym) { error("compiler error, parameter '%s', bugzilla 2962?", v->toChars()); assert(0); } params[pi + i] = v->toSymbol(); } pi += parameters->dim; } if (reverse) { // Reverse params[] entries for (size_t i = 0; i < pi/2; i++) { Symbol *sptmp = params[i]; params[i] = params[pi - 1 - i]; params[pi - 1 - i] = sptmp; } } if (shidden) { #if 0 // shidden becomes last parameter params[pi] = shidden; #else // shidden becomes first parameter memmove(params + 1, params, pi * sizeof(params[0])); params[0] = shidden; #endif pi++; } if (sthis) { #if 0 // sthis becomes last parameter params[pi] = sthis; #else // sthis becomes first parameter memmove(params + 1, params, pi * sizeof(params[0])); params[0] = sthis; #endif pi++; } if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) && linkage != LINKd && shidden && sthis) { /* swap shidden and sthis */ Symbol *sp = params[0]; params[0] = params[1]; params[1] = sp; } for (size_t i = 0; i < pi; i++) { Symbol *sp = params[i]; sp->Sclass = SCparameter; sp->Sflags &= ~SFLspill; sp->Sfl = FLpara; symbol_add(sp); } // Determine register assignments if (pi) { size_t numintegerregs = 0, numfloatregs = 0; const unsigned char* argregs = getintegerparamsreglist(tyf, &numintegerregs); const unsigned char* floatregs = getfloatparamsreglist(tyf, &numfloatregs); // Order of assignment of pointer or integer parameters int r = 0; int xmmcnt = 0; for (size_t i = 0; i < pi; i++) { Symbol *sp = params[i]; tym_t ty = tybasic(sp->Stype->Tty); // BUG: doesn't work for structs if (r < numintegerregs) { if ((I64 || (i == 0 && (tyf == TYjfunc || tyf == TYmfunc))) && type_jparam(sp->Stype)) { sp->Sclass = SCfastpar; sp->Spreg = argregs[r]; sp->Sfl = FLauto; ++r; } } if (xmmcnt < numfloatregs) { if (tyxmmreg(ty)) { sp->Sclass = SCfastpar; sp->Spreg = floatregs[xmmcnt]; sp->Sfl = FLauto; ++xmmcnt; } } } } if (func->fbody) { block *b; Blockx bx; Statement *sbody; localgot = NULL; sbody = func->fbody; memset(&bx,0,sizeof(bx)); bx.startblock = block_calloc(); bx.curblock = bx.startblock; bx.funcsym = s; bx.scope_index = -1; bx.classdec = cd; bx.member = func; bx.module = getModule(); irs.blx = &bx; #if DMDV2 buildClosure(&irs); #endif #if 0 if (func->isSynchronized()) { if (cd) { elem *esync; if (func->isStatic()) { // monitor is in ClassInfo esync = el_ptr(cd->toSymbol()); } else { // 'this' is the monitor esync = el_var(sthis); } if (func->isStatic() || sbody->usesEH() || !(config.flags2 & CFG2seh)) { // BUG: what if frequire or fensure uses EH? sbody = new SynchronizedStatement(func->loc, esync, sbody); } else { #if TARGET_WINDOS if (config.flags2 & CFG2seh) { /* The "jmonitor" uses an optimized exception handling frame * which is a little shorter than the more general EH frame. * It isn't strictly necessary. */ s->Sfunc->Fflags3 |= Fjmonitor; } #endif el_free(esync); } } else { error("synchronized function %s must be a member of a class", func->toChars()); } } #elif TARGET_WINDOS if (func->isSynchronized() && cd && config.flags2 & CFG2seh && !func->isStatic() && !sbody->usesEH()) { /* The "jmonitor" hack uses an optimized exception handling frame * which is a little shorter than the more general EH frame. */ s->Sfunc->Fflags3 |= Fjmonitor; } #endif sbody->toIR(&irs); bx.curblock->BC = BCret; f->Fstartblock = bx.startblock; // einit = el_combine(einit,bx.init); if (isCtorDeclaration()) { assert(sthis); for (b = f->Fstartblock; b; b = b->Bnext) { if (b->BC == BCret) { b->BC = BCretexp; b->Belem = el_combine(b->Belem, el_var(sthis)); } } } } // If static constructor #if DMDV2 if (isSharedStaticCtorDeclaration()) // must come first because it derives from StaticCtorDeclaration { ssharedctors.push(s); } else #endif if (isStaticCtorDeclaration()) { sctors.push(s); } // If static destructor #if DMDV2 if (isSharedStaticDtorDeclaration()) // must come first because it derives from StaticDtorDeclaration { SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration(); assert(f); if (f->vgate) { /* Increment destructor's vgate at construction time */ esharedctorgates.push(f); } sshareddtors.shift(s); } else #endif if (isStaticDtorDeclaration()) { StaticDtorDeclaration *f = isStaticDtorDeclaration(); assert(f); if (f->vgate) { /* Increment destructor's vgate at construction time */ ectorgates.push(f); } sdtors.shift(s); } // If unit test if (isUnitTestDeclaration()) { stests.push(s); } if (global.errors) return; writefunc(s); if (isExport()) obj_export(s, Poffset); for (size_t i = 0; i < irs.deferToObj->dim; i++) { Dsymbol *s = (*irs.deferToObj)[i]; FuncDeclaration *fd = s->isFuncDeclaration(); if (fd) { FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration(); if (fdp && fdp->semanticRun < PASSobj) { /* Bugzilla 7595 * FuncDeclaration::buildClosure() relies on nested functions * being toObjFile'd after the outer function. Otherwise, the * v->offset's for the closure variables are wrong. * So, defer fd until after fdp is done. */ fdp->deferred.push(fd); continue; } } s->toObjFile(0); } for (size_t i = 0; i < deferred.dim; i++) { FuncDeclaration *fd = deferred[i]; fd->toObjFile(0); } #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS // A hack to get a pointer to this function put in the .dtors segment if (ident && memcmp(ident->toChars(), "_STD", 4) == 0) obj_staticdtor(s); #endif #if DMDV2 if (irs.startaddress) { printf("Setting start address\n"); obj_startaddress(irs.startaddress); } #endif }
void op_export(t_node *node) { obj_export(NULL); }