mirror of https://git.wuffs.org/MWCC
1192 lines
33 KiB
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_TYPE_4: return StabType_VectorUChar;
|
|
case STRUCT_TYPE_5: return StabType_VectorSChar;
|
|
case STRUCT_TYPE_6: return StabType_VectorBChar;
|
|
case STRUCT_TYPE_7: return StabType_VectorUShort;
|
|
case STRUCT_TYPE_8: return StabType_VectorSShort;
|
|
case STRUCT_TYPE_9: return StabType_VectorBShort;
|
|
case STRUCT_TYPE_A: return StabType_VectorUInt;
|
|
case STRUCT_TYPE_B: return StabType_VectorSInt;
|
|
case STRUCT_TYPE_C: return StabType_VectorBInt;
|
|
case STRUCT_TYPE_D: return StabType_VectorFloat;
|
|
case STRUCT_TYPE_E: 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();
|
|
}
|