MWCC/compiler_and_linker/unsorted/GenStabs.c

1192 lines
33 KiB
C

#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();
}