mirror of
https://git.wuffs.org/MWCC
synced 2025-12-20 10:25:31 +00:00
move lots of source files around to match their actual placement in the original tree
This commit is contained in:
2033
compiler_and_linker/FrontEnd/C/CABI.c
Normal file
2033
compiler_and_linker/FrontEnd/C/CABI.c
Normal file
File diff suppressed because it is too large
Load Diff
737
compiler_and_linker/FrontEnd/C/CBrowse.c
Normal file
737
compiler_and_linker/FrontEnd/C/CBrowse.c
Normal file
@@ -0,0 +1,737 @@
|
||||
#include "compiler/CBrowse.h"
|
||||
#include "compiler/CDecl.h"
|
||||
#include "compiler/CError.h"
|
||||
#include "compiler/CMangler.h"
|
||||
#include "compiler/CParser.h"
|
||||
#include "compiler/CPrep.h"
|
||||
#include "compiler/CompilerTools.h"
|
||||
#include "compiler/Unmangle.h"
|
||||
#include "compiler/objects.h"
|
||||
#include "compiler/templates.h"
|
||||
#include "cos.h"
|
||||
#include "plugin.h"
|
||||
|
||||
Boolean gUseTokenStreamSource;
|
||||
Boolean gForceSourceLoc;
|
||||
Boolean gUseNameTable;
|
||||
static GList gBrowseData;
|
||||
static GList gClassData;
|
||||
static GList gMemberFuncList;
|
||||
static int gNextMemberFuncID;
|
||||
|
||||
enum ELanguage {
|
||||
langUnknown,
|
||||
langC,
|
||||
langCPlus,
|
||||
langPascal,
|
||||
langObjectPascal,
|
||||
langJava,
|
||||
langAssembler,
|
||||
langFortran,
|
||||
langRez
|
||||
};
|
||||
|
||||
enum EBrowserItem {
|
||||
browseFunction,
|
||||
browseGlobal,
|
||||
browseClass,
|
||||
browseMacro,
|
||||
browseEnum,
|
||||
browseTypedef,
|
||||
browseConstant,
|
||||
browseTemplate,
|
||||
browsePackage,
|
||||
browseCompSymbolStart = 0x70,
|
||||
browseEnd = 0xFF
|
||||
};
|
||||
|
||||
enum {
|
||||
kAbstract = 1,
|
||||
kStatic = 2,
|
||||
kFinal = 4,
|
||||
kMember = 8,
|
||||
|
||||
kInterface = 0x80,
|
||||
kPublic = 0x100,
|
||||
|
||||
kInline = 0x80,
|
||||
kPascal = 0x100,
|
||||
kAsm = 0x200,
|
||||
kVirtual = 0x400,
|
||||
kCtor = 0x800,
|
||||
kDtor = 0x1000,
|
||||
kNative = 0x2000,
|
||||
kSynch = 0x4000,
|
||||
kIntrinsic = 0x8000,
|
||||
kConst = 0x10000,
|
||||
|
||||
kTransient = 0x80,
|
||||
kVolatile = 0x100
|
||||
};
|
||||
|
||||
enum EAccess {
|
||||
accessNone = 0,
|
||||
accessPrivate = 1,
|
||||
accessProtected = 2,
|
||||
accessPublic = 4
|
||||
};
|
||||
|
||||
enum EMember {
|
||||
memberFunction,
|
||||
memberData,
|
||||
memberEnd = 0xFF
|
||||
};
|
||||
|
||||
enum ETemplateType {
|
||||
templateClass,
|
||||
templateFunction
|
||||
};
|
||||
|
||||
static enum EAccess gFromAccessType[] = {
|
||||
accessPublic,
|
||||
accessPrivate,
|
||||
accessProtected,
|
||||
accessNone
|
||||
};
|
||||
|
||||
typedef struct BrowseHeader {
|
||||
SInt32 browse_header;
|
||||
SInt32 browse_version;
|
||||
SInt16 browse_language;
|
||||
SInt16 uses_name_table;
|
||||
SInt32 earliest_compatible_version;
|
||||
SInt32 reserved[15];
|
||||
} BrowseHeader;
|
||||
|
||||
// forward decls
|
||||
static void RecordUndefinedMemberFunctions(void);
|
||||
|
||||
void CBrowse_Setup(CompilerLinkerParamBlk *params) {
|
||||
BrowseHeader hdr;
|
||||
|
||||
CError_ASSERT(123, params != NULL);
|
||||
|
||||
params->object.browsedata = NULL;
|
||||
|
||||
InitGList(&gBrowseData, 0x10000);
|
||||
InitGList(&gMemberFuncList, 1024);
|
||||
|
||||
gNextMemberFuncID = 1;
|
||||
gForceSourceLoc = 0;
|
||||
gUseNameTable = 0;
|
||||
|
||||
memclrw(&hdr, sizeof(hdr));
|
||||
hdr.browse_header = 0xBEABBAEB;
|
||||
hdr.browse_version = 2;
|
||||
hdr.earliest_compatible_version = 2;
|
||||
hdr.browse_language = copts.cplusplus ? langCPlus : langC;
|
||||
hdr.uses_name_table = gUseNameTable;
|
||||
|
||||
AppendGListData(&gBrowseData, &hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
void CBrowse_Finish(CompilerLinkerParamBlk *params) {
|
||||
CWMemHandle hnd;
|
||||
|
||||
CError_ASSERT(151, params != NULL);
|
||||
|
||||
if (gBrowseData.size >= sizeof(BrowseHeader)) {
|
||||
RecordUndefinedMemberFunctions();
|
||||
AppendGListByte(&gBrowseData, -1);
|
||||
|
||||
COS_ResizeHandle(gBrowseData.data, gBrowseData.size);
|
||||
|
||||
if (CWSecretAttachHandle(params->context, gBrowseData.data, &hnd) == cwNoErr) {
|
||||
params->object.browsedata = hnd;
|
||||
gBrowseData.data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_Cleanup(CompilerLinkerParamBlk *params) {
|
||||
FreeGList(&gBrowseData);
|
||||
FreeGList(&gClassData);
|
||||
FreeGList(&gMemberFuncList);
|
||||
}
|
||||
|
||||
static void AppendGList(GList *dst, GList *src) {
|
||||
SInt32 offset = dst->size;
|
||||
|
||||
AppendGListNoData(dst, src->size);
|
||||
memcpy(*dst->data + offset, *src->data, src->size);
|
||||
}
|
||||
|
||||
static void RecordName(GList *gl, const char *str, SInt32 id) {
|
||||
HashNameNode *name;
|
||||
|
||||
CError_ASSERT(190, gl && str && *str);
|
||||
|
||||
if (id < 0 && gUseNameTable) {
|
||||
for (name = name_hash_nodes[CHash(str)]; name; name = name->next) {
|
||||
if (!strcmp(str, name->name)) {
|
||||
id = name->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (id >= 0 && gUseNameTable) {
|
||||
AppendGListWord(gl, -1);
|
||||
AppendGListLong(gl, id);
|
||||
} else {
|
||||
int len = strlen(str);
|
||||
AppendGListWord(gl, len);
|
||||
if (len)
|
||||
AppendGListData(gl, str, len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_BeginClass(DeclInfo *di, GList *gl) {
|
||||
char *buf;
|
||||
ClassList *base;
|
||||
SInt32 i;
|
||||
TypeClass *tclass;
|
||||
|
||||
CError_ASSERT(227, di && di->thetype && gl);
|
||||
|
||||
*gl = gClassData;
|
||||
|
||||
if (
|
||||
!di->file ||
|
||||
!di->file->fileID ||
|
||||
!di->file->recordbrowseinfo ||
|
||||
!di->file2 ||
|
||||
!di->file2->fileID ||
|
||||
di->sourceoffset <= 0
|
||||
)
|
||||
{
|
||||
memclrw(&gClassData, sizeof(gClassData));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTempName(TYPE_CLASS(di->thetype)->classname)) {
|
||||
memclrw(&gClassData, sizeof(gClassData));
|
||||
return;
|
||||
}
|
||||
|
||||
InitGList(&gClassData, 0x4000);
|
||||
AppendGListByte(&gClassData, browseClass);
|
||||
AppendGListWord(&gClassData, di->file->fileID);
|
||||
AppendGListWord(&gClassData, di->file2->fileID);
|
||||
AppendGListLong(&gClassData, di->sourceoffset - 1);
|
||||
CError_ASSERT(270, gClassData.size == 9);
|
||||
AppendGListLong(&gClassData, di->sourceoffset - 1);
|
||||
AppendGListLong(&gClassData, 0);
|
||||
RecordName(&gClassData, TYPE_CLASS(di->thetype)->classname->name, TYPE_CLASS(di->thetype)->classname->id);
|
||||
|
||||
CMangler_MangleType(di->thetype, 0);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
buf = lalloc(name_mangle_list.size + 1);
|
||||
strcpy(buf, *name_mangle_list.data);
|
||||
|
||||
while (*buf && *buf >= '0' && *buf <= '9')
|
||||
buf++;
|
||||
|
||||
if (strcmp(TYPE_CLASS(di->thetype)->classname->name, buf))
|
||||
RecordName(&gClassData, buf, -1);
|
||||
else
|
||||
AppendGListWord(&gClassData, 0);
|
||||
|
||||
AppendGListLong(&gClassData, 0);
|
||||
|
||||
i = 0;
|
||||
base = TYPE_CLASS(di->thetype)->bases;
|
||||
while (base) {
|
||||
base = base->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
AppendGListByte(&gClassData, i);
|
||||
|
||||
for (base = TYPE_CLASS(di->thetype)->bases; base; base = base->next) {
|
||||
AppendGListByte(&gClassData, gFromAccessType[base->access]);
|
||||
AppendGListByte(&gClassData, base->is_virtual);
|
||||
|
||||
tclass = base->base;
|
||||
if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized)
|
||||
tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ);
|
||||
|
||||
CMangler_MangleType(TYPE(tclass), 0);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
buf = lalloc(name_mangle_list.size + 1);
|
||||
strcpy(buf, *name_mangle_list.data);
|
||||
|
||||
while (*buf && *buf >= '0' && *buf <= '9')
|
||||
buf++;
|
||||
|
||||
i = base->base->classname->id;
|
||||
while (*buf && *buf >= '0' && *buf <= '9') {
|
||||
i = -1;
|
||||
buf++;
|
||||
}
|
||||
|
||||
RecordName(&gClassData, buf, i);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_AddClassMemberVar(ObjMemberVar *ivar, SInt32 startOffset, SInt32 endOffset) {
|
||||
short len;
|
||||
|
||||
CError_ASSERT(360, ivar);
|
||||
|
||||
if (gClassData.data && startOffset > 0 && endOffset >= startOffset) {
|
||||
if (tk == ';')
|
||||
endOffset++;
|
||||
|
||||
AppendGListByte(&gClassData, memberData);
|
||||
AppendGListByte(&gClassData, gFromAccessType[ivar->access]);
|
||||
AppendGListLong(&gClassData, 0);
|
||||
AppendGListLong(&gClassData, startOffset - 1);
|
||||
AppendGListLong(&gClassData, endOffset - 1);
|
||||
|
||||
len = strlen(ivar->name->name);
|
||||
AppendGListWord(&gClassData, len);
|
||||
AppendGListData(&gClassData, ivar->name->name, len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_AddClassMemberFunction(Object *object, SInt32 startOffset, SInt32 endOffset) {
|
||||
SInt32 flags;
|
||||
SInt32 id;
|
||||
TypeMemberFunc *tfunc;
|
||||
|
||||
CError_ASSERT(380, object);
|
||||
|
||||
if (
|
||||
!IsTempName(object->name) &&
|
||||
gClassData.data &&
|
||||
startOffset > 0 &&
|
||||
endOffset >= startOffset
|
||||
)
|
||||
{
|
||||
flags = 0;
|
||||
CError_ASSERT(391, object->type && IS_TYPE_FUNC(object->type));
|
||||
tfunc = TYPE_METHOD(object->type);
|
||||
|
||||
if (tfunc->flags & FUNC_AUTO_GENERATED)
|
||||
return;
|
||||
|
||||
if (object->datatype == DVFUNC)
|
||||
flags |= kVirtual;
|
||||
if (tfunc->flags & FUNC_PURE)
|
||||
flags |= kAbstract;
|
||||
if (tfunc->is_static)
|
||||
flags |= kStatic;
|
||||
if (tfunc->flags & FUNC_IS_CTOR)
|
||||
flags |= kCtor;
|
||||
if (tfunc->flags & FUNC_IS_DTOR)
|
||||
flags |= kDtor;
|
||||
|
||||
AppendGListByte(&gClassData, memberFunction);
|
||||
AppendGListByte(&gClassData, gFromAccessType[object->access]);
|
||||
AppendGListLong(&gClassData, flags);
|
||||
|
||||
id = tfunc->funcid;
|
||||
if (id <= 0) {
|
||||
// TODO: this is not 64-bit safe
|
||||
if (!(tfunc->flags & FUNC_DEFINED) || id == -1)
|
||||
AppendGListLong(&gMemberFuncList, (SInt32) object);
|
||||
tfunc->funcid = id = gNextMemberFuncID++;
|
||||
}
|
||||
|
||||
AppendGListLong(&gClassData, id);
|
||||
AppendGListLong(&gClassData, startOffset - 1);
|
||||
AppendGListLong(&gClassData, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_AddClassMemberData(Object *object, SInt32 startOffset, SInt32 endOffset) {
|
||||
short len;
|
||||
|
||||
CError_ASSERT(435, object);
|
||||
|
||||
if (gClassData.data && startOffset > 0 && endOffset >= startOffset && object->datatype == DDATA) {
|
||||
if (tk == ';')
|
||||
endOffset++;
|
||||
|
||||
AppendGListByte(&gClassData, memberData);
|
||||
AppendGListByte(&gClassData, gFromAccessType[object->access]);
|
||||
AppendGListLong(&gClassData, kStatic);
|
||||
AppendGListLong(&gClassData, startOffset - 1);
|
||||
AppendGListLong(&gClassData, endOffset - 1);
|
||||
|
||||
len = strlen(object->name->name);
|
||||
AppendGListWord(&gClassData, len);
|
||||
AppendGListData(&gClassData, object->name->name, len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_EndClass(SInt32 offset, GList *gl) {
|
||||
CError_ASSERT(453, gl);
|
||||
|
||||
if (gClassData.data) {
|
||||
if (gClassData.size > 0) {
|
||||
if (tk == ';')
|
||||
offset++;
|
||||
memcpy(*gClassData.data + 9, &offset, 4);
|
||||
AppendGList(&gBrowseData, &gClassData);
|
||||
AppendGListByte(&gBrowseData, memberEnd);
|
||||
}
|
||||
FreeGList(&gClassData);
|
||||
}
|
||||
|
||||
gClassData = *gl;
|
||||
}
|
||||
|
||||
void CBrowse_BeginStruct(DeclInfo *di, TypeStruct *tstruct, GList *gl) {
|
||||
HashNameNode *name;
|
||||
|
||||
CError_ASSERT(480, di && gl);
|
||||
|
||||
*gl = gClassData;
|
||||
|
||||
if (
|
||||
!di->file ||
|
||||
!di->file->fileID ||
|
||||
!di->file->recordbrowseinfo ||
|
||||
!di->file2 ||
|
||||
!di->file2->fileID ||
|
||||
di->sourceoffset <= 0
|
||||
)
|
||||
{
|
||||
memclrw(&gClassData, sizeof(gClassData));
|
||||
return;
|
||||
}
|
||||
|
||||
name = tstruct->name;
|
||||
if (!name || IsTempName(name)) {
|
||||
memclrw(&gClassData, sizeof(gClassData));
|
||||
return;
|
||||
}
|
||||
|
||||
InitGList(&gClassData, 0x4000);
|
||||
AppendGListByte(&gClassData, browseClass);
|
||||
AppendGListWord(&gClassData, di->file->fileID);
|
||||
AppendGListWord(&gClassData, di->file2->fileID);
|
||||
AppendGListLong(&gClassData, di->sourceoffset - 1);
|
||||
CError_ASSERT(521, gClassData.size == 9);
|
||||
AppendGListLong(&gClassData, di->sourceoffset - 1);
|
||||
AppendGListLong(&gClassData, 0);
|
||||
RecordName(&gClassData, name->name, name->id);
|
||||
AppendGListWord(&gClassData, 0);
|
||||
AppendGListLong(&gClassData, 0);
|
||||
AppendGListByte(&gClassData, 0);
|
||||
}
|
||||
|
||||
void CBrowse_AddStructMember(StructMember *member, SInt32 startOffset, SInt32 endOffset) {
|
||||
short len;
|
||||
|
||||
if (tk == ';')
|
||||
endOffset++;
|
||||
|
||||
if (gClassData.data && member && startOffset > 0 && endOffset >= startOffset) {
|
||||
AppendGListByte(&gClassData, memberData);
|
||||
AppendGListByte(&gClassData, accessPublic);
|
||||
AppendGListLong(&gClassData, 0);
|
||||
AppendGListLong(&gClassData, startOffset - 1);
|
||||
AppendGListLong(&gClassData, endOffset - 1);
|
||||
|
||||
len = strlen(member->name->name);
|
||||
AppendGListWord(&gClassData, len);
|
||||
AppendGListData(&gClassData, member->name->name, len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_EndStruct(SInt32 offset, GList *gl) {
|
||||
CError_ASSERT(558, gl);
|
||||
|
||||
if (gClassData.data) {
|
||||
if (offset > 0 && gClassData.size > 0) {
|
||||
memcpy(*gClassData.data + 9, &offset, 4);
|
||||
AppendGList(&gBrowseData, &gClassData);
|
||||
AppendGListByte(&gBrowseData, memberEnd);
|
||||
}
|
||||
FreeGList(&gClassData);
|
||||
}
|
||||
|
||||
gClassData = *gl;
|
||||
}
|
||||
|
||||
static void EmitStandardData(int item, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset, const char *str, SInt32 id, const char *str2, SInt32 id2) {
|
||||
CError_ASSERT(584, str);
|
||||
|
||||
AppendGListByte(&gBrowseData, item);
|
||||
AppendGListWord(&gBrowseData, fileID1);
|
||||
AppendGListWord(&gBrowseData, fileID2);
|
||||
AppendGListLong(&gBrowseData, startOffset - 1);
|
||||
AppendGListLong(&gBrowseData, endOffset - 1);
|
||||
AppendGListLong(&gBrowseData, 0);
|
||||
|
||||
RecordName(&gBrowseData, str, id);
|
||||
if (str2 && str2 != str)
|
||||
RecordName(&gBrowseData, str2, id2);
|
||||
else
|
||||
AppendGListWord(&gBrowseData, 0);
|
||||
}
|
||||
|
||||
void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(618, file1 && file1->recordbrowseinfo);
|
||||
|
||||
if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) {
|
||||
EmitStandardData(browseTypedef,
|
||||
file1->fileID, file2->fileID,
|
||||
startOffset, endOffset,
|
||||
name->name, name->id,
|
||||
CError_GetQualifiedName(nspace, name), -1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(632, file1 && file1->recordbrowseinfo);
|
||||
|
||||
if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) {
|
||||
EmitStandardData(browseEnum,
|
||||
file1->fileID, file2->fileID,
|
||||
startOffset, endOffset,
|
||||
name->name, name->id,
|
||||
CError_GetQualifiedName(nspace, name), -1);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(646, file1 && file1->recordbrowseinfo);
|
||||
|
||||
if (tk == ',')
|
||||
endOffset++;
|
||||
|
||||
if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) {
|
||||
EmitStandardData(browseConstant,
|
||||
file1->fileID, file2->fileID,
|
||||
startOffset, endOffset,
|
||||
name->name, name->id,
|
||||
CError_GetQualifiedName(nspace, name), -1);
|
||||
}
|
||||
}
|
||||
|
||||
static HashNameNode *CBrowse_GetLinkName(Object *object) {
|
||||
return CMangler_GetLinkName(object);
|
||||
}
|
||||
|
||||
static void RecordFunction(Object *object, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset) {
|
||||
TypeFunc *tfunc;
|
||||
char *tmp;
|
||||
Boolean flag;
|
||||
char *str29;
|
||||
HashNameNode *linkname;
|
||||
SInt32 flags;
|
||||
char *namestr;
|
||||
SInt32 nameid;
|
||||
char *namestr2;
|
||||
SInt32 nameid2;
|
||||
int funcid;
|
||||
char buf[2048];
|
||||
char buf2[256];
|
||||
|
||||
CError_ASSERT(740, object->type && IS_TYPE_FUNC(object->type));
|
||||
|
||||
if (IsTempName(object->name))
|
||||
return;
|
||||
|
||||
tfunc = TYPE_FUNC(object->type);
|
||||
if ((tfunc->flags & (FUNC_AUTO_GENERATED | FUNC_INTRINSIC)) && (!fileID2 || startOffset < 0))
|
||||
return;
|
||||
|
||||
linkname = object->name;
|
||||
tmp = linkname->name;
|
||||
if (!(linkname->name[0] == '_' && linkname->name[1] == '_')) {
|
||||
namestr = tmp;
|
||||
nameid = linkname->id;
|
||||
switch (tmp[0]) {
|
||||
case '.':
|
||||
nameid = -1;
|
||||
namestr += 1;
|
||||
break;
|
||||
case '_':
|
||||
switch (tmp[1]) {
|
||||
case '#':
|
||||
case '%':
|
||||
case '@':
|
||||
nameid = -1;
|
||||
namestr += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
flag = 1;
|
||||
if (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) {
|
||||
tmp = TYPE_METHOD(tfunc)->theclass->classname->name;
|
||||
while (*tmp >= '0' && *tmp <= '9')
|
||||
tmp++;
|
||||
MWUnmangleClassName(tmp, buf, sizeof(buf));
|
||||
|
||||
str29 = buf;
|
||||
if ((tmp = strrchr(str29, ':')))
|
||||
str29 = tmp + 1;
|
||||
|
||||
if (tfunc->flags & FUNC_IS_DTOR) {
|
||||
buf2[0] = '~';
|
||||
strncpy(&buf2[1], str29, sizeof(buf2) - 1);
|
||||
namestr = buf2;
|
||||
} else {
|
||||
namestr = str29;
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
MWUnmangle(object->name->name, buf, sizeof(buf));
|
||||
namestr = buf;
|
||||
}
|
||||
|
||||
nameid = -1;
|
||||
}
|
||||
|
||||
while (*namestr >= '0' && *namestr <= '9') {
|
||||
nameid = -1;
|
||||
namestr++;
|
||||
}
|
||||
|
||||
namestr2 = NULL;
|
||||
nameid2 = -1;
|
||||
|
||||
linkname = CBrowse_GetLinkName(object);
|
||||
if (object->name != linkname) {
|
||||
namestr2 = linkname->name;
|
||||
if (linkname->name[0] == '.')
|
||||
namestr2++;
|
||||
else
|
||||
nameid2 = linkname->id;
|
||||
}
|
||||
|
||||
EmitStandardData(browseFunction, fileID1, fileID2, startOffset, endOffset, namestr, nameid, namestr2, nameid2);
|
||||
|
||||
flags = 0;
|
||||
if (object->qual & Q_INLINE)
|
||||
flags |= kInline;
|
||||
if (object->qual & Q_PASCAL)
|
||||
flags |= kPascal;
|
||||
if (object->qual & Q_ASM)
|
||||
flags |= kAsm;
|
||||
if (object->sclass == TK_STATIC)
|
||||
flags |= kStatic;
|
||||
if (tfunc->flags & FUNC_METHOD)
|
||||
flags |= kMember;
|
||||
AppendGListLong(&gBrowseData, flags);
|
||||
|
||||
funcid = 0;
|
||||
if (tfunc->flags & FUNC_METHOD) {
|
||||
funcid = TYPE_METHOD(tfunc)->funcid;
|
||||
if (funcid <= 0) {
|
||||
TYPE_METHOD(tfunc)->funcid = funcid = gNextMemberFuncID++;
|
||||
}
|
||||
}
|
||||
AppendGListLong(&gBrowseData, funcid);
|
||||
}
|
||||
|
||||
void CBrowse_NewFunction(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(890, file1 && file1->recordbrowseinfo);
|
||||
|
||||
if (file2 && file2->fileID && startOffset > 0 && (endOffset + 1) >= startOffset)
|
||||
RecordFunction(object, file1->fileID, file2->fileID, startOffset, endOffset + 1);
|
||||
}
|
||||
|
||||
void CBrowse_NewData(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) {
|
||||
char *namestr = NULL;
|
||||
SInt32 flags = 0;
|
||||
Boolean is_const = is_const_object(object);
|
||||
|
||||
CError_ASSERT(912, file1 && file1->recordbrowseinfo);
|
||||
CError_ASSERT(913, object);
|
||||
|
||||
if (tk == ';')
|
||||
endOffset++;
|
||||
|
||||
if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) {
|
||||
HashNameNode *name = CBrowse_GetLinkName(object);
|
||||
if (object->name != name)
|
||||
namestr = name->name;
|
||||
|
||||
EmitStandardData(
|
||||
is_const ? browseConstant : browseGlobal,
|
||||
file1->fileID, file2->fileID,
|
||||
startOffset, endOffset,
|
||||
object->name->name, object->name->id,
|
||||
namestr, name->id
|
||||
);
|
||||
|
||||
if (!is_const) {
|
||||
if (object->sclass == TK_STATIC)
|
||||
flags |= kStatic;
|
||||
AppendGListLong(&gBrowseData, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_NewMacro(Macro *macro, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(951, !file || (file->recordbrowseinfo && !macro->is_special));
|
||||
|
||||
if (file && file->fileID && startOffset > 0 && endOffset >= startOffset)
|
||||
EmitStandardData(
|
||||
browseMacro,
|
||||
file->fileID, file->fileID,
|
||||
startOffset, endOffset,
|
||||
macro->name->name, macro->name->id,
|
||||
NULL, -1
|
||||
);
|
||||
}
|
||||
|
||||
void CBrowse_NewTemplateClass(TemplClass *tmclass, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) {
|
||||
CError_ASSERT(965, !file || file->recordbrowseinfo);
|
||||
|
||||
if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) {
|
||||
EmitStandardData(
|
||||
browseTemplate,
|
||||
file->fileID, file->fileID,
|
||||
startOffset, endOffset,
|
||||
tmclass->theclass.classname->name, tmclass->theclass.classname->id,
|
||||
NULL, -1
|
||||
);
|
||||
AppendGListByte(&gBrowseData, templateClass);
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowse_NewTemplateFunc(TemplateFunction *tmfunc) {
|
||||
CError_ASSERT(979, !tmfunc->srcfile || tmfunc->srcfile->recordbrowseinfo);
|
||||
|
||||
if (tmfunc->srcfile && tmfunc->srcfile->fileID && tmfunc->startoffset > 0 && tmfunc->endoffset >= tmfunc->startoffset) {
|
||||
EmitStandardData(
|
||||
browseTemplate,
|
||||
tmfunc->srcfile->fileID, tmfunc->srcfile->fileID,
|
||||
tmfunc->startoffset, tmfunc->endoffset,
|
||||
tmfunc->name->name, tmfunc->name->id,
|
||||
NULL, -1
|
||||
);
|
||||
AppendGListByte(&gBrowseData, templateFunction);
|
||||
}
|
||||
}
|
||||
|
||||
static void RecordUndefinedMemberFunctions(void) {
|
||||
int i;
|
||||
int count;
|
||||
Object **array;
|
||||
|
||||
COS_LockHandleHi(gMemberFuncList.data);
|
||||
|
||||
count = gMemberFuncList.size / sizeof(Object *);
|
||||
array = (Object **) *gMemberFuncList.data;
|
||||
for (i = 0; i < count; i++, array++) {
|
||||
if (IS_TYPE_FUNC((*array)->type) && !(TYPE_FUNC((*array)->type)->flags & FUNC_DEFINED))
|
||||
RecordFunction(*array, 0, 0, -1, -1);
|
||||
}
|
||||
|
||||
COS_UnlockHandle(gMemberFuncList.data);
|
||||
}
|
||||
2312
compiler_and_linker/FrontEnd/C/CClass.c
Normal file
2312
compiler_and_linker/FrontEnd/C/CClass.c
Normal file
File diff suppressed because it is too large
Load Diff
4845
compiler_and_linker/FrontEnd/C/CDecl.c
Normal file
4845
compiler_and_linker/FrontEnd/C/CDecl.c
Normal file
File diff suppressed because it is too large
Load Diff
1098
compiler_and_linker/FrontEnd/C/CError.c
Normal file
1098
compiler_and_linker/FrontEnd/C/CError.c
Normal file
File diff suppressed because it is too large
Load Diff
2183
compiler_and_linker/FrontEnd/C/CException.c
Normal file
2183
compiler_and_linker/FrontEnd/C/CException.c
Normal file
File diff suppressed because it is too large
Load Diff
4971
compiler_and_linker/FrontEnd/C/CExpr.c
Normal file
4971
compiler_and_linker/FrontEnd/C/CExpr.c
Normal file
File diff suppressed because it is too large
Load Diff
4206
compiler_and_linker/FrontEnd/C/CExpr2.c
Normal file
4206
compiler_and_linker/FrontEnd/C/CExpr2.c
Normal file
File diff suppressed because it is too large
Load Diff
2518
compiler_and_linker/FrontEnd/C/CExprConvMatch.c
Normal file
2518
compiler_and_linker/FrontEnd/C/CExprConvMatch.c
Normal file
File diff suppressed because it is too large
Load Diff
3224
compiler_and_linker/FrontEnd/C/CFunc.c
Normal file
3224
compiler_and_linker/FrontEnd/C/CFunc.c
Normal file
File diff suppressed because it is too large
Load Diff
3082
compiler_and_linker/FrontEnd/C/CInit.c
Normal file
3082
compiler_and_linker/FrontEnd/C/CInit.c
Normal file
File diff suppressed because it is too large
Load Diff
4206
compiler_and_linker/FrontEnd/C/CInline.c
Normal file
4206
compiler_and_linker/FrontEnd/C/CInline.c
Normal file
File diff suppressed because it is too large
Load Diff
713
compiler_and_linker/FrontEnd/C/CMangler.c
Normal file
713
compiler_and_linker/FrontEnd/C/CMangler.c
Normal file
@@ -0,0 +1,713 @@
|
||||
#include "compiler/CMangler.h"
|
||||
#include "compiler/CError.h"
|
||||
#include "compiler/CInt64.h"
|
||||
#include "compiler/CFunc.h"
|
||||
#include "compiler/CParser.h"
|
||||
#include "compiler/CTemplateTools.h"
|
||||
#include "compiler/CompilerTools.h"
|
||||
#include "compiler/enode.h"
|
||||
#include "compiler/objects.h"
|
||||
#include "compiler/scopes.h"
|
||||
#include "compiler/templates.h"
|
||||
#include "compiler/types.h"
|
||||
#include "cos.h"
|
||||
|
||||
HashNameNode *constructor_name_node;
|
||||
HashNameNode *destructor_name_node;
|
||||
HashNameNode *asop_name_node;
|
||||
|
||||
// forward decls
|
||||
static void CMangler_MangleClassName(TypeClass *tclass);
|
||||
static void CMangler_MangleTypeAppend(Type *type, UInt32 qual);
|
||||
static void CMangler_MangleArgs(FuncArg *args);
|
||||
|
||||
void CMangler_Setup(void) {
|
||||
constructor_name_node = GetHashNameNodeExport("__ct");
|
||||
destructor_name_node = GetHashNameNodeExport("__dt");
|
||||
asop_name_node = GetHashNameNodeExport("__as");
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_BasicDtorName(void) {
|
||||
return GetHashNameNodeExport("__dtb");
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_VBaseDtorName(void) {
|
||||
return GetHashNameNodeExport("__dtv");
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_ArrayDtorName(void) {
|
||||
return GetHashNameNodeExport("__dta");
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_SDeleteDtorName(void) {
|
||||
return GetHashNameNodeExport("__dts");
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_DeleteDtorName(void) {
|
||||
return GetHashNameNodeExport("__dt");
|
||||
}
|
||||
|
||||
char *CMangler_GetOperator(HashNameNode *name) {
|
||||
char *str;
|
||||
|
||||
if (name == asop_name_node)
|
||||
return "operator=";
|
||||
|
||||
str = name->name;
|
||||
if (!strcmp(str, "__nw")) return "operator new";
|
||||
if (!strcmp(str, "__dl")) return "operator delete";
|
||||
if (!strcmp(str, "__nwa")) return "operator new[]";
|
||||
if (!strcmp(str, "__dla")) return "operator delete[]";
|
||||
if (!strcmp(str, "__pl")) return "operator+";
|
||||
if (!strcmp(str, "__mi")) return "operator-";
|
||||
if (!strcmp(str, "__ml")) return "operator*";
|
||||
if (!strcmp(str, "__dv")) return "operator/";
|
||||
if (!strcmp(str, "__md")) return "operator%";
|
||||
if (!strcmp(str, "__er")) return "operator^";
|
||||
if (!strcmp(str, "__ad")) return "operator&";
|
||||
if (!strcmp(str, "__or")) return "operator|";
|
||||
if (!strcmp(str, "__co")) return "operator~";
|
||||
if (!strcmp(str, "__nt")) return "operator!";
|
||||
if (!strcmp(str, "__lt")) return "operator<";
|
||||
if (!strcmp(str, "__gt")) return "operator>";
|
||||
if (!strcmp(str, "__apl")) return "operator+=";
|
||||
if (!strcmp(str, "__ami")) return "operator-=";
|
||||
if (!strcmp(str, "__amu")) return "operator*=";
|
||||
if (!strcmp(str, "__adv")) return "operator/=";
|
||||
if (!strcmp(str, "__amd")) return "operator%=";
|
||||
if (!strcmp(str, "__aer")) return "operator^=";
|
||||
if (!strcmp(str, "__aad")) return "operator&=";
|
||||
if (!strcmp(str, "__aor")) return "operator|=";
|
||||
if (!strcmp(str, "__ls")) return "operator<<";
|
||||
if (!strcmp(str, "__rs")) return "operator>>";
|
||||
if (!strcmp(str, "__als")) return "operator<<=";
|
||||
if (!strcmp(str, "__ars")) return "operator>>=";
|
||||
if (!strcmp(str, "__eq")) return "operator==";
|
||||
if (!strcmp(str, "__ne")) return "operator!=";
|
||||
if (!strcmp(str, "__le")) return "operator<=";
|
||||
if (!strcmp(str, "__ge")) return "operator>=";
|
||||
if (!strcmp(str, "__aa")) return "operator&&";
|
||||
if (!strcmp(str, "__oo")) return "operator||";
|
||||
if (!strcmp(str, "__pp")) return "operator++";
|
||||
if (!strcmp(str, "__mm")) return "operator--";
|
||||
if (!strcmp(str, "__cm")) return "operator,";
|
||||
if (!strcmp(str, "__rm")) return "operator->*";
|
||||
if (!strcmp(str, "__rf")) return "operator*";
|
||||
if (!strcmp(str, "__cl")) return "operator()";
|
||||
if (!strcmp(str, "__vc")) return "operator[]";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_OperatorName(short token) {
|
||||
switch (token) {
|
||||
case TK_NEW: return GetHashNameNodeExport("__nw");
|
||||
case TK_DELETE: return GetHashNameNodeExport("__dl");
|
||||
case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa");
|
||||
case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla");
|
||||
case '+': return GetHashNameNodeExport("__pl");
|
||||
case '-': return GetHashNameNodeExport("__mi");
|
||||
case '*': return GetHashNameNodeExport("__ml");
|
||||
case '/': return GetHashNameNodeExport("__dv");
|
||||
case '%': return GetHashNameNodeExport("__md");
|
||||
case '^': return GetHashNameNodeExport("__er");
|
||||
case '&': return GetHashNameNodeExport("__ad");
|
||||
case '|': return GetHashNameNodeExport("__or");
|
||||
case '~': return GetHashNameNodeExport("__co");
|
||||
case '!': return GetHashNameNodeExport("__nt");
|
||||
case '=': return asop_name_node;
|
||||
case '<': return GetHashNameNodeExport("__lt");
|
||||
case '>': return GetHashNameNodeExport("__gt");
|
||||
case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl");
|
||||
case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami");
|
||||
case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu");
|
||||
case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv");
|
||||
case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd");
|
||||
case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer");
|
||||
case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad");
|
||||
case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor");
|
||||
case TK_SHL: return GetHashNameNodeExport("__ls");
|
||||
case TK_SHR: return GetHashNameNodeExport("__rs");
|
||||
case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als");
|
||||
case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars");
|
||||
case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq");
|
||||
case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne");
|
||||
case TK_LESS_EQUAL: return GetHashNameNodeExport("__le");
|
||||
case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge");
|
||||
case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa");
|
||||
case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo");
|
||||
case TK_INCREMENT: return GetHashNameNodeExport("__pp");
|
||||
case TK_DECREMENT: return GetHashNameNodeExport("__mm");
|
||||
case ',': return GetHashNameNodeExport("__cm");
|
||||
case TK_ARROW_STAR: return GetHashNameNodeExport("__rm");
|
||||
case TK_ARROW: return GetHashNameNodeExport("__rf");
|
||||
case '(': return GetHashNameNodeExport("__cl");
|
||||
case '[': return GetHashNameNodeExport("__vc");
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_VTableName(TypeClass *theclass) {
|
||||
HashNameNode *name;
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListName(&name_mangle_list, "__vt__");
|
||||
CMangler_MangleClassName(theclass);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) {
|
||||
HashNameNode *name;
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListName(&name_mangle_list, "__RTTI__");
|
||||
CMangler_MangleTypeAppend(type, qual);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_ThunkName(Object *vfunc, SInt32 this_delta, SInt32 return_delta, SInt32 ctoroffset) {
|
||||
HashNameNode *linkname;
|
||||
HashNameNode *name;
|
||||
char buf[64];
|
||||
|
||||
linkname = CMangler_GetLinkName(vfunc);
|
||||
name_mangle_list.size = 0;
|
||||
if (return_delta == 0) {
|
||||
if (ctoroffset < 0)
|
||||
sprintf(buf, "_@%" PRId32 "@", -this_delta);
|
||||
else
|
||||
sprintf(buf, "_@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset);
|
||||
} else {
|
||||
sprintf(buf, "_@%" PRId32 "@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset, return_delta);
|
||||
}
|
||||
AppendGListName(&name_mangle_list, buf);
|
||||
AppendGListID(&name_mangle_list, linkname->name + 1);
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
static void CMangler_CheckTemplateArguments(TemplArg *arg) {
|
||||
ENode *expr;
|
||||
|
||||
while (arg) {
|
||||
if (arg->pid.type == TPT_NONTYPE) {
|
||||
expr = arg->data.paramdecl.expr;
|
||||
CError_ASSERT(360, expr);
|
||||
if (expr->rtype->type != TYPETEMPLDEPEXPR) {
|
||||
switch (expr->type) {
|
||||
case EINTCONST:
|
||||
break;
|
||||
case EOBJREF:
|
||||
CMangler_GetLinkName(expr->data.objref);
|
||||
break;
|
||||
default:
|
||||
CError_FATAL(383);
|
||||
}
|
||||
}
|
||||
}
|
||||
arg = arg->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void CMangler_AppendTemplateArgumentList(TemplArg *arg) {
|
||||
ENode *expr;
|
||||
char buf[32];
|
||||
|
||||
AppendGListByte(&name_mangle_list, '<');
|
||||
|
||||
while (arg) {
|
||||
if (arg->pid.type == TPT_NONTYPE) {
|
||||
expr = arg->data.paramdecl.expr;
|
||||
CError_ASSERT(409, expr);
|
||||
if (expr->rtype->type != TYPETEMPLDEPEXPR) {
|
||||
switch (expr->type) {
|
||||
case EINTCONST:
|
||||
CInt64_PrintDec(buf, expr->data.intval);
|
||||
AppendGListName(&name_mangle_list, buf);
|
||||
break;
|
||||
case EOBJREF:
|
||||
AppendGListByte(&name_mangle_list, '&');
|
||||
AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name);
|
||||
break;
|
||||
default:
|
||||
CError_FATAL(452);
|
||||
}
|
||||
} else {
|
||||
AppendGListByte(&name_mangle_list, 'T');
|
||||
}
|
||||
} else if (arg->pid.type == TPT_TYPE) {
|
||||
CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual);
|
||||
} else {
|
||||
CError_ASSERT(467, arg->pid.type == TPT_TEMPLATE);
|
||||
CMangler_MangleTypeAppend(arg->data.ttargtype, 0);
|
||||
}
|
||||
|
||||
if (arg->next)
|
||||
AppendGListByte(&name_mangle_list, ',');
|
||||
arg = arg->next;
|
||||
}
|
||||
|
||||
AppendGListByte(&name_mangle_list, '>');
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) {
|
||||
HashNameNode *name;
|
||||
|
||||
CMangler_CheckTemplateArguments(args);
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListName(&name_mangle_list, basename->name);
|
||||
CMangler_AppendTemplateArgumentList(args);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
static void CMangler_MangleTypeName(char *str) {
|
||||
char buf[16];
|
||||
|
||||
sprintf(buf, "%d", strlen(str));
|
||||
AppendGListName(&name_mangle_list, buf);
|
||||
AppendGListName(&name_mangle_list, str);
|
||||
}
|
||||
|
||||
static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) {
|
||||
char *stack[10];
|
||||
int stackp;
|
||||
|
||||
stack[0] = str;
|
||||
stackp = 1;
|
||||
while (nspace) {
|
||||
if (nspace->name) {
|
||||
stack[stackp++] = nspace->name->name;
|
||||
if (stackp >= 9)
|
||||
break;
|
||||
}
|
||||
nspace = nspace->parent;
|
||||
}
|
||||
|
||||
if (stackp > 1) {
|
||||
AppendGListByte(&name_mangle_list, 'Q');
|
||||
AppendGListByte(&name_mangle_list, '0' + stackp);
|
||||
}
|
||||
|
||||
while (--stackp >= 0)
|
||||
CMangler_MangleTypeName(stack[stackp]);
|
||||
}
|
||||
|
||||
static void CMangler_MangleClassName(TypeClass *tclass) {
|
||||
if (!tclass->classname)
|
||||
CMangler_MangleNameSpaceName(tclass->nspace->parent, "class");
|
||||
else
|
||||
CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name);
|
||||
}
|
||||
|
||||
static void CMangler_MangleQualifier(UInt32 qual) {
|
||||
if (qual & Q_CONST)
|
||||
AppendGListByte(&name_mangle_list, 'C');
|
||||
if (qual & Q_VOLATILE)
|
||||
AppendGListByte(&name_mangle_list, 'V');
|
||||
}
|
||||
|
||||
static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) {
|
||||
char buf[16];
|
||||
|
||||
switch (type->type) {
|
||||
case TYPEVOID:
|
||||
CMangler_MangleQualifier(qual);
|
||||
AppendGListByte(&name_mangle_list, 'v');
|
||||
break;
|
||||
case TYPEINT:
|
||||
case TYPEFLOAT:
|
||||
CMangler_MangleQualifier(qual);
|
||||
switch (TYPE_INTEGRAL(type)->integral) {
|
||||
case IT_BOOL:
|
||||
AppendGListByte(&name_mangle_list, 'b');
|
||||
return;
|
||||
case IT_CHAR:
|
||||
AppendGListByte(&name_mangle_list, 'c');
|
||||
return;
|
||||
case IT_WCHAR_T:
|
||||
AppendGListByte(&name_mangle_list, 'w');
|
||||
return;
|
||||
case IT_UCHAR:
|
||||
AppendGListName(&name_mangle_list, "Uc");
|
||||
return;
|
||||
case IT_SCHAR:
|
||||
AppendGListName(&name_mangle_list, "Sc");
|
||||
return;
|
||||
case IT_SHORT:
|
||||
AppendGListByte(&name_mangle_list, 's');
|
||||
return;
|
||||
case IT_USHORT:
|
||||
AppendGListName(&name_mangle_list, "Us");
|
||||
return;
|
||||
case IT_INT:
|
||||
AppendGListByte(&name_mangle_list, 'i');
|
||||
return;
|
||||
case IT_UINT:
|
||||
AppendGListName(&name_mangle_list, "Ui");
|
||||
return;
|
||||
case IT_LONG:
|
||||
AppendGListByte(&name_mangle_list, 'l');
|
||||
return;
|
||||
case IT_ULONG:
|
||||
AppendGListName(&name_mangle_list, "Ul");
|
||||
return;
|
||||
case IT_LONGLONG:
|
||||
AppendGListByte(&name_mangle_list, 'x');
|
||||
return;
|
||||
case IT_ULONGLONG:
|
||||
AppendGListName(&name_mangle_list, "Ux");
|
||||
return;
|
||||
case IT_FLOAT:
|
||||
AppendGListByte(&name_mangle_list, 'f');
|
||||
return;
|
||||
case IT_SHORTDOUBLE:
|
||||
AppendGListByte(&name_mangle_list, 'D');
|
||||
return;
|
||||
case IT_DOUBLE:
|
||||
AppendGListByte(&name_mangle_list, 'd');
|
||||
return;
|
||||
case IT_LONGDOUBLE:
|
||||
AppendGListByte(&name_mangle_list, 'r');
|
||||
return;
|
||||
default:
|
||||
CError_FATAL(619);
|
||||
}
|
||||
case TYPEENUM:
|
||||
CMangler_MangleQualifier(qual);
|
||||
if (!TYPE_ENUM(type)->enumname)
|
||||
CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum");
|
||||
else
|
||||
CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name);
|
||||
break;
|
||||
case TYPEPOINTER:
|
||||
CMangler_MangleQualifier(TYPE_POINTER(type)->qual);
|
||||
if (TYPE_POINTER(type)->qual & Q_REFERENCE)
|
||||
AppendGListByte(&name_mangle_list, 'R');
|
||||
else
|
||||
AppendGListByte(&name_mangle_list, 'P');
|
||||
CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
|
||||
break;
|
||||
case TYPEMEMBERPOINTER:
|
||||
if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) {
|
||||
AppendGListName(&name_mangle_list, "3<T>");
|
||||
} else {
|
||||
CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual);
|
||||
AppendGListByte(&name_mangle_list, 'M');
|
||||
CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2));
|
||||
CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual);
|
||||
}
|
||||
break;
|
||||
case TYPEARRAY:
|
||||
AppendGListByte(&name_mangle_list, 'A');
|
||||
if (TYPE_POINTER(type)->target->size) {
|
||||
sprintf(buf, "%" PRId32 "", type->size / TYPE_POINTER(type)->target->size);
|
||||
AppendGListName(&name_mangle_list, buf);
|
||||
} else {
|
||||
AppendGListByte(&name_mangle_list, '0');
|
||||
}
|
||||
AppendGListByte(&name_mangle_list, '_');
|
||||
CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
|
||||
break;
|
||||
case TYPEFUNC:
|
||||
CMangler_MangleQualifier(qual);
|
||||
AppendGListByte(&name_mangle_list, 'F');
|
||||
CMangler_MangleArgs(TYPE_FUNC(type)->args);
|
||||
AppendGListByte(&name_mangle_list, '_');
|
||||
CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual);
|
||||
break;
|
||||
case TYPESTRUCT:
|
||||
CMangler_MangleQualifier(qual);
|
||||
switch (TYPE_STRUCT(type)->stype) {
|
||||
case STRUCT_VECTOR_UCHAR:
|
||||
AppendGListName(&name_mangle_list, "XUc");
|
||||
return;
|
||||
case STRUCT_VECTOR_SCHAR:
|
||||
AppendGListName(&name_mangle_list, "Xc");
|
||||
return;
|
||||
case STRUCT_VECTOR_BCHAR:
|
||||
AppendGListName(&name_mangle_list, "XC");
|
||||
return;
|
||||
case STRUCT_VECTOR_USHORT:
|
||||
AppendGListName(&name_mangle_list, "XUs");
|
||||
return;
|
||||
case STRUCT_VECTOR_SSHORT:
|
||||
AppendGListName(&name_mangle_list, "Xs");
|
||||
return;
|
||||
case STRUCT_VECTOR_BSHORT:
|
||||
AppendGListName(&name_mangle_list, "XS");
|
||||
return;
|
||||
case STRUCT_VECTOR_UINT:
|
||||
AppendGListName(&name_mangle_list, "XUi");
|
||||
return;
|
||||
case STRUCT_VECTOR_SINT:
|
||||
AppendGListName(&name_mangle_list, "Xi");
|
||||
return;
|
||||
case STRUCT_VECTOR_BINT:
|
||||
AppendGListName(&name_mangle_list, "XI");
|
||||
return;
|
||||
case STRUCT_VECTOR_FLOAT:
|
||||
AppendGListName(&name_mangle_list, "Xf");
|
||||
return;
|
||||
case STRUCT_VECTOR_PIXEL:
|
||||
AppendGListName(&name_mangle_list, "Xp");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) {
|
||||
CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (TYPE_STRUCT(type)->stype) {
|
||||
case STRUCT_TYPE_STRUCT:
|
||||
AppendGListName(&name_mangle_list, "struct");
|
||||
break;
|
||||
case STRUCT_TYPE_UNION:
|
||||
AppendGListName(&name_mangle_list, "union");
|
||||
break;
|
||||
case STRUCT_TYPE_CLASS:
|
||||
AppendGListName(&name_mangle_list, "class");
|
||||
break;
|
||||
default:
|
||||
CError_FATAL(701);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPECLASS:
|
||||
CMangler_MangleQualifier(qual);
|
||||
CMangler_MangleClassName(TYPE_CLASS(type));
|
||||
break;
|
||||
|
||||
case TYPETEMPLATE:
|
||||
AppendGListName(&name_mangle_list, "1T");
|
||||
break;
|
||||
|
||||
default:
|
||||
CError_FATAL(716);
|
||||
}
|
||||
}
|
||||
|
||||
void CMangler_MangleType(Type *type, UInt32 qual) {
|
||||
name_mangle_list.size = 0;
|
||||
CMangler_MangleTypeAppend(type, qual);
|
||||
}
|
||||
|
||||
static void CMangler_MangleArgs(FuncArg *args) {
|
||||
TypePointer ptr;
|
||||
|
||||
if (args) {
|
||||
if (args->type) {
|
||||
while (args) {
|
||||
if (args != &elipsis && args != &oldstyle) {
|
||||
if (args->type->type == TYPEPOINTER) {
|
||||
ptr = *TYPE_POINTER(args->type);
|
||||
ptr.qual &= ~(Q_CONST | Q_VOLATILE);
|
||||
CMangler_MangleTypeAppend(TYPE(&ptr), args->qual);
|
||||
} else {
|
||||
CMangler_MangleTypeAppend(args->type, 0);
|
||||
}
|
||||
} else {
|
||||
AppendGListByte(&name_mangle_list, 'e');
|
||||
}
|
||||
args = args->next;
|
||||
}
|
||||
} else {
|
||||
AppendGListByte(&name_mangle_list, 'e');
|
||||
}
|
||||
} else {
|
||||
AppendGListByte(&name_mangle_list, 'v');
|
||||
}
|
||||
}
|
||||
|
||||
static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) {
|
||||
TypeFunc *tfunc = TYPE_FUNC(obj->type);
|
||||
FuncArg *arg = tfunc->args;
|
||||
|
||||
AppendGListName(&name_mangle_list, obj->name->name);
|
||||
if (obj->u.func.inst) {
|
||||
if (tfunc->flags & FUNC_CONVERSION)
|
||||
CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
|
||||
CMangler_AppendTemplateArgumentList(obj->u.func.inst->args);
|
||||
}
|
||||
AppendGListName(&name_mangle_list, "__");
|
||||
while (nspace && nspace->name == NULL)
|
||||
nspace = nspace->parent;
|
||||
|
||||
if (nspace) {
|
||||
CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
|
||||
if (nspace->theclass) {
|
||||
if (obj->name == destructor_name_node) {
|
||||
AppendGListName(&name_mangle_list, "Fv");
|
||||
return;
|
||||
}
|
||||
if (arg) {
|
||||
if (obj->name == constructor_name_node) {
|
||||
arg = arg->next;
|
||||
if (arg && (nspace->theclass->flags & CLASS_HAS_VBASES))
|
||||
arg = arg->next;
|
||||
} else {
|
||||
if ((tfunc->flags & FUNC_METHOD) && !TYPE_METHOD(tfunc)->is_static) {
|
||||
CMangler_MangleQualifier(arg->qual);
|
||||
arg = arg->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppendGListByte(&name_mangle_list, 'F');
|
||||
CMangler_MangleArgs(arg);
|
||||
if (obj->u.func.inst && copts.new_mangler) {
|
||||
AppendGListByte(&name_mangle_list, '_');
|
||||
CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
|
||||
}
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) {
|
||||
HashNameNode *name;
|
||||
|
||||
if (CTemplTool_IsTemplateArgumentDependentType(type))
|
||||
return GetHashNameNodeExport("__op");
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListName(&name_mangle_list, "__op");
|
||||
CMangler_MangleTypeAppend(type, qual);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
static HashNameNode *CMangler_MangleNameToUpper(char *str) {
|
||||
HashNameNode *name;
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
while (*str) {
|
||||
AppendGListByte(&name_mangle_list, toupper(*(str++)));
|
||||
}
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
static HashNameNode *CMangler_FunctionLinkName(Object *obj) {
|
||||
HashNameNode *name;
|
||||
NameSpace *nspace;
|
||||
|
||||
if (obj->u.func.inst)
|
||||
CMangler_CheckTemplateArguments(obj->u.func.inst->args);
|
||||
|
||||
for (nspace = obj->nspace; nspace; nspace = nspace->parent) {
|
||||
if (nspace->name)
|
||||
break;
|
||||
}
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) {
|
||||
AppendGListData(&name_mangle_list, "_", 1);
|
||||
AppendGListID(&name_mangle_list, obj->name->name);
|
||||
} else if ((obj->qual & Q_MANGLE_NAME) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) {
|
||||
AppendGListData(&name_mangle_list, "_", 1);
|
||||
CMangler_MangleFunction(obj, nspace);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
} else {
|
||||
AppendGListData(&name_mangle_list, "_", 1);
|
||||
AppendGListID(&name_mangle_list, obj->name->name);
|
||||
}
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_GetCovariantFunctionName(Object *dobj, TypeClass *theclass) {
|
||||
HashNameNode *name;
|
||||
|
||||
name = CMangler_GetLinkName(dobj);
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListName(&name_mangle_list, name->name);
|
||||
AppendGListName(&name_mangle_list, "@@");
|
||||
CMangler_MangleTypeAppend(TYPE(theclass), 0);
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
static HashNameNode *CMangler_DataLinkName(Object *obj) {
|
||||
NameSpace *nspace;
|
||||
HashNameNode *name;
|
||||
|
||||
nspace = obj->nspace;
|
||||
while (nspace && nspace->name == NULL)
|
||||
nspace = nspace->parent;
|
||||
|
||||
name_mangle_list.size = 0;
|
||||
AppendGListData(&name_mangle_list, "_", 1);
|
||||
AppendGListName(&name_mangle_list, obj->name->name);
|
||||
|
||||
while (nspace && nspace->name == NULL)
|
||||
nspace = nspace->parent;
|
||||
if (nspace && (obj->qual & Q_MANGLE_NAME)) {
|
||||
AppendGListName(&name_mangle_list, "__");
|
||||
CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
|
||||
}
|
||||
AppendGListByte(&name_mangle_list, 0);
|
||||
|
||||
COS_LockHandle(name_mangle_list.data);
|
||||
name = GetHashNameNodeExport(*name_mangle_list.data);
|
||||
COS_UnlockHandle(name_mangle_list.data);
|
||||
return name;
|
||||
}
|
||||
|
||||
HashNameNode *CMangler_GetLinkName(Object *obj) {
|
||||
while (obj->datatype == DALIAS)
|
||||
obj = obj->u.alias.object;
|
||||
|
||||
switch (obj->datatype) {
|
||||
case DFUNC:
|
||||
case DVFUNC:
|
||||
if (!obj->u.func.linkname)
|
||||
obj->u.func.linkname = CMangler_FunctionLinkName(obj);
|
||||
return obj->u.func.linkname;
|
||||
case DDATA:
|
||||
if (!obj->u.data.linkname)
|
||||
obj->u.data.linkname = CMangler_DataLinkName(obj);
|
||||
return obj->u.data.linkname;
|
||||
case DINLINEFUNC:
|
||||
return CMangler_FunctionLinkName(obj);
|
||||
case DLOCAL:
|
||||
case DABSOLUTE:
|
||||
case DLABEL:
|
||||
return obj->name;
|
||||
case DNONLAZYPTR:
|
||||
if (!obj->u.toc.linkname)
|
||||
obj->u.toc.linkname = CMangler_DataLinkName(obj);
|
||||
return obj->u.toc.linkname;
|
||||
default:
|
||||
CError_FATAL(1110);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
3477
compiler_and_linker/FrontEnd/C/CParser.c
Normal file
3477
compiler_and_linker/FrontEnd/C/CParser.c
Normal file
File diff suppressed because it is too large
Load Diff
3482
compiler_and_linker/FrontEnd/C/CPrec.c
Normal file
3482
compiler_and_linker/FrontEnd/C/CPrec.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
#include "compiler/CodeGen.h"
|
||||
#include "compiler/CompilerTools.h"
|
||||
#include "compiler/FuncLevelAsmPPC.h"
|
||||
#include "compiler/IroPointerAnalysis.h"
|
||||
#include "../Optimizer/IroPointerAnalysis.h"
|
||||
#include "compiler/ObjGenMachO.h"
|
||||
#include "compiler/objects.h"
|
||||
#include "compiler/scopes.h"
|
||||
|
||||
676
compiler_and_linker/FrontEnd/C/CPreprocess.c
Normal file
676
compiler_and_linker/FrontEnd/C/CPreprocess.c
Normal file
@@ -0,0 +1,676 @@
|
||||
#include "compiler/CPreprocess.h"
|
||||
#include "compiler/CError.h"
|
||||
#include "compiler/CMachine.h"
|
||||
#include "compiler/CParser.h"
|
||||
#include "compiler/CPrep.h"
|
||||
#include "compiler/CPrepTokenizer.h"
|
||||
#include "compiler/CompilerTools.h"
|
||||
#include "cos.h"
|
||||
|
||||
void CPrep_PreprocessDumpNewLine(void) {
|
||||
if (copts.line_prepdump && pplist.data && filesp >= 0)
|
||||
AppendGListData(&pplist, "\r", 1);
|
||||
}
|
||||
|
||||
void CPrep_PreprocessDumpFileInfo(Boolean flag) {
|
||||
char linebuf[512];
|
||||
int size;
|
||||
SInt16 tmp16;
|
||||
SInt32 tmp32;
|
||||
Str255 filename;
|
||||
|
||||
if (pplist.data && filesp >= 0) {
|
||||
if (nlflag && flag && pplist.size > 0)
|
||||
AppendGListName(&pplist, "\r");
|
||||
|
||||
if (copts.line_prepdump)
|
||||
size = sprintf(linebuf, "#line % " PRId32 "\t\"", linenumber);
|
||||
else
|
||||
size = sprintf(linebuf, "/* #line % " PRId32 "\t\"", linenumber);
|
||||
AppendGListData(&pplist, linebuf, size);
|
||||
|
||||
if (copts.fullpath_prepdump) {
|
||||
if (prep_file->nameNode) {
|
||||
AppendGListData(&pplist, prep_file->nameNode->name, strlen(prep_file->nameNode->name));
|
||||
} else {
|
||||
COS_FileGetPathName(linebuf, &prep_file->textfile, &tmp32);
|
||||
AppendGListData(&pplist, linebuf, strlen(linebuf));
|
||||
}
|
||||
} else {
|
||||
if (prep_file->nameNode) {
|
||||
char *work = prep_file->nameNode->name + strlen(prep_file->nameNode->name);
|
||||
while (work > prep_file->nameNode->name && !strchr("/\\:", work[-1]))
|
||||
work--;
|
||||
|
||||
AppendGListData(&pplist, work, strlen(work));
|
||||
} else {
|
||||
COS_FileGetFSSpecInfo(&prep_file->textfile, &tmp16, &tmp32, filename);
|
||||
AppendGListData(&pplist, &filename[1], filename[0]);
|
||||
}
|
||||
}
|
||||
|
||||
size = sprintf(linebuf, "\"\t/* stack depth % " PRId32 " */", filesp);
|
||||
AppendGListData(&pplist, linebuf, size);
|
||||
|
||||
if (copts.line_prepdump && flag)
|
||||
CPrep_PreprocessDumpNewLine();
|
||||
|
||||
nlflag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void CPrep_DumpWString(UInt16 *str, short len) {
|
||||
int divisor;
|
||||
int i;
|
||||
|
||||
while (len--) {
|
||||
if (*str < 32) {
|
||||
AppendGListByte(&pplist, '\\');
|
||||
switch (*str) {
|
||||
case 7:
|
||||
AppendGListByte(&pplist, 'a');
|
||||
break;
|
||||
case 8:
|
||||
AppendGListByte(&pplist, 'b');
|
||||
break;
|
||||
case 27:
|
||||
AppendGListByte(&pplist, 'e');
|
||||
break;
|
||||
case 12:
|
||||
AppendGListByte(&pplist, 'f');
|
||||
break;
|
||||
case 10:
|
||||
AppendGListByte(&pplist, 'n');
|
||||
break;
|
||||
case 13:
|
||||
AppendGListByte(&pplist, 'r');
|
||||
break;
|
||||
case 9:
|
||||
AppendGListByte(&pplist, 't');
|
||||
break;
|
||||
case 11:
|
||||
AppendGListByte(&pplist, 'v');
|
||||
break;
|
||||
default:
|
||||
if (*str >= 8)
|
||||
AppendGListByte(&pplist, '0' + (*str / 8));
|
||||
AppendGListByte(&pplist, '0' + (*str % 8));
|
||||
}
|
||||
} else if (*str > 255) {
|
||||
AppendGListByte(&pplist, '\\');
|
||||
AppendGListByte(&pplist, 'x');
|
||||
|
||||
divisor = 0x1000;
|
||||
for (i = 0; i < 4; i++) {
|
||||
AppendGListByte(&pplist, "0123456789ABCDEF"[(*str / divisor) % 16]);
|
||||
divisor /= 16;
|
||||
}
|
||||
} else {
|
||||
switch (*str) {
|
||||
case '"':
|
||||
case '\\':
|
||||
AppendGListByte(&pplist, '\\');
|
||||
default:
|
||||
AppendGListByte(&pplist, *str);
|
||||
}
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static void CPrep_DumpString(UInt8 *str, short len) {
|
||||
while (len--) {
|
||||
if (*str < 32) {
|
||||
AppendGListByte(&pplist, '\\');
|
||||
switch (*str) {
|
||||
case 7:
|
||||
AppendGListByte(&pplist, 'a');
|
||||
break;
|
||||
case 8:
|
||||
AppendGListByte(&pplist, 'b');
|
||||
break;
|
||||
case 12:
|
||||
AppendGListByte(&pplist, 'f');
|
||||
break;
|
||||
case 10:
|
||||
AppendGListByte(&pplist, 'n');
|
||||
break;
|
||||
case 13:
|
||||
AppendGListByte(&pplist, 'r');
|
||||
break;
|
||||
case 9:
|
||||
AppendGListByte(&pplist, 't');
|
||||
break;
|
||||
case 11:
|
||||
AppendGListByte(&pplist, 'v');
|
||||
break;
|
||||
default:
|
||||
if (*str >= 8)
|
||||
AppendGListByte(&pplist, '0' + (*str / 8));
|
||||
AppendGListByte(&pplist, '0' + (*str % 8));
|
||||
}
|
||||
} else {
|
||||
switch (*str) {
|
||||
case '"':
|
||||
case '\\':
|
||||
AppendGListByte(&pplist, '\\');
|
||||
default:
|
||||
AppendGListByte(&pplist, *str);
|
||||
}
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void CPrep_Preprocess(void) {
|
||||
short innertoken;
|
||||
short token;
|
||||
char startToken;
|
||||
char endToken;
|
||||
int depth;
|
||||
Boolean save_asmpoundcomment; // r16
|
||||
Boolean save_cplusplus; // r15
|
||||
char *p;
|
||||
|
||||
startToken = 0;
|
||||
depth = 0;
|
||||
|
||||
if (InitGList(&pplist, 10000))
|
||||
CError_NoMem();
|
||||
|
||||
nlflag = 0;
|
||||
spaceskip = 0;
|
||||
|
||||
if ((token = lex())) {
|
||||
do {
|
||||
if (nlflag) {
|
||||
if (!copts.line_prepdump)
|
||||
AppendGListData(&pplist, "\r", 1);
|
||||
} else {
|
||||
if (spaceskip)
|
||||
AppendGListByte(&pplist, ' ');
|
||||
}
|
||||
|
||||
while (1) {
|
||||
switch ((innertoken = token)) {
|
||||
case '(':
|
||||
case ')':
|
||||
case '{':
|
||||
case '}':
|
||||
AppendGListByte(&pplist, token);
|
||||
if (cprep_nostring) {
|
||||
if (innertoken == startToken) {
|
||||
depth++;
|
||||
} else if (innertoken == endToken) {
|
||||
if (--depth == 0) {
|
||||
cprep_nostring = 0;
|
||||
in_assembler = 0;
|
||||
copts.cplusplus = save_cplusplus;
|
||||
copts.asmpoundcomment = save_asmpoundcomment;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TK_INTCONST:
|
||||
case TK_FLOATCONST:
|
||||
if (tokenstacklevel > 0)
|
||||
p = macropos;
|
||||
else
|
||||
p = prep_file_start + ts_current[-1].tokenoffset;
|
||||
AppendGListData(&pplist, p, pos - p);
|
||||
break;
|
||||
|
||||
case TK_IDENTIFIER:
|
||||
AppendGListData(&pplist, tkidentifier->name, strlen(tkidentifier->name));
|
||||
break;
|
||||
|
||||
case TK_AUTO:
|
||||
AppendGListData(&pplist, "auto", 4);
|
||||
break;
|
||||
case TK_REGISTER:
|
||||
AppendGListData(&pplist, "register", 8);
|
||||
break;
|
||||
case TK_STATIC:
|
||||
AppendGListData(&pplist, "static", 6);
|
||||
break;
|
||||
case TK_EXTERN:
|
||||
AppendGListData(&pplist, "extern", 6);
|
||||
break;
|
||||
case TK_TYPEDEF:
|
||||
AppendGListData(&pplist, "typedef", 7);
|
||||
break;
|
||||
case TK_INLINE:
|
||||
AppendGListData(&pplist, "inline", 6);
|
||||
break;
|
||||
case TK_VOID:
|
||||
AppendGListData(&pplist, "void", 4);
|
||||
break;
|
||||
case TK_CHAR:
|
||||
AppendGListData(&pplist, "char", 4);
|
||||
break;
|
||||
case TK_SHORT:
|
||||
AppendGListData(&pplist, "short", 5);
|
||||
break;
|
||||
case TK_INT:
|
||||
AppendGListData(&pplist, "int", 3);
|
||||
break;
|
||||
case TK_LONG:
|
||||
AppendGListData(&pplist, "long", 4);
|
||||
break;
|
||||
case TK_FLOAT:
|
||||
AppendGListData(&pplist, "float", 5);
|
||||
break;
|
||||
case TK_DOUBLE:
|
||||
AppendGListData(&pplist, "double", 6);
|
||||
break;
|
||||
case TK_SIGNED:
|
||||
AppendGListData(&pplist, "signed", 6);
|
||||
break;
|
||||
case TK_UNSIGNED:
|
||||
AppendGListData(&pplist, "unsigned", 8);
|
||||
break;
|
||||
case TK_STRUCT:
|
||||
AppendGListData(&pplist, "struct", 6);
|
||||
break;
|
||||
case TK_UNION:
|
||||
AppendGListData(&pplist, "union", 5);
|
||||
break;
|
||||
case TK_ENUM:
|
||||
AppendGListData(&pplist, "enum", 4);
|
||||
break;
|
||||
case TK_CLASS:
|
||||
AppendGListData(&pplist, "class", 5);
|
||||
break;
|
||||
case TK_CONST:
|
||||
AppendGListData(&pplist, "const", 5);
|
||||
break;
|
||||
case TK_VOLATILE:
|
||||
AppendGListData(&pplist, "volatile", 8);
|
||||
break;
|
||||
case TK_PASCAL:
|
||||
AppendGListData(&pplist, "pascal", 6);
|
||||
break;
|
||||
case TK_UU_FAR:
|
||||
AppendGListData(&pplist, "__far", 5);
|
||||
break;
|
||||
case TK_ONEWAY:
|
||||
AppendGListData(&pplist, "oneway", 6);
|
||||
break;
|
||||
case TK_IN:
|
||||
AppendGListData(&pplist, "in", 2);
|
||||
break;
|
||||
case TK_OUT:
|
||||
AppendGListData(&pplist, "out", 3);
|
||||
break;
|
||||
case TK_INOUT:
|
||||
AppendGListData(&pplist, "inout", 5);
|
||||
break;
|
||||
case TK_BYCOPY:
|
||||
AppendGListData(&pplist, "bycopy", 6);
|
||||
break;
|
||||
case TK_BYREF:
|
||||
AppendGListData(&pplist, "byref", 5);
|
||||
break;
|
||||
case TK_ASM:
|
||||
AppendGListData(&pplist, "asm", 3);
|
||||
endToken = 0;
|
||||
startToken = 0;
|
||||
AppendGListByte(&pplist, ' ');
|
||||
token = lex();
|
||||
if (token == TK_VOLATILE || (token == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) {
|
||||
AppendGListData(&pplist, "volatile", 8);
|
||||
token = lex();
|
||||
}
|
||||
if (token) {
|
||||
if (token < ' ' || token > 255)
|
||||
continue;
|
||||
AppendGListByte(&pplist, token);
|
||||
|
||||
if (token == '(') {
|
||||
startToken = '(';
|
||||
endToken = ')';
|
||||
} else if (token == '{') {
|
||||
startToken = '{';
|
||||
endToken = '}';
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
cprep_nostring = 1;
|
||||
in_assembler = 1;
|
||||
depth = 1;
|
||||
save_asmpoundcomment = copts.asmpoundcomment;
|
||||
save_cplusplus = copts.cplusplus;
|
||||
|
||||
token = lex();
|
||||
if (token == '"') {
|
||||
AppendGListByte(&pplist, token);
|
||||
copts.cplusplus = 0;
|
||||
copts.asmpoundcomment = 1;
|
||||
break;
|
||||
} else if (token == 0) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case TK_CASE:
|
||||
AppendGListData(&pplist, "case", 4);
|
||||
break;
|
||||
case TK_DEFAULT:
|
||||
AppendGListData(&pplist, "default", 7);
|
||||
break;
|
||||
case TK_IF:
|
||||
AppendGListData(&pplist, "if", 2);
|
||||
break;
|
||||
case TK_ELSE:
|
||||
AppendGListData(&pplist, "else", 4);
|
||||
break;
|
||||
case TK_SWITCH:
|
||||
AppendGListData(&pplist, "switch", 6);
|
||||
break;
|
||||
case TK_WHILE:
|
||||
AppendGListData(&pplist, "while", 5);
|
||||
break;
|
||||
case TK_DO:
|
||||
AppendGListData(&pplist, "do", 2);
|
||||
break;
|
||||
case TK_FOR:
|
||||
AppendGListData(&pplist, "for", 3);
|
||||
break;
|
||||
case TK_GOTO:
|
||||
AppendGListData(&pplist, "goto", 4);
|
||||
break;
|
||||
case TK_CONTINUE:
|
||||
AppendGListData(&pplist, "continue", 8);
|
||||
break;
|
||||
case TK_BREAK:
|
||||
AppendGListData(&pplist, "break", 5);
|
||||
break;
|
||||
case TK_RETURN:
|
||||
AppendGListData(&pplist, "return", 6);
|
||||
break;
|
||||
case TK_SIZEOF:
|
||||
AppendGListData(&pplist, "sizeof", 6);
|
||||
break;
|
||||
case TK_CATCH:
|
||||
AppendGListData(&pplist, "catch", 5);
|
||||
break;
|
||||
case TK_DELETE:
|
||||
AppendGListData(&pplist, "delete", 6);
|
||||
break;
|
||||
case TK_FRIEND:
|
||||
AppendGListData(&pplist, "friend", 6);
|
||||
break;
|
||||
case TK_NEW:
|
||||
AppendGListData(&pplist, "new", 3);
|
||||
break;
|
||||
case TK_OPERATOR:
|
||||
AppendGListData(&pplist, "operator", 8);
|
||||
break;
|
||||
case TK_PRIVATE:
|
||||
AppendGListData(&pplist, "private", 7);
|
||||
break;
|
||||
case TK_PROTECTED:
|
||||
AppendGListData(&pplist, "protected", 9);
|
||||
break;
|
||||
case TK_PUBLIC:
|
||||
AppendGListData(&pplist, "public", 6);
|
||||
break;
|
||||
case TK_TEMPLATE:
|
||||
AppendGListData(&pplist, "template", 8);
|
||||
break;
|
||||
case TK_THIS:
|
||||
AppendGListData(&pplist, "this", 4);
|
||||
break;
|
||||
case TK_THROW:
|
||||
AppendGListData(&pplist, "throw", 5);
|
||||
break;
|
||||
case TK_TRY:
|
||||
AppendGListData(&pplist, "try", 3);
|
||||
break;
|
||||
case TK_VIRTUAL:
|
||||
AppendGListData(&pplist, "virtual", 7);
|
||||
break;
|
||||
case TK_INHERITED:
|
||||
AppendGListData(&pplist, "inherited", 9);
|
||||
break;
|
||||
case TK_CONST_CAST:
|
||||
AppendGListData(&pplist, "const_cast", 10);
|
||||
break;
|
||||
case TK_DYNAMIC_CAST:
|
||||
AppendGListData(&pplist, "dynamic_cast", 12);
|
||||
break;
|
||||
case TK_EXPLICIT:
|
||||
AppendGListData(&pplist, "explicit", 8);
|
||||
break;
|
||||
case TK_MUTABLE:
|
||||
AppendGListData(&pplist, "mutable", 7);
|
||||
break;
|
||||
case TK_NAMESPACE:
|
||||
AppendGListData(&pplist, "namespace", 9);
|
||||
break;
|
||||
case TK_REINTERPRET_CAST:
|
||||
AppendGListData(&pplist, "reinterpret_cast", 16);
|
||||
break;
|
||||
case TK_STATIC_CAST:
|
||||
AppendGListData(&pplist, "static_cast", 11);
|
||||
break;
|
||||
case TK_USING:
|
||||
AppendGListData(&pplist, "using", 5);
|
||||
break;
|
||||
case TK_WCHAR_T:
|
||||
AppendGListData(&pplist, "wchar_t", 7);
|
||||
break;
|
||||
case TK_TYPENAME:
|
||||
AppendGListData(&pplist, "typename", 8);
|
||||
break;
|
||||
case TK_TRUE:
|
||||
AppendGListData(&pplist, "true", 4);
|
||||
break;
|
||||
case TK_FALSE:
|
||||
AppendGListData(&pplist, "false", 5);
|
||||
break;
|
||||
case TK_TYPEID:
|
||||
AppendGListData(&pplist, "typeid", 6);
|
||||
break;
|
||||
case TK_EXPORT:
|
||||
AppendGListData(&pplist, "export", 6);
|
||||
break;
|
||||
case TK_UU_STDCALL:
|
||||
AppendGListData(&pplist, "__stdcall", 9);
|
||||
break;
|
||||
case TK_UU_CDECL:
|
||||
AppendGListData(&pplist, "__cdecl", 7);
|
||||
break;
|
||||
case TK_UU_FASTCALL:
|
||||
AppendGListData(&pplist, "__fastcall", 10);
|
||||
break;
|
||||
case TK_UU_DECLSPEC:
|
||||
AppendGListData(&pplist, "__declspec", 10);
|
||||
break;
|
||||
case TK_MULT_ASSIGN:
|
||||
AppendGListData(&pplist, "*=", 2);
|
||||
break;
|
||||
case TK_DIV_ASSIGN:
|
||||
AppendGListData(&pplist, "/=", 2);
|
||||
break;
|
||||
case TK_MOD_ASSIGN:
|
||||
AppendGListData(&pplist, "%=", 2);
|
||||
break;
|
||||
case TK_ADD_ASSIGN:
|
||||
AppendGListData(&pplist, "+=", 2);
|
||||
break;
|
||||
case TK_SUB_ASSIGN:
|
||||
AppendGListData(&pplist, "-=", 2);
|
||||
break;
|
||||
case TK_SHL_ASSIGN:
|
||||
AppendGListData(&pplist, "<<=", 3);
|
||||
break;
|
||||
case TK_SHR_ASSIGN:
|
||||
AppendGListData(&pplist, ">>=", 3);
|
||||
break;
|
||||
case TK_AND_ASSIGN:
|
||||
AppendGListData(&pplist, "&=", 2);
|
||||
break;
|
||||
case TK_XOR_ASSIGN:
|
||||
AppendGListData(&pplist, "^=", 2);
|
||||
break;
|
||||
case TK_OR_ASSIGN:
|
||||
AppendGListData(&pplist, "|=", 2);
|
||||
break;
|
||||
case TK_LOGICAL_OR:
|
||||
AppendGListData(&pplist, "||", 2);
|
||||
break;
|
||||
case TK_LOGICAL_AND:
|
||||
AppendGListData(&pplist, "&&", 2);
|
||||
break;
|
||||
case TK_LOGICAL_EQ:
|
||||
AppendGListData(&pplist, "==", 2);
|
||||
break;
|
||||
case TK_LOGICAL_NE:
|
||||
AppendGListData(&pplist, "!=", 2);
|
||||
break;
|
||||
case TK_LESS_EQUAL:
|
||||
AppendGListData(&pplist, "<=", 2);
|
||||
break;
|
||||
case TK_GREATER_EQUAL:
|
||||
AppendGListData(&pplist, ">=", 2);
|
||||
break;
|
||||
case TK_SHL:
|
||||
AppendGListData(&pplist, "<<", 2);
|
||||
break;
|
||||
case TK_SHR:
|
||||
AppendGListData(&pplist, ">>", 2);
|
||||
break;
|
||||
case TK_INCREMENT:
|
||||
AppendGListData(&pplist, "++", 2);
|
||||
break;
|
||||
case TK_DECREMENT:
|
||||
AppendGListData(&pplist, "--", 2);
|
||||
break;
|
||||
case TK_ARROW:
|
||||
AppendGListData(&pplist, "->", 2);
|
||||
break;
|
||||
case TK_ELLIPSIS:
|
||||
AppendGListData(&pplist, "...", 3);
|
||||
break;
|
||||
case TK_DOT_STAR:
|
||||
AppendGListData(&pplist, ".*", 2);
|
||||
break;
|
||||
case TK_ARROW_STAR:
|
||||
AppendGListData(&pplist, "->*", 3);
|
||||
break;
|
||||
case TK_COLON_COLON:
|
||||
AppendGListData(&pplist, "::", 2);
|
||||
break;
|
||||
case TK_AT_INTERFACE:
|
||||
AppendGListData(&pplist, "@interface", 10);
|
||||
break;
|
||||
case TK_AT_IMPLEMENTATION:
|
||||
AppendGListData(&pplist, "@implementation", 15);
|
||||
break;
|
||||
case TK_AT_PROTOCOL:
|
||||
AppendGListData(&pplist, "@protocol", 9);
|
||||
break;
|
||||
case TK_AT_END:
|
||||
AppendGListData(&pplist, "@end", 4);
|
||||
break;
|
||||
case TK_AT_PRIVATE:
|
||||
AppendGListData(&pplist, "@private", 8);
|
||||
break;
|
||||
case TK_AT_PROTECTED:
|
||||
AppendGListData(&pplist, "@protected", 10);
|
||||
break;
|
||||
case TK_AT_PUBLIC:
|
||||
AppendGListData(&pplist, "@public", 7);
|
||||
break;
|
||||
case TK_AT_CLASS:
|
||||
AppendGListData(&pplist, "@class", 6);
|
||||
break;
|
||||
case TK_AT_SELECTOR:
|
||||
AppendGListData(&pplist, "@selector", 9);
|
||||
break;
|
||||
case TK_AT_ENCODE:
|
||||
AppendGListData(&pplist, "@encode", 7);
|
||||
break;
|
||||
case TK_AT_DEFS:
|
||||
AppendGListData(&pplist, "@defs", 5);
|
||||
break;
|
||||
case TK_SELF:
|
||||
AppendGListData(&pplist, "self", 4);
|
||||
break;
|
||||
case TK_SUPER:
|
||||
AppendGListData(&pplist, "super", 5);
|
||||
break;
|
||||
case TK_BOOL:
|
||||
if (!copts.cplusplus && copts.c9x)
|
||||
AppendGListData(&pplist, "_Bool", 5);
|
||||
else
|
||||
AppendGListData(&pplist, "bool", 4);
|
||||
break;
|
||||
case TK_RESTRICT:
|
||||
if (copts.c9x)
|
||||
AppendGListData(&pplist, "restrict", 8);
|
||||
else
|
||||
AppendGListData(&pplist, "__restrict", 10);
|
||||
break;
|
||||
case TK_UU_VECTOR:
|
||||
AppendGListData(&pplist, "__vector", 8);
|
||||
break;
|
||||
case TK_UU_TYPEOF_UU:
|
||||
AppendGListData(&pplist, "__typeof__", 10);
|
||||
break;
|
||||
case TK_UU_ATTRIBUTE_UU:
|
||||
AppendGListData(&pplist, "__attribute__", 13);
|
||||
break;
|
||||
case TK_UU_ALIGNOF_UU:
|
||||
AppendGListData(&pplist, "__alignof__", 11);
|
||||
break;
|
||||
case TK_UU_UUIDOF:
|
||||
AppendGListData(&pplist, "__uuidof", 8);
|
||||
break;
|
||||
case TK_U_COMPLEX:
|
||||
AppendGListData(&pplist, "_Complex", 8);
|
||||
break;
|
||||
case TK_U_IMAGINARY:
|
||||
AppendGListData(&pplist, "_Imaginary", 10);
|
||||
break;
|
||||
|
||||
case TK_STRING:
|
||||
if (ispascalstring) {
|
||||
AppendGListData(&pplist, "\"\\p", 3);
|
||||
CPrep_DumpString((UInt8 *) tkstring + 1, tksize - 1);
|
||||
} else {
|
||||
AppendGListByte(&pplist, '"');
|
||||
CPrep_DumpString((UInt8 *) tkstring, tksize - 1);
|
||||
}
|
||||
AppendGListByte(&pplist, '"');
|
||||
break;
|
||||
|
||||
case TK_STRING_WIDE:
|
||||
AppendGListData(&pplist, "L\"", 2);
|
||||
CPrep_DumpWString((UInt16 *) tkstring, (tksize / stwchar.size) - 1);
|
||||
AppendGListByte(&pplist, '"');
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token >= 32 && token <= 255)
|
||||
AppendGListByte(&pplist, token);
|
||||
else
|
||||
CError_FATAL(563);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
CPrep_TokenStreamFlush();
|
||||
nlflag = 0;
|
||||
spaceskip = 0;
|
||||
} while ((token = lex()));
|
||||
}
|
||||
|
||||
AppendGListByte(&pplist, 0);
|
||||
COS_ResizeHandle(pplist.data, pplist.size);
|
||||
}
|
||||
940
compiler_and_linker/FrontEnd/C/CRTTI.c
Normal file
940
compiler_and_linker/FrontEnd/C/CRTTI.c
Normal file
@@ -0,0 +1,940 @@
|
||||
#include "compiler/CRTTI.h"
|
||||
#include "compiler/CClass.h"
|
||||
#include "compiler/CDecl.h"
|
||||
#include "compiler/CError.h"
|
||||
#include "compiler/CExpr.h"
|
||||
#include "compiler/CInit.h"
|
||||
#include "compiler/CInt64.h"
|
||||
#include "compiler/CMachine.h"
|
||||
#include "compiler/CMangler.h"
|
||||
#include "compiler/CParser.h"
|
||||
#include "compiler/CScope.h"
|
||||
#include "compiler/CompilerTools.h"
|
||||
#include "compiler/objects.h"
|
||||
#include "compiler/scopes.h"
|
||||
#include "compiler/types.h"
|
||||
#include "compiler/CPrepTokenizer.h"
|
||||
#include "compiler/CPrep.h"
|
||||
|
||||
typedef struct Offset {
|
||||
struct Offset *next;
|
||||
SInt32 offset;
|
||||
} Offset;
|
||||
|
||||
static Offset *crtti_offsets;
|
||||
static OLinkList *crtti_olinks;
|
||||
|
||||
// forward decls
|
||||
static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual);
|
||||
|
||||
typedef struct RTTISubClassList {
|
||||
struct RTTISubClassList *next;
|
||||
TypeClass *base;
|
||||
SInt32 voffset;
|
||||
} RTTISubClassList;
|
||||
|
||||
typedef struct RTTIBaseList {
|
||||
struct RTTIBaseList *next;
|
||||
TypeClass *base;
|
||||
RTTISubClassList *subclasses;
|
||||
SInt32 voffset;
|
||||
short numsubclasses;
|
||||
Boolean x12;
|
||||
Boolean x13;
|
||||
} RTTIBaseList;
|
||||
|
||||
static RTTIBaseList *CRTTI_CreateBaseList(TypeClass *tclass, TypeClass *tclassbase, RTTIBaseList *list, SInt32 voffset, Boolean flag) {
|
||||
RTTIBaseList *scan;
|
||||
ClassList *base;
|
||||
Boolean flag27;
|
||||
SInt32 newvoffset;
|
||||
|
||||
if (tclass != tclassbase) {
|
||||
flag27 = 0;
|
||||
|
||||
for (scan = list; scan; scan = scan->next) {
|
||||
if (scan->base == tclassbase) {
|
||||
if (scan->voffset == voffset) {
|
||||
if (!flag)
|
||||
scan->x12 = 0;
|
||||
flag27 = 0;
|
||||
} else {
|
||||
scan->x13 = 1;
|
||||
flag27 = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scan || flag27) {
|
||||
scan = lalloc(sizeof(RTTIBaseList));
|
||||
memclrw(scan, sizeof(RTTIBaseList));
|
||||
|
||||
scan->next = list;
|
||||
list = scan;
|
||||
scan->base = tclassbase;
|
||||
scan->voffset = voffset;
|
||||
scan->x12 = flag;
|
||||
scan->x13 = flag27;
|
||||
}
|
||||
}
|
||||
|
||||
for (base = tclassbase->bases; base; base = base->next) {
|
||||
if (base->is_virtual)
|
||||
newvoffset = CClass_VirtualBaseOffset(tclass, base->base);
|
||||
else
|
||||
newvoffset = voffset + base->offset;
|
||||
|
||||
list = CRTTI_CreateBaseList(tclass, base->base, list, newvoffset, flag || base->access == ACCESSPRIVATE);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void CRTTI_CreateSubClassList(TypeClass *tclass, RTTIBaseList *baselist, TypeClass *tclassbase, SInt32 voffset, Boolean flag) {
|
||||
ClassList *base;
|
||||
RTTISubClassList *scan;
|
||||
SInt32 newvoffset;
|
||||
|
||||
if (baselist->base != tclassbase) {
|
||||
for (scan = baselist->subclasses; scan; scan = scan->next) {
|
||||
if (scan->base == tclassbase && scan->voffset == voffset)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!scan) {
|
||||
scan = lalloc(sizeof(RTTISubClassList));
|
||||
scan->next = baselist->subclasses;
|
||||
baselist->subclasses = scan;
|
||||
|
||||
scan->base = tclassbase;
|
||||
scan->voffset = voffset;
|
||||
baselist->numsubclasses++;
|
||||
}
|
||||
}
|
||||
|
||||
for (base = tclassbase->bases; base; base = base->next) {
|
||||
if (base->access == ACCESSPUBLIC) {
|
||||
if (base->is_virtual) {
|
||||
if (!flag)
|
||||
continue;
|
||||
newvoffset = CClass_VirtualBaseOffset(tclass, base->base);
|
||||
} else {
|
||||
newvoffset = voffset + base->offset;
|
||||
}
|
||||
|
||||
CRTTI_CreateSubClassList(tclass, baselist, base->base, newvoffset, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object *CRTTI_CreateBaseListObject(TypeClass *tclass) {
|
||||
RTTIBaseList *baselist;
|
||||
OLinkList *refs;
|
||||
Object *object;
|
||||
SInt32 *buf;
|
||||
SInt32 size;
|
||||
short count1;
|
||||
short count2;
|
||||
short total;
|
||||
OLinkList *ref;
|
||||
RTTIBaseList *scan;
|
||||
RTTISubClassList *subclass;
|
||||
SInt32 *work;
|
||||
SInt32 *work2;
|
||||
|
||||
baselist = CRTTI_CreateBaseList(tclass, tclass, NULL, 0, 0);
|
||||
if (!baselist)
|
||||
return NULL;
|
||||
|
||||
count1 = 0;
|
||||
count2 = 0;
|
||||
total = 0;
|
||||
|
||||
for (scan = baselist; scan; scan = scan->next) {
|
||||
if (scan->x13 || scan->x12) {
|
||||
CRTTI_CreateSubClassList(tclass, scan, scan->base, scan->voffset, scan->x13 == 0);
|
||||
if (scan->numsubclasses) {
|
||||
total += scan->numsubclasses;
|
||||
count2++;
|
||||
}
|
||||
} else {
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!count1 && !count2)
|
||||
return NULL;
|
||||
|
||||
size = (count1 + total) * 8 + count2 * 12 + 4;
|
||||
buf = lalloc(size);
|
||||
memclrw(buf, size);
|
||||
|
||||
object = CParser_NewCompilerDefDataObject();
|
||||
object->name = CParser_GetUniqueName();
|
||||
object->type = CDecl_NewStructType(size, 4);
|
||||
object->qual = Q_CONST;
|
||||
object->sclass = TK_STATIC;
|
||||
refs = NULL;
|
||||
|
||||
work = buf;
|
||||
|
||||
if (count1) {
|
||||
for (scan = baselist; scan; scan = scan->next) {
|
||||
if (!scan->x12 && !scan->x13) {
|
||||
ref = lalloc(sizeof(OLinkList));
|
||||
ref->next = refs;
|
||||
refs = ref;
|
||||
|
||||
ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0);
|
||||
ref->offset = ((char *) work) - ((char *) buf);
|
||||
ref->somevalue = 0;
|
||||
|
||||
work[1] = CTool_EndianConvertWord32(scan->voffset);
|
||||
work += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count2) {
|
||||
for (scan = baselist; scan; scan = scan->next) {
|
||||
if (scan->numsubclasses) {
|
||||
ref = lalloc(sizeof(OLinkList));
|
||||
ref->next = refs;
|
||||
refs = ref;
|
||||
|
||||
ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0);
|
||||
ref->offset = ((char *) work) - ((char *) buf);
|
||||
ref->somevalue = 0;
|
||||
|
||||
work[1] = CTool_EndianConvertWord32(scan->voffset | 0x80000000);
|
||||
work[2] = CTool_EndianConvertWord32(scan->numsubclasses);
|
||||
work2 = work + 3;
|
||||
|
||||
for (subclass = scan->subclasses; subclass; subclass = subclass->next) {
|
||||
ref = lalloc(sizeof(OLinkList));
|
||||
ref->next = refs;
|
||||
refs = ref;
|
||||
|
||||
ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(subclass->base), 0);
|
||||
ref->offset = ((char *) work2) - ((char *) buf);
|
||||
ref->somevalue = 0;
|
||||
|
||||
work2[1] = CTool_EndianConvertWord32(subclass->voffset);
|
||||
work2 += 2;
|
||||
}
|
||||
|
||||
work = work2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CInit_DeclareData(object, buf, refs, object->type->size);
|
||||
return object;
|
||||
}
|
||||
|
||||
static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual) {
|
||||
Object *baselistobj;
|
||||
Object *nameobj;
|
||||
HashNameNode *rttiname;
|
||||
OLinkList *refs;
|
||||
char *namestr;
|
||||
int namelen;
|
||||
Object *object;
|
||||
NameSpaceObjectList *list;
|
||||
TypePointer tptr_copy;
|
||||
TypeMemberPointer tmemptr_copy;
|
||||
UInt32 data[2];
|
||||
|
||||
switch (type->type) {
|
||||
case TYPEPOINTER:
|
||||
if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) {
|
||||
tptr_copy = *TYPE_POINTER(type);
|
||||
tptr_copy.qual &= ~(Q_CONST | Q_VOLATILE);
|
||||
type = TYPE(&tptr_copy);
|
||||
}
|
||||
break;
|
||||
case TYPEMEMBERPOINTER:
|
||||
if (TYPE_MEMBER_POINTER(type)->qual & (Q_CONST | Q_VOLATILE)) {
|
||||
tmemptr_copy = *TYPE_MEMBER_POINTER(type);
|
||||
tmemptr_copy.qual &= ~(Q_CONST | Q_VOLATILE);
|
||||
type = TYPE(&tmemptr_copy);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qual = 0;
|
||||
}
|
||||
|
||||
if (IS_TYPE_CLASS(type) && type->size == 0) {
|
||||
CDecl_CompleteType(type);
|
||||
if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED))
|
||||
CError_Error(CErrorStr136, type, 0);
|
||||
}
|
||||
|
||||
rttiname = CMangler_RTTIObjectName(type, qual);
|
||||
list = CScope_FindName(cscope_root, rttiname);
|
||||
|
||||
if (!list || (object = OBJECT(list->object))->otype != OT_OBJECT || object->datatype != DDATA) {
|
||||
namestr = CError_GetTypeName(type, qual, 0);
|
||||
namelen = strlen(namestr) + 1;
|
||||
nameobj = CInit_DeclareString(namestr, namelen, 0, 0);
|
||||
|
||||
baselistobj = NULL;
|
||||
if (IS_TYPE_CLASS(type))
|
||||
baselistobj = CRTTI_CreateBaseListObject(TYPE_CLASS(type));
|
||||
|
||||
memclrw(data, sizeof(data));
|
||||
|
||||
object = CParser_NewCompilerDefDataObject();
|
||||
object->name = rttiname;
|
||||
object->type = CDecl_NewStructType(sizeof(data), 4);
|
||||
object->qual = Q_CONST;
|
||||
object->sclass = TK_STATIC;
|
||||
|
||||
refs = lalloc(sizeof(OLinkList));
|
||||
refs->next = NULL;
|
||||
refs->obj = nameobj;
|
||||
refs->offset = 0;
|
||||
refs->somevalue = 0;
|
||||
|
||||
if (baselistobj) {
|
||||
refs->next = lalloc(sizeof(OLinkList));
|
||||
refs->next->next = NULL;
|
||||
refs->next->obj = baselistobj;
|
||||
refs->next->offset = 4;
|
||||
refs->next->somevalue = 0;
|
||||
}
|
||||
|
||||
CScope_AddGlobalObject(object);
|
||||
CInit_DeclareData(object, data, refs, object->type->size);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void CRTTI_ConstructVTableHeader(TypeClass *tclass1, TypeClass *tclass2, Object *typeinfoObj, char *data, SInt32 offset, SInt32 voffset) {
|
||||
ClassList *base;
|
||||
Offset *o;
|
||||
OLinkList *olink;
|
||||
SInt32 tmp;
|
||||
SInt32 newoffset;
|
||||
SInt32 newvoffset;
|
||||
|
||||
if (tclass2->vtable->owner == tclass2) {
|
||||
for (o = crtti_offsets; o; o = o->next) {
|
||||
if (o->offset == voffset)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!o) {
|
||||
o = lalloc(sizeof(Offset));
|
||||
o->next = crtti_offsets;
|
||||
o->offset = voffset;
|
||||
crtti_offsets = o;
|
||||
|
||||
olink = lalloc(sizeof(OLinkList));
|
||||
olink->next = crtti_olinks;
|
||||
olink->obj = typeinfoObj;
|
||||
olink->offset = voffset;
|
||||
olink->somevalue = 0;
|
||||
crtti_olinks = olink;
|
||||
|
||||
*((SInt32 *) (data + voffset + 4)) = CTool_EndianConvertWord32(-offset);
|
||||
} else {
|
||||
tmp = *((SInt32 *) (data + voffset + 4));
|
||||
CError_ASSERT(404, tmp == CTool_EndianConvertWord32(-offset));
|
||||
}
|
||||
}
|
||||
|
||||
for (base = tclass2->bases; base; base = base->next) {
|
||||
if (base->base->vtable) {
|
||||
if (base->is_virtual) {
|
||||
newoffset = CClass_VirtualBaseOffset(tclass1, base->base);
|
||||
newvoffset = CClass_VirtualBaseVTableOffset(tclass1, base->base);
|
||||
} else {
|
||||
newoffset = offset + base->offset;
|
||||
newvoffset = voffset + base->voffset;
|
||||
}
|
||||
|
||||
CRTTI_ConstructVTableHeader(tclass1, base->base, typeinfoObj, data, newoffset, newvoffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OLinkList *CRTTI_ConstructVTableHeaders(TypeClass *tclass, void *data, OLinkList *links) {
|
||||
crtti_offsets = NULL;
|
||||
crtti_olinks = links;
|
||||
|
||||
CRTTI_ConstructVTableHeader(
|
||||
tclass, tclass,
|
||||
CRTTI_ConstructTypeInfoObject(TYPE(tclass), 0),
|
||||
data, 0, 0);
|
||||
|
||||
return crtti_olinks;
|
||||
}
|
||||
|
||||
static Type *CRTTI_FindTypeInfoType(void) {
|
||||
NameSpace *nspace;
|
||||
NameSpaceObjectList *list;
|
||||
Type *type;
|
||||
|
||||
if ((list = CScope_FindName(cscope_root, GetHashNameNodeExport("std"))) && list->object->otype == OT_NAMESPACE)
|
||||
nspace = OBJ_NAMESPACE(list->object)->nspace;
|
||||
else
|
||||
nspace = cscope_root;
|
||||
|
||||
type = CScope_GetLocalTagType(nspace, GetHashNameNodeExport("type_info"));
|
||||
if (type && IS_TYPE_CLASS(type) && type->size)
|
||||
return type;
|
||||
|
||||
CError_Error(CErrorStr140, "::std::type_info");
|
||||
return TYPE(&stchar);
|
||||
}
|
||||
|
||||
ENode *CRTTI_ParseTypeID(void) {
|
||||
ENode *expr;
|
||||
Type *type;
|
||||
Type *typeinfoType;
|
||||
UInt32 qual;
|
||||
|
||||
if (!copts.RTTI)
|
||||
CError_Warning(CErrorStr257);
|
||||
|
||||
typeinfoType = CRTTI_FindTypeInfoType();
|
||||
|
||||
if (lex() != '(') {
|
||||
CError_Error(CErrorStr114);
|
||||
return nullnode();
|
||||
}
|
||||
|
||||
tk = lex();
|
||||
if ((type = CParser_ParseTypeID(&qual, NULL))) {
|
||||
if (tk != ')')
|
||||
CError_ErrorSkip(CErrorStr115);
|
||||
else
|
||||
tk = lex();
|
||||
|
||||
if (IS_TYPE_REFERENCE(type))
|
||||
type = TPTR_TARGET(type);
|
||||
} else {
|
||||
expr = s_expression();
|
||||
|
||||
if (tk != ')')
|
||||
CError_ErrorSkip(CErrorStr115);
|
||||
else
|
||||
tk = lex();
|
||||
|
||||
type = expr->rtype;
|
||||
qual = ENODE_QUALS(expr);
|
||||
|
||||
if (IS_TYPE_REFERENCE(type))
|
||||
type = TPTR_TARGET(type);
|
||||
|
||||
if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->vtable) {
|
||||
expr = funccallexpr(
|
||||
Rgtid_func,
|
||||
getnodeaddress(expr, 0),
|
||||
intconstnode(TYPE(&stsignedlong), TYPE_CLASS(type)->vtable->offset),
|
||||
NULL,
|
||||
NULL);
|
||||
expr->rtype = CDecl_NewPointerType(typeinfoType);
|
||||
|
||||
expr = makemonadicnode(expr, EINDIRECT);
|
||||
expr->rtype = typeinfoType;
|
||||
expr->flags = ENODE_FLAG_CONST;
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
expr = create_objectrefnode(CRTTI_ConstructTypeInfoObject(type, qual));
|
||||
expr = makemonadicnode(expr, EINDIRECT);
|
||||
expr->rtype = typeinfoType;
|
||||
expr->flags = ENODE_FLAG_CONST;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static void CRTTI_ConstCastQualCheck(UInt32 qual1, UInt32 qual2) {
|
||||
if (
|
||||
((qual1 & Q_CONST) && !(qual2 & Q_CONST)) ||
|
||||
((qual1 & Q_VOLATILE) && !(qual2 & Q_VOLATILE))
|
||||
)
|
||||
CError_Error(CErrorStr258);
|
||||
}
|
||||
|
||||
static void CRTTI_ConstCastCheck(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2) {
|
||||
Boolean flag = 1;
|
||||
if (IS_TYPE_REFERENCE(type2)) {
|
||||
type2 = TPTR_TARGET(type2);
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (type1->type != type2->type)
|
||||
break;
|
||||
|
||||
switch (type1->type) {
|
||||
case TYPEPOINTER:
|
||||
if (!flag)
|
||||
CRTTI_ConstCastQualCheck(TPTR_QUAL(type1), TPTR_QUAL(type2));
|
||||
type1 = TPTR_TARGET(type1);
|
||||
type2 = TPTR_TARGET(type2);
|
||||
flag = 0;
|
||||
continue;
|
||||
|
||||
case TYPEMEMBERPOINTER:
|
||||
if (!flag)
|
||||
CRTTI_ConstCastQualCheck(TYPE_MEMBER_POINTER(type1)->qual, TYPE_MEMBER_POINTER(type2)->qual);
|
||||
type1 = TYPE_MEMBER_POINTER(type1)->ty1;
|
||||
type2 = TYPE_MEMBER_POINTER(type2)->ty1;
|
||||
flag = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flag && !IS_TYPE_FUNC(type1) && !IS_TYPE_FUNC(type2))
|
||||
CRTTI_ConstCastQualCheck(CParser_GetCVTypeQualifiers(type1, qual1), CParser_GetCVTypeQualifiers(type2, qual2));
|
||||
}
|
||||
|
||||
static ENode *CRTTI_ParseCast(DeclInfo *di) {
|
||||
ENode *expr;
|
||||
|
||||
if (lex() != '<') {
|
||||
CError_Error(CErrorStr230);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tk = lex();
|
||||
|
||||
memclrw(di, sizeof(DeclInfo));
|
||||
CParser_GetDeclSpecs(di, 0);
|
||||
scandeclarator(di);
|
||||
|
||||
if (di->name)
|
||||
CError_Error(CErrorStr164);
|
||||
|
||||
if (tk != '>') {
|
||||
CError_Error(CErrorStr231);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lex() != '(') {
|
||||
CError_Error(CErrorStr114);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tk = lex();
|
||||
expr = s_expression();
|
||||
if (!IS_TYPE_REFERENCE(di->thetype))
|
||||
expr = pointer_generation(expr);
|
||||
|
||||
if (tk != ')') {
|
||||
CError_Error(CErrorStr115);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tk = lex();
|
||||
return expr;
|
||||
}
|
||||
|
||||
static void CRTTI_IncompleteCheck(Type *type) {
|
||||
if (IS_TYPE_POINTER_ONLY(type))
|
||||
type = TPTR_TARGET(type);
|
||||
|
||||
if (IS_TYPE_CLASS(type) && type->size == 0) {
|
||||
CDecl_CompleteType(type);
|
||||
if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED))
|
||||
CError_Error(CErrorStr136, type, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean CRTTI_IsSameType(Type *a, Type *b) {
|
||||
while (1) {
|
||||
if (a->type != b->type)
|
||||
return 0;
|
||||
|
||||
switch (a->type) {
|
||||
case TYPEVOID:
|
||||
return 1;
|
||||
case TYPEINT:
|
||||
case TYPEFLOAT:
|
||||
case TYPEENUM:
|
||||
case TYPESTRUCT:
|
||||
return a == b;
|
||||
case TYPEPOINTER:
|
||||
a = TPTR_TARGET(a);
|
||||
b = TPTR_TARGET(b);
|
||||
continue;
|
||||
default:
|
||||
return is_typesame(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ENode *CRTTI_UniversalCast(ENode *expr, Type *type, UInt32 qual, UInt8 mode) {
|
||||
// type/qual are the target type
|
||||
Boolean isSimpleCast;
|
||||
Boolean needsTypcon;
|
||||
Boolean failed;
|
||||
|
||||
if (ENODE_IS(expr, EOBJLIST))
|
||||
return CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1);
|
||||
|
||||
isSimpleCast = needsTypcon = failed = 0;
|
||||
|
||||
switch (type->type) {
|
||||
case TYPEINT:
|
||||
case TYPEENUM:
|
||||
if (mode == 2 && IS_TYPE_POINTER_ONLY(expr->rtype) && type != TYPE(&stbool))
|
||||
failed = 1;
|
||||
break;
|
||||
|
||||
case TYPEPOINTER:
|
||||
if (TPTR_QUAL(type) & Q_REFERENCE) {
|
||||
if (
|
||||
!CRTTI_IsSameType(TPTR_TARGET(type), expr->rtype) &&
|
||||
mode == 2 &&
|
||||
!(
|
||||
IS_TYPE_CLASS(TPTR_TARGET(type)) &&
|
||||
IS_TYPE_CLASS(expr->rtype) &&
|
||||
(
|
||||
CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(expr->rtype), NULL, 0, 1) ||
|
||||
CClass_IsBaseClass(TYPE_CLASS(expr->rtype), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
failed = 1;
|
||||
}
|
||||
} else if (IS_TYPE_POINTER_ONLY(expr->rtype)) {
|
||||
if (
|
||||
mode == 3 ||
|
||||
CRTTI_IsSameType(type, expr->rtype) ||
|
||||
IS_TYPE_VOID(TPTR_TARGET(type)) ||
|
||||
IS_TYPE_VOID(TPTR_TARGET(expr->rtype))
|
||||
)
|
||||
{
|
||||
isSimpleCast = needsTypcon = 1;
|
||||
}
|
||||
else if (
|
||||
mode == 2 &&
|
||||
!(
|
||||
IS_TYPE_CLASS(TPTR_TARGET(type)) &&
|
||||
IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) &&
|
||||
(
|
||||
CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(TPTR_TARGET(expr->rtype)), NULL, 0, 1) ||
|
||||
CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
failed = 1;
|
||||
}
|
||||
} else {
|
||||
if (IS_TYPE_ENUM(expr->rtype))
|
||||
expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
|
||||
|
||||
if (IS_TYPE_INT(expr->rtype)) {
|
||||
if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) {
|
||||
isSimpleCast = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode != 2)
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_TYPE_CLASS(expr->rtype)) {
|
||||
if (mode == 2)
|
||||
break;
|
||||
}
|
||||
|
||||
failed = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual);
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (isSimpleCast) {
|
||||
if (needsTypcon && ENODE_IS(expr, EINDIRECT) && (copts.pointercast_lvalue || !copts.ANSIstrict))
|
||||
expr = makemonadicnode(expr, ETYPCON);
|
||||
|
||||
expr->rtype = type;
|
||||
expr->flags = qual & ENODE_FLAG_QUALS;
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (copts.old_argmatch)
|
||||
return do_typecast(expr, type, qual);
|
||||
|
||||
return CExpr_Convert(expr, type, qual, 1, 1);
|
||||
}
|
||||
|
||||
ENode *CRTTI_Parse_dynamic_cast(void) {
|
||||
Boolean isRef;
|
||||
ENode *expr;
|
||||
TypeClass *srcclass;
|
||||
TypeClass *destclass;
|
||||
ENode *typeinfo;
|
||||
DeclInfo di;
|
||||
|
||||
expr = CRTTI_ParseCast(&di);
|
||||
if (!expr)
|
||||
return nullnode();
|
||||
|
||||
if (!copts.RTTI)
|
||||
CError_Warning(CErrorStr257);
|
||||
|
||||
CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
|
||||
if (!IS_TYPE_POINTER_ONLY(di.thetype)) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
|
||||
isRef = (TPTR_QUAL(di.thetype) & Q_REFERENCE) != 0;
|
||||
|
||||
if (IS_TYPE_CLASS(TPTR_TARGET(di.thetype))) {
|
||||
destclass = TYPE_CLASS(TPTR_TARGET(di.thetype));
|
||||
CDecl_CompleteType(TYPE(destclass));
|
||||
if (!(destclass->flags & CLASS_COMPLETED)) {
|
||||
CError_Error(CErrorStr136, destclass, 0);
|
||||
return expr;
|
||||
}
|
||||
} else if (!IS_TYPE_VOID(TPTR_TARGET(di.thetype))) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
} else {
|
||||
destclass = NULL;
|
||||
}
|
||||
|
||||
if (isRef) {
|
||||
if (!IS_TYPE_CLASS(expr->rtype)) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
|
||||
srcclass = TYPE_CLASS(expr->rtype);
|
||||
if (destclass) {
|
||||
if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1))
|
||||
return do_typecast(expr, di.thetype, di.qual);
|
||||
}
|
||||
|
||||
expr = getnodeaddress(expr, 1);
|
||||
} else {
|
||||
if (!IS_TYPE_POINTER_ONLY(expr->rtype) || !IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
|
||||
srcclass = TYPE_CLASS(TPTR_TARGET(expr->rtype));
|
||||
if (destclass) {
|
||||
if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1))
|
||||
return do_typecast(expr, di.thetype, di.qual);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(srcclass->flags & CLASS_COMPLETED)) {
|
||||
CError_Error(CErrorStr136, srcclass, 0);
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (!srcclass->vtable) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (srcclass->sominfo) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (destclass) {
|
||||
typeinfo = create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(destclass), 0));
|
||||
if (destclass->sominfo) {
|
||||
CError_Error(CErrorStr164);
|
||||
return expr;
|
||||
}
|
||||
} else {
|
||||
typeinfo = nullnode();
|
||||
}
|
||||
|
||||
expr = CExpr_FuncCallSix(
|
||||
Rdync_func,
|
||||
expr,
|
||||
intconstnode(TYPE(&stsignedlong), srcclass->vtable->offset),
|
||||
typeinfo,
|
||||
create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(srcclass), 0)),
|
||||
intconstnode(TYPE(&stsignedshort), isRef),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (isRef) {
|
||||
expr->rtype = CDecl_NewPointerType(TYPE(destclass));
|
||||
expr = makemonadicnode(expr, EINDIRECT);
|
||||
expr->rtype = TYPE(destclass);
|
||||
} else {
|
||||
expr->rtype = di.thetype;
|
||||
}
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
return expr;
|
||||
}
|
||||
|
||||
ENode *CRTTI_Parse_static_cast(void) {
|
||||
ENode *expr;
|
||||
DeclInfo di;
|
||||
|
||||
expr = CRTTI_ParseCast(&di);
|
||||
if (!expr)
|
||||
return nullnode();
|
||||
|
||||
CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
|
||||
|
||||
if (IS_TYPE_REFERENCE(di.thetype)) {
|
||||
if (IS_TYPE_CLASS(expr->rtype) && CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) {
|
||||
expr = CExpr_Convert(expr, di.thetype, di.qual, 0, 1);
|
||||
CError_ASSERT(959, IS_TYPE_POINTER_ONLY(expr->rtype));
|
||||
|
||||
expr = makemonadicnode(expr, EINDIRECT);
|
||||
expr->rtype = TPTR_TARGET(di.thetype);
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
return expr;
|
||||
}
|
||||
} else {
|
||||
if (CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual))
|
||||
return CExpr_Convert(expr, di.thetype, di.qual, 1, 1);
|
||||
}
|
||||
|
||||
if (!IS_TYPE_VOID(di.thetype) && !(IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_VOID(TPTR_TARGET(expr->rtype)))) {
|
||||
CRTTI_IncompleteCheck(di.thetype);
|
||||
CRTTI_IncompleteCheck(expr->rtype);
|
||||
}
|
||||
|
||||
return CRTTI_UniversalCast(expr, di.thetype, di.qual, 2);
|
||||
}
|
||||
|
||||
ENode *CRTTI_Parse_reinterpret_cast(void) {
|
||||
ENode *expr;
|
||||
Type *origtype;
|
||||
ENode *lvalue;
|
||||
DeclInfo di;
|
||||
|
||||
expr = CRTTI_ParseCast(&di);
|
||||
if (!expr)
|
||||
return nullnode();
|
||||
|
||||
CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual);
|
||||
|
||||
if (IS_TYPE_REFERENCE(di.thetype)) {
|
||||
lvalue = CExpr_LValue(expr, 0, 1);
|
||||
if (!ENODE_IS(lvalue, EINDIRECT))
|
||||
return lvalue;
|
||||
|
||||
lvalue->data.monadic->rtype = CDecl_NewPointerType(lvalue->rtype);
|
||||
expr = lvalue->data.monadic;
|
||||
origtype = di.thetype;
|
||||
di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype));
|
||||
} else {
|
||||
origtype = NULL;
|
||||
}
|
||||
|
||||
switch (di.thetype->type) {
|
||||
case TYPEINT:
|
||||
switch (expr->rtype->type) {
|
||||
case TYPEMEMBERPOINTER:
|
||||
case TYPEPOINTER:
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
break;
|
||||
default:
|
||||
CError_Error(CErrorStr164);
|
||||
}
|
||||
break;
|
||||
case TYPEPOINTER:
|
||||
switch (expr->rtype->type) {
|
||||
case TYPEINT:
|
||||
case TYPEENUM:
|
||||
if (origtype)
|
||||
di.thetype = origtype;
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
break;
|
||||
case TYPEPOINTER:
|
||||
expr = makemonadicnode(expr, ETYPCON);
|
||||
expr->rtype = di.thetype;
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
break;
|
||||
default:
|
||||
CError_Error(CErrorStr164);
|
||||
}
|
||||
break;
|
||||
case TYPEMEMBERPOINTER:
|
||||
if (IS_TYPE_MEMBERPOINTER(expr->rtype)) {
|
||||
if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(di.thetype)->ty1)) {
|
||||
if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) {
|
||||
expr->rtype = di.thetype;
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) {
|
||||
expr->rtype = di.thetype;
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
break;
|
||||
default:
|
||||
CError_Error(CErrorStr164);
|
||||
}
|
||||
|
||||
if (origtype && IS_TYPE_POINTER_ONLY(expr->rtype)) {
|
||||
expr = makemonadicnode(expr, EINDIRECT);
|
||||
expr->rtype = TPTR_TARGET(di.thetype);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
ENode *CRTTI_Parse_const_cast(void) {
|
||||
DeclInfo di;
|
||||
ENode *expr;
|
||||
|
||||
if (!(expr = CRTTI_ParseCast(&di)))
|
||||
return nullnode();
|
||||
|
||||
if (IS_TYPE_POINTER_ONLY(di.thetype)) {
|
||||
if (TPTR_QUAL(di.thetype) & Q_REFERENCE) {
|
||||
if (!iscpp_typeequal(TPTR_TARGET(di.thetype), expr->rtype))
|
||||
CError_Error(CErrorStr164);
|
||||
|
||||
if (ENODE_IS(expr, EINDIRECT)) {
|
||||
expr->rtype = TPTR_TARGET(di.thetype);
|
||||
expr->flags = di.qual & ENODE_FLAG_QUALS;
|
||||
} else {
|
||||
CError_Error(CErrorStr142);
|
||||
}
|
||||
} else {
|
||||
if (!iscpp_typeequal(di.thetype, expr->rtype))
|
||||
CError_Error(CErrorStr164);
|
||||
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
}
|
||||
} else if (IS_TYPE_MEMBERPOINTER(di.thetype)) {
|
||||
if (!iscpp_typeequal(di.thetype, expr->rtype))
|
||||
CError_Error(CErrorStr164);
|
||||
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
} else {
|
||||
if (!is_typesame(di.thetype, expr->rtype))
|
||||
CError_Error(CErrorStr164);
|
||||
else
|
||||
expr = do_typecast(expr, di.thetype, di.qual);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
2068
compiler_and_linker/FrontEnd/C/CSOM.c
Normal file
2068
compiler_and_linker/FrontEnd/C/CSOM.c
Normal file
File diff suppressed because it is too large
Load Diff
1632
compiler_and_linker/FrontEnd/C/CTemplateClass.c
Normal file
1632
compiler_and_linker/FrontEnd/C/CTemplateClass.c
Normal file
File diff suppressed because it is too large
Load Diff
1383
compiler_and_linker/FrontEnd/C/CTemplateFunc.c
Normal file
1383
compiler_and_linker/FrontEnd/C/CTemplateFunc.c
Normal file
File diff suppressed because it is too large
Load Diff
1880
compiler_and_linker/FrontEnd/C/CTemplateNew.c
Normal file
1880
compiler_and_linker/FrontEnd/C/CTemplateNew.c
Normal file
File diff suppressed because it is too large
Load Diff
1962
compiler_and_linker/FrontEnd/C/CTemplateTools.c
Normal file
1962
compiler_and_linker/FrontEnd/C/CTemplateTools.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user