#include "compiler/GenStabs.h" #include "compiler/CDecl.h" #include "compiler/CError.h" #include "compiler/CFunc.h" #include "compiler/CInt64.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CompilerTools.h" #include "compiler/MachO.h" #include "compiler/ObjGenMachO.h" #include "compiler/RegisterInfo.h" #include "compiler/StackFrame.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/types.h" enum { StabType_Int = 1, StabType_Char = 2, StabType_Long = 3, StabType_UInt = 4, StabType_ULong = 5, StabType_LongLong = 6, StabType_ULongLong = 7, StabType_Short = 8, StabType_UShort = 9, StabType_SChar = 10, StabType_UChar = 11, StabType_Float = 12, StabType_Double = 13, StabType_LongDouble = 14, StabType_ComplexInt = 15, StabType_ComplexFloat = 16, StabType_ComplexDouble = 17, StabType_ComplexLongDouble = 18, StabType_VectorUChar = 19, StabType_VectorSChar = 20, StabType_VectorBChar = 21, StabType_VectorUShort = 22, StabType_VectorSShort = 23, StabType_VectorBShort = 24, StabType_VectorUInt = 25, StabType_VectorSInt = 26, StabType_VectorBInt = 27, StabType_VectorFloat = 28, StabType_VectorPixel = 29, StabType_Bool = 30, StabType_Void = 31, StabType_WChar = 32, StabType_VtblPtr = 33, StabType_CharPtr = 34, StabType_UCharPtr = 35, StabType_Func = 36, StabType_FuncPtr = 37, StabType_CString = 38, StabType_PString = 39 }; #ifdef __MWERKS__ #pragma options align=mac68k #endif typedef struct StabType { struct StabType *next; int id; Type *type; } StabType; typedef struct StabClass { struct StabClass *next; int id; int id2; Type *type; } StabClass; typedef struct IncompleteList { struct IncompleteList *next; Type *type; StabType *listnode; Boolean xC; } IncompleteList; typedef struct HashedPath { struct HashedPath *next; char *str; SInt32 id; } HashedPath; #ifdef __MWERKS__ #pragma options align=reset #endif int unnamedstructs; static StabType *pointerlist; static StabType *structlist; static StabType *arraylist; static StabType *enumlist; static StabClass *classlist; static IncompleteList *incomplete_list; static int nexttypeid; static int type_done; static int first_file; static GList func_nl; static GList stab_string; static UInt32 current_offset; static UInt32 current_line; static HashedPath *hashedpaths[32]; // forward decls static Boolean stabtypeequal(Type *a, Type *b); static void StabNestedType(Type *type); static void output_stab_string(SInt32 (*func)(char *, SInt16, UInt32), SInt16 desc, UInt32 value); static void StabAppendType(Type *type); static SInt32 Output_FUN_Stab(char *str, SInt16 desc, UInt32 value); static short StabBasicType(short bt) { switch (bt) { case IT_BOOL: return StabType_Bool; case IT_CHAR: return StabType_Char; case IT_SCHAR: return StabType_SChar; case IT_UCHAR: return StabType_UChar; case IT_WCHAR_T: return StabType_WChar; case IT_SHORT: return StabType_Short; case IT_USHORT: return StabType_UShort; case IT_INT: return StabType_Int; case IT_UINT: return StabType_UInt; case IT_LONG: return StabType_Long; case IT_ULONG: return StabType_ULong; case IT_LONGLONG: return StabType_LongLong; case IT_ULONGLONG: return StabType_ULongLong; case IT_FLOAT: return StabType_Float; case IT_SHORTDOUBLE: return StabType_Double; case IT_DOUBLE: return StabType_Double; case IT_LONGDOUBLE: return StabType_Double; default: CError_FATAL(187); return StabType_Int; } } static void StabAppendNameSpaceName(GList *glist, NameSpace *nspace, int num) { char buf[16]; if (!nspace || num >= 9) { AppendGListByte(glist, 'Q'); AppendGListByte(glist, '0' + num); } else { while (nspace && !nspace->name) nspace = nspace->parent; if (nspace) { StabAppendNameSpaceName(glist, nspace->parent, num + 1); sprintf(buf, "%d", strlen(nspace->name->name)); AppendGListName(glist, buf); AppendGListName(glist, nspace->name->name); } else if (num > 1) { StabAppendNameSpaceName(glist, NULL, num + 1); } } } static void StabAppendName(GList *glist, NameSpace *nspace, HashNameNode *name) { if (IsTempName(name)) { unnamedstructs++; } else { while (nspace && !nspace->name) nspace = nspace->parent; if (nspace) StabAppendNameSpaceName(glist, nspace, 1); AppendGListName(glist, name->name); } } static SInt32 Output_LSYM_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_LSYM; sym.section = NULL; sym.desc = desc; sym.value = value; return ObjGen_OutputStab(&sym, -1); } static int StabAppendNextTypeDefinition(void) { char buf[48]; sprintf(buf, "(0,%d)=", ++nexttypeid); AppendGListName(&stab_string, buf); return nexttypeid; } static int namestarts(char *a, char *b) { while (1) { if (!*b) return 1; if (*b != tolower(*a)) break; a++; b++; } return 0; } static int namecontains(char *a, char *b) { char *aa; char *bb; while (*a) { aa = a; bb = b; while (1) { if (!*bb) return 1; if (*bb != tolower(*aa)) break; aa++; bb++; } a++; } return 0; } static void nested_local_array(Type *type) { StabType *list; for (list = arraylist; list; list = list->next) { if (stabtypeequal(type, list->type)) return; } StabNestedType(TPTR_TARGET(type)); } static int local_array(Type *type) { StabType *list; char buf[32]; for (list = arraylist; list; list = list->next) { if (stabtypeequal(type, list->type)) return list->id; } list = galloc(sizeof(StabType)); list->next = pointerlist; pointerlist = list; list->type = type; list->id = StabAppendNextTypeDefinition(); AppendGListName(&stab_string, "ar(0,1);0"); sprintf(buf, ";%d;", (type->size / TPTR_TARGET(type)->size) - 1); AppendGListName(&stab_string, buf); StabAppendType(TPTR_TARGET(type)); return list->id; } static Boolean stabtypeequal(Type *a, Type *b) { while (1) { if (a->type != b->type) return 0; switch (a->type) { case TYPEVOID: case TYPEFUNC: return 1; case TYPEINT: case TYPEFLOAT: case TYPEENUM: case TYPESTRUCT: case TYPECLASS: return a == b; case TYPEPOINTER: a = TPTR_TARGET(a); b = TPTR_TARGET(b); break; case TYPEARRAY: if (a->size != b->size) return 0; a = TPTR_TARGET(a); b = TPTR_TARGET(b); break; case TYPEMEMBERPOINTER: return 0; default: CError_FATAL(393); } } } static void nested_local_pointer(Type *type) { StabType *list; for (list = pointerlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return; } while (IS_TYPE_POINTER_ONLY(type)) type = TPTR_TARGET(type); StabNestedType(type); } static int local_pointer(Type *type) { StabType *list; for (list = pointerlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return list->id; } list = galloc(sizeof(StabType)); list->next = pointerlist; pointerlist = list; list->type = type; list->id = StabAppendNextTypeDefinition(); AppendGListName(&stab_string, "*"); for (type = TPTR_TARGET(type); IS_TYPE_POINTER_ONLY(type); type = TPTR_TARGET(type)) { StabAppendNextTypeDefinition(); AppendGListName(&stab_string, "*"); } StabAppendType(type); return list->id; } static int local_enum_add(Type *type) { ObjEnumConst *entry; int id; char buf[48]; id = StabAppendNextTypeDefinition(); AppendGListName(&stab_string, "e"); for (entry = TYPE_ENUM(type)->enumlist; entry; entry = entry->next) { AppendGListName(&stab_string, entry->name->name); sprintf(buf, ":%d,", CInt64_GetULong(&entry->val)); AppendGListName(&stab_string, buf); } AppendGListName(&stab_string, ";"); return id; } static void nested_local_enum(Type *type) { StabType *list; for (list = enumlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return; } if (TYPE_ENUM(type)->enumname) { stab_string.size = 0; StabAppendName(&stab_string, TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname); AppendGListName(&stab_string, ":T"); list = galloc(sizeof(StabType)); list->next = enumlist; enumlist = list; list->type = type; list->id = local_enum_add(type); output_stab_string(Output_LSYM_Stab, 0, 0); } } static int local_enum(Type *type) { StabType *list; for (list = enumlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return list->id; } list = galloc(sizeof(StabType)); list->next = enumlist; enumlist = list; list->type = type; list->id = local_enum_add(type); return list->id; } static void local_struct_add(StabType *list) { StructMember *member; Type *type; IncompleteList *incomplete; char buf[80]; type = list->type; if (type->size == 0) { incomplete = galloc(sizeof(IncompleteList)); incomplete->next = incomplete_list; incomplete_list = incomplete; incomplete->type = type; incomplete->listnode = list; incomplete->xC = 0; } if (list->id >= 0) { sprintf(buf, "(0,%d)=", list->id); AppendGListName(&stab_string, buf); } else { list->id = StabAppendNextTypeDefinition(); } sprintf(buf, "s%d", type->size); AppendGListName(&stab_string, buf); for (member = TYPE_STRUCT(type)->members; member; member = member->next) { AppendGListName(&stab_string, member->name->name); AppendGListName(&stab_string, ":"); type = member->type; if (IS_TYPE_BITFIELD(type)) { StabAppendType(TYPE_BITFIELD(type)->bitfieldtype); sprintf(buf, ",%d,%d;", TYPE_BITFIELD(type)->unkA + member->offset * 8, TYPE_BITFIELD(type)->unkB); AppendGListName(&stab_string, buf); } else { StabAppendType(type); sprintf(buf, ",%d,%d;", member->offset * 8, member->type->size * 8); AppendGListName(&stab_string, buf); } } AppendGListName(&stab_string, ";"); } static void nested_local_struct(Type *type) { StabType *list; StructMember *member; for (list = structlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return; } list = galloc(sizeof(StabType)); list->next = structlist; structlist = list; list->type = type; list->id = ++nexttypeid; for (member = TYPE_STRUCT(type)->members; member; member = member->next) { if (IS_TYPE_BITFIELD(member->type)) StabNestedType(TYPE_BITFIELD(member->type)->bitfieldtype); else StabNestedType(member->type); } stab_string.size = 0; StabAppendName(&stab_string, NULL, TYPE_STRUCT(type)->name); AppendGListName(&stab_string, ":T"); local_struct_add(list); output_stab_string(Output_LSYM_Stab, 0, 0); } static int local_struct(Type *type) { StabType *list; for (list = structlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return list->id; } list = galloc(sizeof(StabType)); list->next = structlist; structlist = list; list->type = type; local_struct_add(list); return list->id; } static void local_class_add(StabClass *list) { Type *type; IncompleteList *incomplete; int baseCount; ClassList *base; ObjMemberVar *ivar; Type *ivarType; char buf[80]; type = list->type; if (type->size == 0) { incomplete = galloc(sizeof(IncompleteList)); incomplete->next = incomplete_list; incomplete_list = incomplete; incomplete->type = type; incomplete->listnode = (StabType *) list; incomplete->xC = 0; } if (list->id >= 0) { sprintf(buf, "(0,%d)=", list->id); AppendGListName(&stab_string, buf); } else { list->id = StabAppendNextTypeDefinition(); } list->id2 = list->id; if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) { AppendGListName(&stab_string, "*"); StabAppendNextTypeDefinition(); } sprintf(buf, "s%d", type->size); AppendGListName(&stab_string, buf); if (!TYPE_CLASS(type)->sominfo) { baseCount = 0; base = TYPE_CLASS(type)->bases; while (base) { base = base->next; baseCount++; } if (baseCount > 0) { sprintf(buf, "!%d,", baseCount); AppendGListName(&stab_string, buf); for (base = TYPE_CLASS(type)->bases; base; base = base->next) { int virtualChar; char accessChar; virtualChar = base->is_virtual ? '1' : '0'; switch (base->access) { case ACCESSPUBLIC: accessChar = '2'; break; case ACCESSPRIVATE: accessChar = '0'; break; case ACCESSPROTECTED: accessChar = '1'; break; default: accessChar = '0'; break; } sprintf(buf, "%c%c%d,", (char) virtualChar, accessChar, base->is_virtual ? 0 : (base->offset * 8)); AppendGListName(&stab_string, buf); StabAppendType(TYPE(base->base)); AppendGListName(&stab_string, ";"); } for (base = TYPE_CLASS(type)->bases; base; base = base->next) { if (base->is_virtual) { AppendGListName(&stab_string, "$vb"); StabAppendType(TYPE(base->base)); AppendGListName(&stab_string, ":"); StabAppendType(CDecl_NewPointerType(TYPE(base->base))); sprintf(buf, ",%d;", base->offset * 8); AppendGListName(&stab_string, buf); } } } } for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { StabAppendName(&stab_string, NULL, ivar->name); AppendGListName(&stab_string, ":"); ivarType = ivar->type; if (IS_TYPE_BITFIELD(ivarType)) { StabAppendType(TYPE_BITFIELD(ivarType)->bitfieldtype); sprintf(buf, ",%d,%d;", TYPE_BITFIELD(ivarType)->unkA + ivar->offset * 8, TYPE_BITFIELD(ivarType)->unkB); AppendGListName(&stab_string, buf); } else { StabAppendType(ivarType); sprintf(buf, ",%d,%d;", ivar->offset * 8, ivar->type->size * 8); AppendGListName(&stab_string, buf); } } AppendGListName(&stab_string, ";"); } static void nested_local_class(Type *type) { StabClass *clslist; ClassList *base; ObjMemberVar *ivar; if (TYPE_CLASS(type)->sominfo) return; for (clslist = classlist; clslist; clslist = clslist->next) { if (stabtypeequal(type, clslist->type)) return; } clslist = galloc(sizeof(StabClass)); clslist->next = classlist; classlist = clslist; clslist->id = ++nexttypeid; clslist->type = type; if (!TYPE_CLASS(type)->sominfo) { for (base = TYPE_CLASS(type)->bases; base; base = base->next) { if (base->base->classname) { if (base->is_virtual) StabNestedType(CDecl_NewPointerType(TYPE(base->base))); else StabNestedType(TYPE(base->base)); } } } for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { if (IS_TYPE_BITFIELD(ivar->type)) StabNestedType(TYPE_BITFIELD(ivar->type)->bitfieldtype); else StabNestedType(ivar->type); } stab_string.size = 0; StabAppendName(&stab_string, TYPE_CLASS(type)->nspace->parent, TYPE_CLASS(type)->classname); AppendGListName(&stab_string, ":Tt"); local_class_add(clslist); output_stab_string(Output_LSYM_Stab, 0, 0); } static int local_class(Type *type) { StabClass *list; if (TYPE_CLASS(type)->sominfo) return 31; for (list = classlist; list; list = list->next) { if (stabtypeequal(type, list->type)) return list->id; } list = galloc(sizeof(StabClass)); list->next = classlist; classlist = list; list->type = type; local_class_add(list); return list->id; } static void StabNestedType(Type *type) { switch (type->type) { case TYPEVOID: break; case TYPEINT: break; case TYPEFLOAT: break; case TYPEENUM: nested_local_enum(type); break; case TYPESTRUCT: nested_local_struct(type); break; case TYPECLASS: nested_local_class(type); break; case TYPEFUNC: break; case TYPEBITFIELD: break; case TYPEMEMBERPOINTER: break; case TYPEPOINTER: if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type))) { if (!IS_TYPE_FUNC(TPTR_TARGET(TPTR_TARGET(type)))) nested_local_pointer(type); } else if ( !IS_TYPE_INT(TPTR_TARGET(type)) || (TYPE_INTEGRAL(TPTR_TARGET(type))->integral != IT_CHAR && TYPE_INTEGRAL(TPTR_TARGET(type))->integral != IT_UCHAR)) nested_local_pointer(type); break; case TYPEARRAY: nested_local_array(type); break; default: CError_FATAL(921); } } static int StabTypeID(Type *type) { int id; switch (type->type) { case TYPEVOID: id = StabType_Void; break; case TYPEINT: case TYPEFLOAT: id = StabBasicType(TYPE_INTEGRAL(type)->integral); break; case TYPEENUM: id = local_enum(type); break; case TYPESTRUCT: if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) { switch (TYPE_STRUCT(type)->stype) { case STRUCT_VECTOR_UCHAR: return StabType_VectorUChar; case STRUCT_VECTOR_SCHAR: return StabType_VectorSChar; case STRUCT_VECTOR_BCHAR: return StabType_VectorBChar; case STRUCT_VECTOR_USHORT: return StabType_VectorUShort; case STRUCT_VECTOR_SSHORT: return StabType_VectorSShort; case STRUCT_VECTOR_BSHORT: return StabType_VectorBShort; case STRUCT_VECTOR_UINT: return StabType_VectorUInt; case STRUCT_VECTOR_SINT: return StabType_VectorSInt; case STRUCT_VECTOR_BINT: return StabType_VectorBInt; case STRUCT_VECTOR_FLOAT: return StabType_VectorFloat; case STRUCT_VECTOR_PIXEL: return StabType_VectorPixel; } } else { id = local_struct(type); } break; case TYPECLASS: id = local_class(type); break; case TYPEFUNC: id = StabType_Func; break; case TYPEBITFIELD: id = StabType_Void; break; case TYPEPOINTER: if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type))) { if (IS_TYPE_FUNC(TPTR_TARGET(TPTR_TARGET(type)))) id = StabType_FuncPtr; else id = local_pointer(type); break; } if (IS_TYPE_INT(TPTR_TARGET(type))) { if (TYPE_INTEGRAL(TPTR_TARGET(type))->integral == IT_CHAR) { id = copts.unsigned_char ? StabType_UCharPtr : StabType_CharPtr; break; } if (TYPE_INTEGRAL(TPTR_TARGET(type))->integral == IT_UCHAR) { id = StabType_UCharPtr; break; } } id = local_pointer(type); break; case TYPEARRAY: id = local_array(type); break; case TYPEMEMBERPOINTER: id = StabType_Void; break; default: CError_FATAL(1041); id = StabType_Void; } return id; } static void output_stab_string(SInt32 (*func)(char *, SInt16, UInt32), SInt16 desc, UInt32 value) { int len; char *src; char *end; char *dst; char *boundarySrc; char *boundaryDst; char *possibleBoundarySrc; char *possibleBoundaryDst; char buffer[1024]; if (stab_string.size > 0) { LockGList(&stab_string); src = *stab_string.data; end = *stab_string.data + stab_string.size; dst = buffer; len = 0; boundarySrc = NULL; boundaryDst = NULL; possibleBoundarySrc = NULL; possibleBoundaryDst = NULL; while (src < end) { if (*src == ':') { boundarySrc = possibleBoundarySrc; boundaryDst = possibleBoundaryDst; } if (*src == '(') { *(dst++) = *(src++); len++; while (isdigit(*src)) { *(dst++) = *(src++); len++; } if (*src == ',') { *(dst++) = *(src++); len++; while (isdigit(*src)) { *(dst++) = *(src++); len++; } if (*src == ',') { *(dst++) = *(src++); len++; } } } if (*src == ',' || *src == ';') { possibleBoundarySrc = src; possibleBoundaryDst = dst; } *(dst++) = *(src++); len++; if ((end - src) <= 10 || len <= 40 || !boundarySrc) { if ((unsigned int) len <= 1021) continue; } if (boundarySrc) { src = boundarySrc + 1; dst = boundaryDst + 1; } dst[0] = '\\'; dst[1] = 0; func(buffer, desc, value); dst = buffer; boundarySrc = NULL; boundaryDst = NULL; possibleBoundarySrc = NULL; possibleBoundaryDst = NULL; len = 0; } if (len) { *dst = 0; func(buffer, desc, value); } UnlockGList(&stab_string); } } static void output_default_types(void) { Output_LSYM_Stab("int:t(0,1)=r(0,1);0020000000000;0017777777777;", 0, 0); if (copts.unsigned_char) Output_LSYM_Stab("char:t(0,2)=r(0,2);0;255;", 0, 0); else Output_LSYM_Stab("char:t(0,2)=r(0,2);-128;127;", 0, 0); Output_LSYM_Stab("long int:t(0,3)=r(0,1);0020000000000;0017777777777;", 0, 0); Output_LSYM_Stab("unsigned int:t(0,4)=r(0,1);0000000000000;0037777777777;", 0, 0); Output_LSYM_Stab("long unsigned int:t(0,5)=r(0,1);0000000000000;0037777777777;", 0, 0); Output_LSYM_Stab("long long int:t(0,6)=r(0,1);01000000000000000000000;0777777777777777777777;", 0, 0); Output_LSYM_Stab("long long unsigned int:t(0,7)=r(0,1);0000000000000;01777777777777777777777;", 0, 0); Output_LSYM_Stab("short int:t(0,8)=r(0,8);-32768;32767;", 0, 0); Output_LSYM_Stab("short unsigned int:t(0,9)=r(0,9);0;65535;", 0, 0); Output_LSYM_Stab("signed char:t(0,10)=r(0,10);-128;127;", 0, 0); Output_LSYM_Stab("unsigned char:t(0,11)=r(0,11);0;255;", 0, 0); Output_LSYM_Stab("float:t(0,12)=r(0,1);4;0;", 0, 0); Output_LSYM_Stab("double:t(0,13)=r(0,1);8;0;", 0, 0); Output_LSYM_Stab("long double:t(0,14)=r(0,1);8;0;", 0, 0); Output_LSYM_Stab("complex int:t(0,15)=s8real:(0,1),0,32;imag:(0,1),32,32;;", 0, 0); Output_LSYM_Stab("complex float:t(0,16)=r(0,16);4;0;", 0, 0); Output_LSYM_Stab("complex double:t(0,17)=r(0,17);8;0;", 0, 0); Output_LSYM_Stab("complex long double:t(0,18)=r(0,18);8;0;", 0, 0); Output_LSYM_Stab("__vector unsigned char:t(0,19)=ar(0,1);0;15;(0,11)", 0, 0); Output_LSYM_Stab("__vector signed char:t(0,20)=ar(0,1);0;15;(0,10)", 0, 0); Output_LSYM_Stab("__vector bool char:t(0,21)=ar(0,1);0;15;(0,11)", 0, 0); Output_LSYM_Stab("__vector unsigned short:t(0,22)=ar(0,1);0;7;(0,9)", 0, 0); Output_LSYM_Stab("__vector signed short:t(0,23)=ar(0,1);0;7;(0,8)", 0, 0); Output_LSYM_Stab("__vector bool short:t(0,24)=ar(0,1);0;7;(0,9)", 0, 0); Output_LSYM_Stab("__vector unsigned int:t(0,25)=ar(0,1);0;3;(0,5)", 0, 0); Output_LSYM_Stab("__vector signed int:t(0,26)=ar(0,1);0;3;(0,3)", 0, 0); Output_LSYM_Stab("__vector bool int:t(0,27)=ar(0,1);0;3;(0,5)", 0, 0); Output_LSYM_Stab("__vector float:t(0,28)=ar(0,1);0;3;(0,12)", 0, 0); Output_LSYM_Stab("__vector pixel:t(0,29)=ar(0,1);0;7;(0,9)", 0, 0); if (copts.booltruefalse) { Output_LSYM_Stab("bool:t(0,30)=r(0,30);0;1;", 0, 0); Output_LSYM_Stab("true:c=b1;", 0, 0); Output_LSYM_Stab("false:c=b0;", 0, 0); } else { Output_LSYM_Stab(":t(0,30)=r(0,30);0;1;", 0, 0); } Output_LSYM_Stab("void:t(0,31)=(0,31);", 0, 0); if (copts.wchar_type) Output_LSYM_Stab("wchar_t:t(0,32)=r(0,1);0020000000000;0017777777777;", 0, 0); else Output_LSYM_Stab("__wchar_t:t(0,32)=r(0,1);0020000000000;0017777777777;", 0, 0); if (copts.cplusplus) Output_LSYM_Stab("__vtbl_ptr_type:t(0,33)=*(0,34)=f(0,1)", 0, 0); Output_LSYM_Stab("__charptr__:t(0,34)=*(0,10);", 0, 0); Output_LSYM_Stab("__ucharptr__:t(0,35)=*(0,11);", 0, 0); Output_LSYM_Stab("__funcptr__:t(0,37)=*(0,36)=f(0,31);", 0, 0); Output_LSYM_Stab("__cstring__:t(0,38)=*(0,10);", 0, 0); Output_LSYM_Stab("__pstring__:t(0,39)=*(0,11);", 0, 0); nexttypeid = StabType_PString; type_done = 1; } int GenStab_Type(char *name, Type *type) { int id; if (!type_done) output_default_types(); StabNestedType(type); stab_string.size = 0; if (name && strlen(name)) { AppendGListName(&stab_string, name); AppendGListName(&stab_string, ":t"); } id = StabTypeID(type); output_stab_string(Output_LSYM_Stab, 0, 0); return id; } static void StabAppendType(Type *type) { SInt32 size; int id; char buf[20]; size = stab_string.size; id = StabTypeID(type); if (size == stab_string.size) { sprintf(buf, "(0,%d)", id); AppendGListName(&stab_string, buf); } } void GenStab_Function(Object *func, UInt32 offset) { HashNameNode *name; if (!type_done) output_default_types(); StabNestedType(TYPE_FUNC(func->type)->functype); stab_string.size = 0; name = CMangler_GetLinkName(func); AppendGListName(&stab_string, (name->name[0] == '_') ? &name->name[1] : name->name); if (CParser_HasInternalLinkage(func)) AppendGListName(&stab_string, ":f"); else AppendGListName(&stab_string, ":F"); StabAppendType(TYPE_FUNC(func->type)->functype); output_stab_string(Output_FUN_Stab, functionbodyoffset, offset); current_offset = offset; current_line = -1; } void GenStab_FunctionEnd(Object *func, SInt32 relocID, UInt32 offset) { stab_string.size = 0; Output_FUN_Stab("", current_line, relocID + offset); } void GenStab_Line(UInt32 line, UInt32 offset) { SymbolData sym; if (offset != current_offset && line != current_line) { sym.u.name = NULL; sym.type = N_SLINE; sym.section = NULL; sym.desc = line; sym.value = offset; ObjGen_OutputStab(&sym, -1); current_offset = offset; current_line = line; } } static SInt32 Output_RSYM_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_RSYM; sym.section = NULL; sym.desc = desc; sym.value = value; return ObjGen_OutputStab(&sym, -1); } static SInt32 Output_PSYM_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_PSYM; sym.section = NULL; sym.desc = desc; sym.value = value; return ObjGen_OutputStab(&sym, -1); } static SInt32 Output_FUN_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_FUN; sym.section = NULL; sym.desc = desc; sym.value = value; return ObjGen_OutputStab(&sym, -1); } static SInt32 Output_GSYM_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_GSYM; sym.section = NULL; sym.desc = 0; sym.value = 0; return ObjGen_OutputStab(&sym, -1); } static SInt32 Output_STSYM_Stab(char *str, SInt16 desc, UInt32 value) { SymbolData sym; sym.u.name = str; sym.type = N_STSYM; sym.section = NULL; sym.desc = desc; sym.value = value; return ObjGen_OutputStab(&sym, -1); } static const int reg_offset[] = { -200, 68, 76, 32, 0 }; void GenStab_Parameter(Object *object) { VarInfo *vi; if (!type_done) output_default_types(); StabNestedType(object->type); stab_string.size = 0; vi = Registers_GetVarInfo(object); AppendGListName(&stab_string, object->name->name); if (vi->flags & VarInfoFlag2) { AppendGListName(&stab_string, ":P"); StabAppendType(object->type); output_stab_string(Output_RSYM_Stab, 0, vi->reg + reg_offset[vi->rclass]); } else { AppendGListName(&stab_string, ":p"); StabAppendType(object->type); output_stab_string(Output_PSYM_Stab, 0, local_offset_32(object)); } } void GenStab_Var(Object *object) { VarInfo *vi; if (!type_done) output_default_types(); StabNestedType(object->type); stab_string.size = 0; vi = Registers_GetVarInfo(object); AppendGListName(&stab_string, object->name->name); vi = Registers_GetVarInfo(object); if (object->datatype == DLOCAL) { if (vi->flags & VarInfoFlag2) { AppendGListName(&stab_string, ":r"); StabAppendType(object->type); output_stab_string(Output_RSYM_Stab, 0, vi->reg + reg_offset[vi->rclass]); } else { AppendGListName(&stab_string, ":"); StabAppendType(object->type); output_stab_string(Output_LSYM_Stab, 0, local_offset_32(object)); } } else if (CParser_HasInternalLinkage(object) || (object->qual & (Q_20000 | Q_OVERLOAD))) { AppendGListName(&stab_string, ":S"); StabAppendType(object->type); output_stab_string(Output_STSYM_Stab, 0, CMangler_GetLinkName(object)->id); } else { AppendGListName(&stab_string, ":G"); StabAppendType(object->type); output_stab_string(Output_GSYM_Stab, 0, 0); } } static HashedPath *Stabs_LookupPath(char *str) { char *buf; HashedPath *hp; HashedPath **ptr; for (hp = hashedpaths[CHash(str) & 31]; hp; hp = hp->next) { if (!strcmp(hp->str, str)) return hp; } ptr = hashedpaths + (CHash(str) & 31); hp = galloc(sizeof(HashedPath)); buf = galloc(strlen(str) + 1); strcpy(buf, str); hp->str = buf; hp->id = -1; hp->next = *ptr; *ptr = hp; return hp; } void GenStab_IncludeFile(char *path) { HashedPath *hp; SymbolData sym; hp = Stabs_LookupPath(path); sym.u.name = hp->str; sym.type = N_SOL; sym.section = NULL; sym.desc = 0; sym.value = 0; hp->id = ObjGen_OutputStab(&sym, hp->id); } void GenStab_SourceFile(char *path) { HashedPath *hp; SymbolData sym; hp = Stabs_LookupPath(path); sym.u.name = hp->str; sym.type = N_SO; sym.section = NULL; sym.desc = 0; sym.value = 0; hp->id = ObjGen_OutputStab(&sym, hp->id); } void GenStab_Setup(void) { SInt32 i; for (i = 0; i < 32; i++) hashedpaths[i] = NULL; type_done = 0; first_file = 0; nexttypeid = 0; pointerlist = NULL; structlist = NULL; arraylist = NULL; enumlist = NULL; classlist = NULL; incomplete_list = NULL; current_offset = 0; current_line = -1; func_nl.data = NULL; stab_string.data = NULL; if (InitGList(&stab_string, 256)) CError_NoMem(); }