type *type_static_array(targ_size_t dim, type *tnext) { type *t = type_allocn(TYarray, tnext); t->Tdim = dim; t->Tcount++; return t; }
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; }
type *TypeFunction::toCtype() { if (!ctype) { size_t nparams = Parameter::dim(parameters); type *tmp[10]; type **ptypes = tmp; if (nparams > 10) ptypes = (type **)malloc(sizeof(type*) * nparams); for (size_t i = 0; i < nparams; i++) { Parameter *arg = Parameter::getNth(parameters, i); type *tp = arg->type->toCtype(); if (arg->storageClass & (STCout | STCref)) tp = type_allocn(TYref, tp); ptypes[i] = tp; } type* tnext = next ? next->toCtype() : tsvoid; ctype = type_function(totym(), ptypes, nparams, varargs == 1, tnext); if (nparams > 10) free(ptypes); } return ctype; }
void visit(TypeFunction *t) { size_t nparams = Parameter::dim(t->parameters); type *tmp[10]; type **ptypes = tmp; if (nparams > 10) ptypes = (type **)malloc(sizeof(type*) * nparams); for (size_t i = 0; i < nparams; i++) { Parameter *p = Parameter::getNth(t->parameters, i); type *tp = Type_toCtype(p->type); if (p->storageClass & (STCout | STCref)) tp = type_allocn(TYref, tp); else if (p->storageClass & STClazy) { // Mangle as delegate type *tf = type_function(TYnfunc, NULL, 0, false, tp); tp = type_delegate(tf); } ptypes[i] = tp; } t->ctype = type_function(totym(t), ptypes, nparams, t->varargs == 1, Type_toCtype(t->next)); if (nparams > 10) free(ptypes); }
type *type_assoc_array(type *tkey, type *tvalue) { type *t = type_allocn(TYaarray, tvalue); t->Tkey = tkey; tkey->Tcount++; t->Tcount++; 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; }
type *TypeSArray::toCtype() { if (!ctype) { type *tn; tn = next->toCtype(); ctype = type_allocn(TYarray, tn); ctype->Tdim = dim->toInteger(); } return ctype; }
type *type_allocmemptr(Classsym *stag,type *tn) { type *t; symbol_debug(stag); assert(stag->Sclass == SCstruct || tybasic(stag->Stype->Tty) == TYident); t = type_allocn(TYmemptr,tn); t->Ttag = stag; //printf("type_allocmemptr() = %p\n", t); //type_print(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; }
/*************************************** * Create an enum type. * Input: * name name of enum * tbase "base" type of enum * Returns: * Tcount already incremented */ type *type_enum(const char *name, type *tbase) { Symbol *s = symbol_calloc(name); s->Sclass = SCenum; s->Senum = (enum_t *) MEM_PH_CALLOC(sizeof(enum_t)); s->Senum->SEflags |= SENforward; // forward reference type *t = type_allocn(TYenum, tbase); t->Ttag = (Classsym *)s; // enum tag name t->Tcount++; s->Stype = t; t->Tcount++; return t; }
STATIC void cpp_this_type(type *tfunc,Classsym *stag) { type *t; type_debug(tfunc); symbol_debug(stag); #if MARS t = type_allocn(TYnptr, stag->Stype); t->Tcount++; #else t = cpp_thistype(tfunc,stag); #endif //cpp_data_indirect_type(t); cpp_ecsu_data_indirect_type(t); type_free(t); }
type *type_function(tym_t tyf, type **ptypes, size_t nparams, bool variadic, type *tret) { param_t *paramtypes = NULL; for (size_t i = 0; i < nparams; i++) { param_append_type(¶mtypes, ptypes[i]); } type *t = type_allocn(tyf, tret); t->Tflags |= TFprototype; if (!variadic) t->Tflags |= TFfixed; t->Tparamtypes = paramtypes; t->Tcount++; return t; }
Symbol *objc_getImageInfo() { assert(!objc_simageInfo); // only allow once per object file objc_hasSymbols = true; dt_t *dt = NULL; dtdword(&dt, 0); // version dtdword(&dt, 0); // flags objc_simageInfo = symbol_name("L_OBJC_IMAGE_INFO", SCstatic, type_allocn(TYarray, tschar)); objc_simageInfo->Sdt = dt; objc_simageInfo->Sseg = objc_getSegment(SEGimage_info); outdata(objc_simageInfo); return objc_simageInfo; }
Symbol *objc_getModuleInfo() { assert(!objc_smoduleInfo); // only allow once per object file objc_hasSymbols = true; dt_t *dt = NULL; Symbol* symbol = symbol_name("L_OBJC_LABEL_CLASS_$", SCstatic, type_allocn(TYarray, tschar)); symbol->Sdt = dt; symbol->Sseg = objc_getSegment(SEGmodule_info); outdata(symbol); objc_getImageInfo(); // make sure we also generate image info return objc_smoduleInfo; }
Symbol *toVtblSymbol(ClassDeclaration *cd) { if (!cd->vtblsym) { if (!cd->csym) toSymbol(cd); TYPE *t = type_allocn(TYnptr | mTYconst, tsvoid); t->Tmangle = mTYman_d; Symbol *s = toSymbolX(cd, "__vtbl", SCextern, t, "Z"); s->Sflags |= SFLnodebug; s->Sfl = FLextern; cd->vtblsym = s; slist_add(s); } return cd->vtblsym; }
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 *objc_getCString(const char *str, size_t len, const char *symbolName, ObjcSegment segment) { objc_hasSymbols = true; // create data dt_t *dt = NULL; dtnbytes(&dt, len + 1, str); // find segment int seg = objc_getSegment(segment); // create symbol Symbol *s; s = symbol_name(symbolName, SCstatic, type_allocn(TYarray, tschar)); s->Sdt = dt; s->Sseg = seg; return s; }
Symbol *ClassDeclaration::toVtblSymbol() { if (!vtblsym) { Symbol *s; TYPE *t; if (!csym) toSymbol(); t = type_allocn(TYnptr | mTYconst, tsvoid); t->Tmangle = mTYman_d; s = toSymbolX("__vtbl", SCextern, t, "Z"); s->Sflags |= SFLnodebug; s->Sfl = FLextern; vtblsym = s; slist_add(s); } return vtblsym; }
void visit(TypeFunction *t) { size_t nparams = Parameter::dim(t->parameters); type *tmp[10]; type **ptypes = tmp; if (nparams > 10) ptypes = (type **)malloc(sizeof(type*) * nparams); for (size_t i = 0; i < nparams; i++) { Parameter *arg = Parameter::getNth(t->parameters, i); type *tp = Type_toCtype(arg->type); if (arg->storageClass & (STCout | STCref)) tp = type_allocn(TYref, tp); ptypes[i] = tp; } t->ctype = type_function(t->totym(), ptypes, nparams, t->varargs == 1, Type_toCtype(t->next)); if (nparams > 10) free(ptypes); }
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 */ }
type *type_delegate(type *tnext) { type *t = type_allocn(TYdelegate, tnext); t->Tcount++; return t; }
type *type_dyn_array(type *tnext) { type *t = type_allocn(TYdarray, tnext); t->Tcount++; return t; }
type *type_pointer(type *tnext) { type *t = type_allocn(TYnptr, tnext); t->Tcount++; return t; }
void cv8_func_term(Symbol *sfunc) { //printf("cv8_func_term(%s)\n", sfunc->Sident); assert(currentfuncdata.sfunc == sfunc); currentfuncdata.section_length = retoffset + retsize; funcdata->write(¤tfuncdata, sizeof(currentfuncdata)); // Write function symbol assert(tyfunc(sfunc->ty())); idx_t typidx; func_t* fn = sfunc->Sfunc; if(fn->Fclass) { // generate member function type info // it would be nicer if this could be in cv4_typidx, but the function info is not available there unsigned nparam; unsigned char call = cv4_callconv(sfunc->Stype); idx_t paramidx = cv4_arglist(sfunc->Stype,&nparam); unsigned next = cv4_typidx(sfunc->Stype->Tnext); type* classtype = (type*)fn->Fclass; unsigned classidx = cv4_typidx(classtype); type *tp = type_allocn(TYnptr, classtype); unsigned thisidx = cv4_typidx(tp); // TODO debtyp_t *d = debtyp_alloc(2 + 4 + 4 + 4 + 1 + 1 + 2 + 4 + 4); TOWORD(d->data,LF_MFUNCTION_V2); TOLONG(d->data + 2,next); // return type TOLONG(d->data + 6,classidx); // class type TOLONG(d->data + 10,thisidx); // this type d->data[14] = call; d->data[15] = 0; // reserved TOWORD(d->data + 16,nparam); TOLONG(d->data + 18,paramidx); TOLONG(d->data + 22,0); // this adjust typidx = cv_debtyp(d); } else typidx = cv_typidx(sfunc->Stype); const char *id = sfunc->prettyIdent ? sfunc->prettyIdent : prettyident(sfunc); size_t len = strlen(id); if(len > CV8_MAX_SYMBOL_LENGTH) len = CV8_MAX_SYMBOL_LENGTH; /* * 2 length (not including these 2 bytes) * 2 S_GPROC_V3 * 4 parent * 4 pend * 4 pnext * 4 size of function * 4 size of function prolog * 4 offset to function epilog * 4 type index * 6 seg:offset of function start * 1 flags * n 0 terminated name string */ Outbuffer *buf = currentfuncdata.f1buf; buf->reserve(2 + 2 + 4 * 7 + 6 + 1 + len + 1); buf->writeWordn( 2 + 4 * 7 + 6 + 1 + len + 1); buf->writeWordn(sfunc->Sclass == SCstatic ? S_LPROC_V3 : S_GPROC_V3); buf->write32(0); // parent buf->write32(0); // pend buf->write32(0); // pnext buf->write32(currentfuncdata.section_length); // size of function buf->write32(startoffset); // size of prolog buf->write32(retoffset); // offset to epilog buf->write32(typidx); F1_Fixups f1f; f1f.s = sfunc; f1f.offset = buf->size(); currentfuncdata.f1fixup->write(&f1f, sizeof(f1f)); buf->write32(0); buf->writeWordn(0); buf->writeByte(0); buf->writen(id, len); buf->writeByte(0); // Write local symbol table bool endarg = false; for (SYMIDX si = 0; si < globsym.top; si++) { //printf("globsym.tab[%d] = %p\n",si,globsym.tab[si]); symbol *sa = globsym.tab[si]; if (endarg == false && sa->Sclass != SCparameter && sa->Sclass != SCfastpar && sa->Sclass != SCshadowreg) { buf->writeWord(2); buf->writeWord(S_ENDARG); endarg = true; } cv8_outsym(sa); } /* Put out function return record S_RETURN * (VC doesn't, so we won't bother, either.) */ // Write function end symbol buf->writeWord(2); buf->writeWord(S_END); currentfuncdata.f1buf = F1_buf; currentfuncdata.f1fixup = F1fixup; }
void visit(VarDeclaration *vd) { //printf("VarDeclaration::toSymbol(%s)\n", vd->toChars()); assert(!vd->needThis()); if (!vd->csym) { const char *id; if (vd->isDataseg()) id = mangle(vd); else id = vd->ident->toChars(); Symbol *s = symbol_calloc(id); s->Salignment = vd->alignment; if (vd->storage_class & STCtemp) s->Sflags |= SFLartifical; TYPE *t; if (vd->storage_class & (STCout | STCref)) { t = type_allocn(TYnref, Type_toCtype(vd->type)); t->Tcount++; } else if (vd->storage_class & STClazy) { if (config.exe == EX_WIN64 && vd->isParameter()) t = type_fake(TYnptr); else t = type_fake(TYdelegate); // Tdelegate as C type t->Tcount++; } else if (vd->isParameter()) { if (config.exe == EX_WIN64 && vd->type->size(Loc()) > REGSIZE) { t = type_allocn(TYnref, Type_toCtype(vd->type)); t->Tcount++; } else { t = Type_toCtype(vd->type); t->Tcount++; } } else { t = Type_toCtype(vd->type); t->Tcount++; } if (vd->isDataseg()) { if (vd->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 = vd->loc.toChars(); fprintf(global.stdmsg, "%s: %s is thread local\n", p ? p : "", vd->toChars()); if (p) mem.xfree(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 = vd->toPrettyChars(true); } else { s->Sclass = SCauto; s->Sfl = FLauto; if (vd->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 (vd->ident == Id::va_argsave || vd->storage_class & STCvolatile) { /* __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 (vd->linkage) { case LINKwindows: m = global.params.is64bit ? mTYman_c : mTYman_std; break; case LINKpascal: m = mTYman_pas; break; case LINKc: m = mTYman_c; break; case LINKd: m = mTYman_d; break; case LINKcpp: s->Sflags |= SFLpublic; m = mTYman_d; break; default: printf("linkage = %d\n", vd->linkage); assert(0); } type_setmangle(&t, m); s->Stype = t; vd->csym = s; } result = vd->csym; }