Symbol *objc_getMsgSend(Type *ret, bool hasHiddenArg) { if (hasHiddenArg) { if (!objc_smsgSend_stret) objc_smsgSend_stret = symbol_name("_objc_msgSend_stret", SCglobal, type_fake(TYhfunc)); return objc_smsgSend_stret; } // not sure if DMD can handle this else if (ret->ty == Tcomplex80) { if (!objc_smsgSend_fp2ret) objc_smsgSend_fp2ret = symbol_name("_objc_msgSend_fp2ret", SCglobal, type_fake(TYnfunc)); return objc_smsgSend_fp2ret; } else if (ret->ty == Tfloat80) { if (!objc_smsgSend_fpret) objc_smsgSend_fpret = symbol_name("_objc_msgSend_fpret", SCglobal, type_fake(TYnfunc)); return objc_smsgSend_fpret; } else { if (!objc_smsgSend) objc_smsgSend = symbol_name("_objc_msgSend", SCglobal, type_fake(TYnfunc)); return objc_smsgSend; } assert(0); return NULL; }
void rtlsym_init() { static int inited; if (!inited) { inited++; //printf("rtlsym_init(%s)\n", regm_str(FREGSAVED)); #if MARS type *t = type_fake(TYnfunc); t->Tmangle = mTYman_c; t->Tcount++; // Variadic function type *tv = type_fake(TYnfunc); tv->Tmangle = mTYman_c; tv->Tcount++; #endif // Only used by dmd1 for RTLSYM_THROW type *tw = NULL; #undef SYMBOL_Z #define SYMBOL_Z(e, fl, regsaved, n, flags, t) \ rtlsym[RTLSYM_##e] = symbolz(n, t, fl, flags, regsaved); RTLSYMS }
void rtlsym_init() { static int inited; if (!inited) { inited++; //printf("rtlsym_init(%s)\n", regm_str(FREGSAVED)); for (int i = 0; i < RTLSYM_MAX; i++) { rtlsym[i] = &rtlsym2[i]; #ifdef DEBUG rtlsym[i]->id = IDsymbol; #endif rtlsym[i]->Stype = tsclib; rtlsym[i]->Ssymnum = -1; rtlsym[i]->Sclass = SCextern; rtlsym[i]->Sfl = FLfunc; #if ELFOBJ || MACHOBJ rtlsym[i]->obj_si = (unsigned)-1; rtlsym[i]->dwarf_off = (unsigned)-1; #endif rtlsym[i]->Sregsaved = FREGSAVED; } #if MARS type *t = type_fake(LARGECODE ? TYffunc : TYnfunc); t->Tmangle = mTYman_c; t->Tcount++; // Variadic function type *tv = type_fake(LARGECODE ? TYffunc : TYnfunc); tv->Tmangle = mTYman_c; tv->Tcount++; #endif #if MACHOBJ type *tw = type_fake(TYnpfunc); tw->Tmangle = mTYman_sys; tw->Tcount++; #else type *tw = NULL; #endif #undef SYMBOL_Z #define SYMBOL_Z(e, fl, saved, n, flags, ty) \ if (ty) rtlsym[RTLSYM_##e]->Stype = ty; \ if (fl != FLfunc) rtlsym[RTLSYM_##e]->Sfl = fl; \ if (flags) rtlsym[RTLSYM_##e]->Sflags = flags; \ if (saved != FREGSAVED) rtlsym[RTLSYM_##e]->Sregsaved = saved; \ strcpy(rtlsym[RTLSYM_##e]->Sident, n); \ RTLSYMS }
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; }
Symbol *objc_getMethVarRef(const char *s, size_t len) { objc_hasSymbols = true; StringValue *sv = objc_smethVarRefTable->update(s, len); Symbol *refsymbol = (Symbol *) sv->ptrvalue; if (refsymbol == NULL) { // create data dt_t *dt = NULL; Symbol *sselname = objc_getMethVarName(s, len); dtxoff(&dt, sselname, 0, TYnptr); // find segment int seg = objc_getSegment(SEGselrefs); // create symbol static size_t selcount = 0; char namestr[42]; sprintf(namestr, "L_OBJC_SELECTOR_REFERENCES_%lu", selcount); refsymbol = symbol_name(namestr, SCstatic, type_fake(TYnptr)); refsymbol->Sdt = dt; refsymbol->Sseg = seg; outdata(refsymbol); sv->ptrvalue = refsymbol; ++selcount; } return refsymbol; }
void Module::genhelpers(bool iscomdat) { // 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_DASSERT; bc = BCexit; break; case 2: ma = munittest; rt = RTLSYM_DUNITTEST; 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 = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar; FuncParamRegs fpr(TYjfunc); fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2); sp->Sflags &= ~SFLspill; sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast; cstate.CSpsymtab = &ma->Sfunc->Flocsym; symbol_add(sp); elinnum = el_var(sp); } elem *efilename = toEfilename(this); 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 = iscomdat ? SCcomdat : SCglobal; ma->Sfl = 0; ma->Sflags |= rtlsym[rt]->Sflags & SFLexit; writefunc(ma); } } }
type *Type::toCtype() { if (!ctype) { ctype = type_fake(totym()); ctype->Tcount++; } return ctype; }
symbol *symboldata(targ_size_t offset,tym_t ty) { symbol *s = symbol_generate(SClocstat, type_fake(ty)); s->Sfl = FLdata; s->Soffset = offset; symbol_keep(s); // keep around return s; }
static void genhelpers(Module *m) { // If module assert for (int i = 0; i < 3; i++) { Symbol *ma; unsigned rt; unsigned bc; switch (i) { case 0: ma = toModuleArray(m); rt = RTLSYM_DARRAY; bc = BCexit; break; case 1: ma = toModuleAssert(m); rt = RTLSYM_DASSERT; bc = BCexit; break; case 2: ma = toModuleUnittest(m); rt = RTLSYM_DUNITTEST; bc = BCret; break; default: assert(0); } if (!ma) continue; 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 = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar; FuncParamRegs fpr(TYjfunc); fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2); sp->Sflags &= ~SFLspill; sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast; cstate.CSpsymtab = &ma->Sfunc->Flocsym; symbol_add(sp); elem *elinnum = el_var(sp); elem *efilename = toEfilename(m); if (config.exe == EX_WIN64) efilename = addressElem(efilename, Type::tstring, true); elem *e = el_var(getRtlsym(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 = m->arg; ma->Sfunc->Fstartblock = b; ma->Sclass = SCglobal; ma->Sfl = 0; ma->Sflags |= getRtlsym(rt)->Sflags & SFLexit; writefunc(ma); } }
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; }
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 *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; }
/** * Creates the data symbol for a TLS variable for Mach-O. * * Input: * vd the variable declaration for the symbol * s the regular symbol for the variable * * Returns: the newly create symbol */ Symbol *createTLVDataSymbol(VarDeclaration *vd, Symbol *s) { assert(config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread); OutBuffer buffer; buffer.writestring(s->Sident); buffer.write("$tlv$init", 9); const char *tlvInitName = buffer.extractString(); Symbol *tlvInit = symbol_name(tlvInitName, SCstatic, type_fake(vd->type->ty)); tlvInit->Sdt = NULL; tlvInit->Salignment = type_alignsize(s->Stype); type_setty(&tlvInit->Stype, tlvInit->Stype->Tty | mTYthreadData); type_setmangle(&tlvInit->Stype, mangle(vd, tlvInit)); return tlvInit; }
elem *toEfilename(Module *m) { elem *efilename; if (!m->sfilename) { dt_t *dt = NULL; char *id = m->srcfile->toChars(); size_t len = strlen(id); dtsize_t(&dt, len); dtabytes(&dt,TYnptr, 0, len + 1, id); m->sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); m->sfilename->Sdt = dt; m->sfilename->Sfl = FLdata; out_readonly(m->sfilename); outdata(m->sfilename); } efilename = (config.exe == EX_WIN64) ? el_ptr(m->sfilename) : el_var(m->sfilename); return efilename; }
/** * Creates the data symbol used to initialize a TLS variable for Mach-O. * * Params: * vd = the variable declaration for the symbol * s = the back end symbol corresponding to vd * * Returns: the newly created symbol */ Symbol *createTLVDataSymbol(VarDeclaration *vd, Symbol *s) { assert(config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread); // Compute identifier for tlv symbol OutBuffer buffer; buffer.writestring(s->Sident); buffer.write("$tlv$init", 9); const char *tlvInitName = buffer.peekString(); // Compute type for tlv symbol type *t = type_fake(vd->type->ty); type_setty(&t, t->Tty | mTYthreadData); type_setmangle(&t, mangle(vd)); Symbol *tlvInit = symbol_name(tlvInitName, SCstatic, t); tlvInit->Sdt = NULL; tlvInit->Salignment = type_alignsize(s->Stype); if (vd->linkage == LINKcpp) tlvInit->Sflags |= SFLpublic; return tlvInit; }
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; }
elem *Module::toEfilename() { elem *efilename; if (!sfilename) { dt_t *dt = NULL; char *id; int len; id = srcfile->toChars(); len = strlen(id); dtsize_t(&dt, len); dtabytes(&dt,TYnptr, 0, len + 1, id); sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); sfilename->Sdt = dt; sfilename->Sfl = FLdata; out_readonly(sfilename); outdata(sfilename); } efilename = el_var(sfilename); return efilename; }
Symbol *VarDeclaration::toSymbol() { //printf("VarDeclaration::toSymbol(%s)\n", toChars()); //if (needThis()) *(char*)0=0; assert(!needThis()); if (!csym) { Symbol *s; TYPE *t; const char *id; mangle_t m = 0; if (isDataseg()) id = mangle(); else id = ident->toChars(); s = symbol_calloc(id); if (storage_class & STCout) t = type_fake(TYnptr); else if (isParameter()) t = type->toCParamtype(); else t = type->toCtype(); t->Tcount++; if (isDataseg()) { s->Sclass = SCextern; s->Sfl = FLextern; slist_add(s); } else { s->Sclass = SCauto; s->Sfl = FLauto; if (nestedref) { /* Symbol is accessed by a nested function. Make sure * it is not put in a register, and that the optimizer * assumes it is modified across function calls and pointer * dereferences. */ //printf("\tnested ref, not register\n"); type_setcv(&t, t->Tty | mTYvolatile); } } if (storage_class & STCconst) { // Insert const modifiers tym_t tym = 0; if (storage_class & STCconst) tym |= mTYconst; type_setcv(&t, tym); } switch (linkage) { case LINKwindows: m = mTYman_std; break; case LINKpascal: m = mTYman_pas; break; case LINKc: m = mTYman_c; break; case LINKd: m = mTYman_d; break; case LINKcpp: m = mTYman_cpp; break; default: printf("linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); s->Stype = t; csym = s; } return csym; }
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 */ }
/**************************************** * Return type index for a aarray of type Value[Key] * Input: * t associative array type * keyidx key type * validx value type */ idx_t cv8_daarray(type *t, idx_t keyidx, idx_t validx) { //printf("cv8_daarray(keyidx = %x, validx = %x)\n", keyidx, validx); /* Put out a struct: * struct dAssocArray { * void* ptr; * typedef key-type __key_t; * typedef val-type __val_t; * } */ #if 0 debtyp_t *d = debtyp_alloc(18); TOWORD(d->data, 0x100F); TOWORD(d->data + 2, OEM); TOWORD(d->data + 4, 2); // 2 = associative array TOLONG(d->data + 6, 2); // count of type indices to follow TOLONG(d->data + 10, keyidx); // key type TOLONG(d->data + 14, validx); // element type #else type *tv = type_fake(TYnptr); tv->Tcount++; idx_t pvidx = cv4_typidx(tv); type_free(tv); static const unsigned char fl[] = { 0x03, 0x12, // LF_FIELDLIST_V2 0x0d, 0x15, // LF_MEMBER_V3 0x03, 0x00, // attribute 0x00, 0x00, 0x00, 0x00, // void* 0x00, 0x00, // offset 'p','t','r',0, // "ptr" 0xf2, 0xf1, // align to 4-byte including field id // offset 18 0x10, 0x15, // LF_NESTTYPE_V3 0x00, 0x00, // padding 0x00, 0x00, 0x00, 0x00, // key type '_','_','k','e','y','_','t',0, // "__key_t" // offset 34 0x10, 0x15, // LF_NESTTYPE_V3 0x00, 0x00, // padding 0x00, 0x00, 0x00, 0x00, // value type '_','_','v','a','l','_','t',0, // "__val_t" }; debtyp_t *f = debtyp_alloc(sizeof(fl)); memcpy(f->data,fl,sizeof(fl)); TOLONG(f->data + 6, pvidx); TOLONG(f->data + 22, keyidx); TOLONG(f->data + 38, validx); idx_t fieldlist = cv_debtyp(f); const char *id = "dAssocArray"; int idlen = strlen(id); if (idlen > CV8_MAX_SYMBOL_LENGTH) idlen = CV8_MAX_SYMBOL_LENGTH; debtyp_t *d = debtyp_alloc(20 + idlen + 1); TOWORD(d->data, LF_STRUCTURE_V3); TOWORD(d->data + 2, 1); // count TOWORD(d->data + 4, 0); // property TOLONG(d->data + 6, fieldlist); TOLONG(d->data + 10, 0); // dList TOLONG(d->data + 14, 0); // vtshape TOWORD(d->data + 18, NPTRSIZE); // size memcpy(d->data + 20, id, idlen); d->data[20 + idlen] = 0; #endif return cv_debtyp(d); }
/**************************************** * Return type index for a delegate * Input: * t delegate type * functypidx type index for pointer to function */ idx_t cv8_ddelegate(type *t, idx_t functypidx) { //printf("cv8_ddelegate(functypidx = %x)\n", functypidx); /* Put out a struct: * struct dDelegate { * void* ptr; * function* funcptr; * } */ type *tv = type_fake(TYnptr); tv->Tcount++; idx_t pvidx = cv4_typidx(tv); type_free(tv); type *tp = type_pointer(t->Tnext); idx_t ptridx = cv4_typidx(tp); type_free(tp); #if 0 debtyp_t *d = debtyp_alloc(18); TOWORD(d->data, 0x100F); TOWORD(d->data + 2, OEM); TOWORD(d->data + 4, 3); // 3 = delegate TOLONG(d->data + 6, 2); // count of type indices to follow TOLONG(d->data + 10, key); // void* type TOLONG(d->data + 14, functypidx); // function type #else static const unsigned char fl[] = { 0x03, 0x12, // LF_FIELDLIST_V2 0x0d, 0x15, // LF_MEMBER_V3 0x03, 0x00, // attribute 0x00, 0x00, 0x00, 0x00, // void* 0x00, 0x00, // offset 'p','t','r',0, // "ptr" 0xf2, 0xf1, // align to 4-byte including length word before data 0x0d, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // ptrtypidx 0x08, 0x00, 'f', 'u','n','c','p','t','r', 0, // "funcptr" 0xf2, 0xf1, }; debtyp_t *f = debtyp_alloc(sizeof(fl)); memcpy(f->data,fl,sizeof(fl)); TOLONG(f->data + 6, pvidx); TOLONG(f->data + 22, ptridx); TOWORD(f->data + 26, NPTRSIZE); idx_t fieldlist = cv_debtyp(f); const char *id = "dDelegate"; int idlen = strlen(id); if (idlen > CV8_MAX_SYMBOL_LENGTH) idlen = CV8_MAX_SYMBOL_LENGTH; debtyp_t *d = debtyp_alloc(20 + idlen + 1); TOWORD(d->data, LF_STRUCTURE_V3); TOWORD(d->data + 2, 2); // count TOWORD(d->data + 4, 0); // property TOLONG(d->data + 6, fieldlist); TOLONG(d->data + 10, 0); // dList TOLONG(d->data + 14, 0); // vtshape TOWORD(d->data + 18, 2 * NPTRSIZE); // size memcpy(d->data + 20, id, idlen); d->data[20 + idlen] = 0; #endif return cv_debtyp(d); }
void visit(TypeStruct *t) { //printf("TypeStruct::toCtype() '%s'\n", t->sym->toChars()); Type *tm = t->mutableOf(); if (tm->ctype) { t->ctype = type_alloc(tybasic(tm->ctype->Tty)); t->ctype->Tcount++; if (t->ctype->Tty == TYstruct) { Symbol *s = tm->ctype->Ttag; t->ctype->Ttag = (Classsym *)s; // structure tag name } // 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 { StructDeclaration *sym = t->sym; if (sym->ident == Id::__c_long_double) { t->ctype = type_fake(TYdouble); t->ctype->Tcount++; return; } t->ctype = type_struct_class(sym->toPrettyChars(true), sym->alignsize, sym->structsize, sym->arg1type ? Type_toCtype(sym->arg1type) : NULL, sym->arg2type ? Type_toCtype(sym->arg2type) : NULL, sym->isUnionDeclaration() != 0, false, sym->isPOD() != 0); tm->ctype = t->ctype; /* Add in fields of the struct * (after setting ctype to avoid infinite recursion) */ if (global.params.symdebug) { for (size_t i = 0; i < sym->fields.dim; i++) { VarDeclaration *v = sym->fields[i]; symbol_struct_addField(t->ctype->Ttag, v->ident->toChars(), Type_toCtype(v->type), v->offset); } } } //printf("t = %p, Tflags = x%x\n", ctype, ctype->Tflags); }
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(); }
Symbol *VarDeclaration::toSymbol() { //printf("VarDeclaration::toSymbol(%s)\n", toChars()); //if (needThis()) *(char*)0=0; assert(!needThis()); if (!csym) { TYPE *t; const char *id; if (isDataseg()) id = mangle(); else id = ident->toChars(); Symbol *s = symbol_calloc(id); s->Salignment = alignment; if (storage_class & (STCout | STCref)) { // should be TYref, but problems in back end t = type_pointer(type->toCtype()); } else if (storage_class & STClazy) { if (config.exe == EX_WIN64 && isParameter()) t = type_fake(TYnptr); else t = type_fake(TYdelegate); // Tdelegate as C type t->Tcount++; } else if (isParameter()) { if (config.exe == EX_WIN64 && type->size(Loc()) > REGSIZE) { // should be TYref, but problems in back end t = type_pointer(type->toCtype()); } else { t = type->toCParamtype(); t->Tcount++; } } else { t = type->toCtype(); t->Tcount++; } if (isDataseg()) { if (isThreadlocal()) { /* Thread local storage */ TYPE *ts = t; ts->Tcount++; // make sure a different t is allocated type_setty(&t, t->Tty | mTYthread); ts->Tcount--; if (global.params.vtls) { char *p = loc.toChars(); fprintf(stderr, "%s: %s is thread local\n", p ? p : "", toChars()); if (p) mem.free(p); } } s->Sclass = SCextern; s->Sfl = FLextern; slist_add(s); /* if it's global or static, then it needs to have a qualified but unmangled name. * This gives some explanation of the separation in treating name mangling. * It applies to PDB format, but should apply to CV as PDB derives from CV. * http://msdn.microsoft.com/en-us/library/ff553493(VS.85).aspx */ s->prettyIdent = toPrettyChars(); } else { s->Sclass = SCauto; s->Sfl = FLauto; if (nestedrefs.dim) { /* Symbol is accessed by a nested function. Make sure * it is not put in a register, and that the optimizer * assumes it is modified across function calls and pointer * dereferences. */ //printf("\tnested ref, not register\n"); type_setcv(&t, t->Tty | mTYvolatile); } } if (ident == Id::va_argsave) /* __va_argsave is set outside of the realm of the optimizer, * so we tell the optimizer to leave it alone */ type_setcv(&t, t->Tty | mTYvolatile); mangle_t m = 0; switch (linkage) { case LINKwindows: m = mTYman_std; break; case LINKpascal: m = mTYman_pas; break; case LINKc: m = mTYman_c; break; case LINKd: m = mTYman_d; break; case LINKcpp: { m = mTYman_cpp; s->Sflags = SFLpublic; Dsymbol *parent = toParent(); ClassDeclaration *cd = parent->isClassDeclaration(); if (cd) { ::type *tc = cd->type->toCtype(); s->Sscope = tc->Tnext->Ttag; } StructDeclaration *sd = parent->isStructDeclaration(); if (sd) { ::type *ts = sd->type->toCtype(); s->Sscope = ts->Ttag; } break; } default: printf("linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); s->Stype = t; csym = s; } return csym; }
void genObjFile(Module *m, bool multiobj) { //EEcontext *ee = env->getEEcontext(); //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, m->toChars()); if (m->ident == Id::entrypoint) { bool v = global.params.verbose; global.params.verbose = false; for (size_t i = 0; i < m->members->dim; i++) { Dsymbol *member = (*m->members)[i]; //printf("toObjFile %s %s\n", member->kind(), member->toChars()); toObjFile(member, global.params.multiobj); } global.params.verbose = v; return; } lastmname = m->srcfile->toChars(); objmod->initfile(lastmname, NULL, m->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); if (m->doppelganger) { /* Generate a reference to the moduleinfo, so the module constructors * and destructors get linked in. */ Module *mod = m->aimports[0]; assert(mod); if (mod->sictor || mod->sctor || mod->sdtor || mod->ssharedctor || mod->sshareddtor) { Symbol *s = toSymbol(mod); //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 Symbol *sref = symbol_generate(SCstatic, type_fake(TYnptr)); sref->Sfl = FLdata; dtxoff(&sref->Sdt, s, 0, TYnptr); outdata(sref); #endif } } } if (global.params.cov) { /* Create coverage identifier: * private uint[numlines] __coverage; */ m->cov = symbol_calloc("__coverage"); m->cov->Stype = type_fake(TYint); m->cov->Stype->Tmangle = mTYman_c; m->cov->Stype->Tcount++; m->cov->Sclass = SCstatic; m->cov->Sfl = FLdata; dtnzeros(&m->cov->Sdt, 4 * m->numlines); outdata(m->cov); slist_add(m->cov); m->covb = (unsigned *)calloc((m->numlines + 32) / 32, sizeof(*m->covb)); } for (size_t i = 0; i < m->members->dim; i++) { Dsymbol *member = (*m->members)[i]; //printf("toObjFile %s %s\n", member->kind(), member->toChars()); toObjFile(member, 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; dtnbytes(&bcov->Sdt, (m->numlines + 32) / 32 * sizeof(*m->covb), (char *)m->covb); outdata(bcov); free(m->covb); m->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_function(TYnfunc, NULL, 0, false, tsvoid); t->Tmangle = mTYman_c; m->sictor = toSymbolX(m, "__modictor", SCglobal, t, "FZv"); cstate.CSpsymtab = &m->sictor->Sfunc->Flocsym; localgot = ictorlocalgot; elem *ecov = el_pair(TYdarray, el_long(TYsize_t, m->numlines), el_ptr(m->cov)); elem *ebcov = el_pair(TYdarray, el_long(TYsize_t, m->numlines), el_ptr(bcov)); if (config.exe == EX_WIN64) { ecov = addressElem(ecov, Type::tvoid->arrayOf(), false); ebcov = addressElem(ebcov, Type::tvoid->arrayOf(), false); } elem *efilename = toEfilename(m); if (config.exe == EX_WIN64) efilename = addressElem(efilename, Type::tstring, true); elem *e = el_params( el_long(TYuchar, global.params.covPercent), ecov, ebcov, efilename, NULL); e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER2]), 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; m->sictor->Sfunc->Fstartline.Sfilename = m->arg; m->sictor->Sfunc->Fstartblock = b; writefunc(m->sictor); } m->sctor = callFuncsAndGates(m, &sctors, &ectorgates, "__modctor"); m->sdtor = callFuncsAndGates(m, &sdtors, NULL, "__moddtor"); m->ssharedctor = callFuncsAndGates(m, &ssharedctors, (StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor"); m->sshareddtor = callFuncsAndGates(m, &sshareddtors, NULL, "__modshareddtor"); m->stest = callFuncsAndGates(m, &stests, NULL, "__modtest"); if (m->doppelganger) genModuleInfo(m); } if (m->doppelganger) { objmod->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(m); toModuleUnittest(m); toModuleArray(m); } /* Always generate module info, because of templates and -cov. * But module info needs the runtime library, so disable it for betterC. */ if (!global.params.betterC /*|| needModuleInfo()*/) genModuleInfo(m); genhelpers(m, false); objmod->termfile(); }
void visit(Type *t) { t->ctype = type_fake(totym(t)); t->ctype->Tcount++; }
void Module::genobjfile(int multiobj) { //EEcontext *ee = env->getEEcontext(); //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars()); lastmname = srcfile->toChars(); objmod->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 Symbol *sref = symbol_generate(SCstatic, type_fake(TYnptr)); sref->Sfl = FLdata; dtxoff(&sref->Sdt, s, 0, TYnptr); outdata(sref); #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; 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]; //printf("toObjFile %s %s\n", member->kind(), member->toChars()); 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; 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_function(TYnfunc, NULL, 0, false, tsvoid); t->Tmangle = mTYman_c; sictor = toSymbolX("__modictor", SCglobal, t, "FZv"); cstate.CSpsymtab = &sictor->Sfunc->Flocsym; localgot = ictorlocalgot; elem *ecov = el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(cov)); elem *ebcov = el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(bcov)); if (config.exe == EX_WIN64) { ecov = addressElem(ecov, Type::tvoid->arrayOf(), false); ebcov = addressElem(ebcov, Type::tvoid->arrayOf(), false); } elem *e = el_params( el_long(TYuchar, global.params.covPercent), ecov, ebcov, toEfilename(), NULL); e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER2]), 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) { objmod->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(); } /* Always generate module info, because of templates and -cov. * But module info needs the runtime library, so disable it for betterC. */ if (!global.params.betterC /*|| needModuleInfo()*/) genmoduleinfo(); // 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 = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar; FuncParamRegs fpr(TYjfunc); fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2); sp->Sflags &= ~SFLspill; sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast; 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); } } objmod->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(); }
void visit(TryCatchStatement *s) { Blockx *blx = irs->blx; #if SEH if (!global.params.is64bit) nteh_declarvars(blx); #endif IRState mystate(irs, s); block *tryblock = block_goto(blx,BCgoto,NULL); int previndex = blx->scope_index; tryblock->Blast_index = previndex; blx->scope_index = tryblock->Bscope_index = blx->next_index++; // Set the current scope index setScopeIndex(blx,tryblock,tryblock->Bscope_index); // This is the catch variable tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr)); blx->tryblock = tryblock; block *breakblock = block_calloc(blx); block_goto(blx,BC_try,NULL); if (s->_body) { Statement_toIR(s->_body, &mystate); } blx->tryblock = tryblock->Btry; // break block goes here block_goto(blx, BCgoto, breakblock); setScopeIndex(blx,blx->curblock, previndex); blx->scope_index = previndex; // create new break block that follows all the catches breakblock = block_calloc(blx); blx->curblock->appendSucc(breakblock); block_next(blx,BCgoto,NULL); assert(s->catches); for (size_t i = 0 ; i < s->catches->dim; i++) { Catch *cs = (*s->catches)[i]; if (cs->var) cs->var->csym = tryblock->jcatchvar; block *bcatch = blx->curblock; if (cs->type) bcatch->Bcatchtype = toSymbol(cs->type->toBasetype()); tryblock->appendSucc(bcatch); block_goto(blx, BCjcatch, NULL); if (cs->handler != NULL) { IRState catchState(irs, s); /* Append to block: * *(sclosure + cs.offset) = cs; */ if (cs->var && cs->var->offset) { tym_t tym = totym(cs->var->type); elem *ex = el_var(irs->sclosure); ex = el_bin(OPadd, TYnptr, ex, el_long(TYsize_t, cs->var->offset)); ex = el_una(OPind, tym, ex); ex = el_bin(OPeq, tym, ex, el_var(toSymbol(cs->var))); block_appendexp(catchState.blx->curblock, ex); } Statement_toIR(cs->handler, &catchState); } blx->curblock->appendSucc(breakblock); block_next(blx, BCgoto, NULL); } block_next(blx,(enum BC)blx->curblock->BC, breakblock); }
void visit(SwitchStatement *s) { int string; Blockx *blx = irs->blx; //printf("SwitchStatement::toIR()\n"); IRState mystate(irs,s); mystate.switchBlock = blx->curblock; /* Block for where "break" goes to */ mystate.breakBlock = block_calloc(blx); /* Block for where "default" goes to. * If there is a default statement, then that is where default goes. * If not, then do: * default: break; * by making the default block the same as the break block. */ mystate.defaultBlock = s->sdefault ? block_calloc(blx) : mystate.breakBlock; size_t numcases = 0; if (s->cases) numcases = s->cases->dim; incUsage(irs, s->loc); elem *econd = toElemDtor(s->condition, &mystate); if (s->hasVars) { /* Generate a sequence of if-then-else blocks for the cases. */ if (econd->Eoper != OPvar) { elem *e = exp2_copytotemp(econd); block_appendexp(mystate.switchBlock, e); econd = e->E2; } for (size_t i = 0; i < numcases; i++) { CaseStatement *cs = (*s->cases)[i]; elem *ecase = toElemDtor(cs->exp, &mystate); elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase); block *b = blx->curblock; block_appendexp(b, e); Label *clabel = getLabel(irs, blx, cs); block_next(blx, BCiftrue, NULL); b->appendSucc(clabel->lblock); b->appendSucc(blx->curblock); } /* The final 'else' clause goes to the default */ block *b = blx->curblock; block_next(blx, BCgoto, NULL); b->appendSucc(mystate.defaultBlock); Statement_toIR(s->_body, &mystate); /* Have the end of the switch body fall through to the block * following the switch statement. */ block_goto(blx, BCgoto, mystate.breakBlock); return; } if (s->condition->type->isString()) { // Number the cases so we can unscramble things after the sort() for (size_t i = 0; i < numcases; i++) { CaseStatement *cs = (*s->cases)[i]; cs->index = i; } s->cases->sort(); /* Create a sorted array of the case strings, and si * will be the symbol for it. */ dt_t *dt = NULL; Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray)); dtsize_t(&dt, numcases); dtxoff(&dt, si, Target::ptrsize * 2, TYnptr); for (size_t i = 0; i < numcases; i++) { CaseStatement *cs = (*s->cases)[i]; if (cs->exp->op != TOKstring) { s->error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert } else { StringExp *se = (StringExp *)(cs->exp); Symbol *si = toStringSymbol((char *)se->string, se->len, se->sz); dtsize_t(&dt, se->len); dtxoff(&dt, si, 0); } } si->Sdt = dt; si->Sfl = FLdata; outdata(si); /* Call: * _d_switch_string(string[] si, string econd) */ if (config.exe == EX_WIN64) econd = addressElem(econd, s->condition->type, true); elem *eparam = el_param(econd, (config.exe == EX_WIN64) ? el_ptr(si) : el_var(si)); switch (s->condition->type->nextOf()->ty) { case Tchar: econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_STRING)), eparam); break; case Twchar: econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_USTRING)), eparam); break; case Tdchar: // BUG: implement econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_DSTRING)), eparam); break; default: assert(0); } elem_setLoc(econd, s->loc); string = 1; } else string = 0; block_appendexp(mystate.switchBlock, econd); block_next(blx,BCswitch,NULL); // Corresponding free is in block_free targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1)); mystate.switchBlock->BS.Bswitch = pu; /* First pair is the number of cases, and the default block */ *pu++ = numcases; mystate.switchBlock->appendSucc(mystate.defaultBlock); /* Fill in the first entry in each pair, which is the case value. * CaseStatement::toIR() will fill in * the second entry for each pair with the block. */ for (size_t i = 0; i < numcases; i++) { CaseStatement *cs = (*s->cases)[i]; if (string) { pu[cs->index] = i; } else { pu[i] = cs->exp->toInteger(); } } Statement_toIR(s->_body, &mystate); /* Have the end of the switch body fall through to the block * following the switch statement. */ block_goto(blx, BCgoto, mystate.breakBlock); }