MWCC/compiler_and_linker/unsorted/CSOM.c

2075 lines
60 KiB
C
Raw Normal View History

2022-12-29 12:32:55 +00:00
#include "compiler/CSOM.h"
#include "compiler/CClass.h"
#include "compiler/CDecl.h"
#include "compiler/CError.h"
#include "compiler/CException.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInit.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/CMangler.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CScope.h"
#include "compiler/CodeGen.h"
#include "compiler/CompilerTools.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/types.h"
#include "cos.h"
// all pointers have been converted to UInt32 for the sake of maintaining 32-bit compat
typedef struct {
SInt32 zero;
/* struct somStaticClassInfo * */ UInt32 sci;
/* void * */ UInt32 instanceDataToken;
SInt32 reserved[3];
/* void * */ UInt32 tokens[1];
} somClassDataStructure;
enum {
mtVirtualMethod = 0,
mtProcedure = 1,
mtNonStatic = 2,
mtEmpty = 3,
mtDToken = 4
};
enum {
pdUByte = 0,
pdSByte = 1,
pdUHalf = 2,
pdSHalf = 3,
pdULong = 4,
pdSLong = 5,
pdVLong = 6,
pdVoid = 7,
pdSFlt = 8,
pdDFlt = 9,
pdLFlt = 10,
pdVSAgg = 11,
pdNPtr = 12,
pdLPtr = 13,
pdSAgg = 14,
pdLAgg = 15
};
enum {
fgShortOrChars = 1,
fgShortFloats = 2,
fgAnyFloats = 4,
fgAnyNon4Bytes = 8
};
enum {
cfSharedStrings = 1,
cfTempClass = 2,
cfProxyClass = 4,
cfClassAllocate = 0x100,
cfClassDeallocate = 0x200,
cfClassInit = 0x400,
cfClassUninit = 0x800
};
typedef struct {
UInt32 majorVersion;
UInt32 minorVersion;
UInt32 flags;
UInt16 dataAlignment;
UInt16 classTokenCount;
UInt16 numDirectParents;
UInt16 numMetaClasses;
UInt16 numOverriddenAncestors;
UInt16 numMigratedMethods;
UInt16 numSelectInherited;
UInt16 numUnused;
UInt16 dummy2a[4];
} somStaticClassCounts;
typedef UInt8 somSlotUsage;
typedef UInt8 somSignatureInfo;
typedef UInt16 somOverrideData;
typedef UInt16 somMigratedMethods;
typedef UInt16 somSelectedInherited;
typedef UInt32 somParentVersions;
typedef struct {
/* const char * */ UInt32 className;
UInt32 instanceDataSize;
/* const somParentVersions * */ UInt32 parentVersions;
/* const somSlotUsage * */ UInt32 ttSlotUsage;
/* const somSignatureInfo * */ UInt32 signatureInfo;
/* const char * */ UInt32 methodNames;
/* const somOverrideData * */ UInt32 overrideData;
/* const somMigratedMethods * */ UInt32 migratedMethods;
/* const somSelectedInherited * */ UInt32 selectedInherited;
/* const void * */ UInt32 unused;
/* const void * */ UInt32 dummy4b[4];
} somStaticClassDescription;
typedef struct somStaticClassInfo {
UInt32 layoutVersion;
/* somClassDataStructure * */ UInt32 tokenTable;
/* somMethodPtr * */ UInt32 overrideMethods;
/* somClassDataStructure ** */ UInt32 specifiedAncestry;
/* somOpaque */ UInt32 DLLDesignator;
/* somMethodPtr * */ UInt32 specialProcs;
/* somRuntimeClassInfo * */ UInt32 runtimeClassInfo;
SInt32 interesting;
/* somClassDataStructure ** */ UInt32 actualAncestry;
/* void * */ UInt32 extra[4];
/* const somStaticClassCounts * */ UInt32 classCounts;
somStaticClassDescription classDescription;
} somStaticClassInfo;
CSOMStub *csom_stubs;
static HashNameNode *csom_initname;
static HashNameNode *csom_uninitname;
static HashNameNode *csom_envname;
static HashNameNode *csom_selfname;
static FuncArg SOMIDT_arg1 = {
NULL,
NULL,
NULL,
TYPE(&void_ptr),
0,
0,
0,
0
};
static TypeFunc SOMIDT_type = {
TYPEFUNC,
0,
&SOMIDT_arg1,
NULL,
TYPE(&void_ptr),
0,
0
};
void CSOM_Setup(Boolean flag) {
if (!flag)
csom_stubs = NULL;
csom_initname = GetHashNameNodeExport("somInit");
csom_uninitname = GetHashNameNodeExport("somUninit");
csom_envname = GetHashNameNodeExport("Environment");
csom_selfname = GetHashNameNodeExport("__somself");
}
void CSOM_Cleanup(void) {
CSOMStub *stub;
if (cparamblkptr->isPrecompiling != 1) {
for (stub = csom_stubs; stub; stub = stub->next) {
switch (stub->x10) {
case 0:
CodeGen_SOMStub(stub->object, rt_som_glue1, stub->tclass->sominfo->classdataobject, stub->offset);
break;
case 1:
CodeGen_SOMStub(stub->object, rt_som_glue2, stub->tclass->sominfo->classdataobject, stub->offset);
break;
case 2:
CodeGen_SOMStub(stub->object, rt_som_glue3, stub->tclass->sominfo->classdataobject, stub->offset);
break;
default:
CError_FATAL(132);
}
}
}
}
static HashNameNode *CSOM_NameTranslate(HashNameNode *name) {
if (name == constructor_name_node)
name = csom_initname;
else if (name == destructor_name_node)
name = csom_uninitname;
return name;
}
static Type *CSOM_FindClassType(HashNameNode *name) {
Type *type;
type = CScope_GetTagType(cscope_current, name);
if (!type) {
CPrep_ErrorName(CErrorStr281, name->name);
type = &stvoid;
}
return type;
}
static inline UInt16 CSOM_GetTokenTableIndex(const Object *object) {
CError_ASSERT(173, IS_TYPE_METHOD(object->type));
return TYPE_METHOD(object->type)->x1E;
}
static SInt32 CSOM_GetTokenOffset(Object *object) {
return 24 + 4 * CSOM_GetTokenTableIndex(object);
}
typedef struct TypeSig {
UInt8 x0;
UInt8 x1;
UInt8 x2;
} TypeSig;
static UInt8 CSOM_GetTypeSig(TypeSig *sig, Type *type, Boolean flag) {
if (type->size > 4)
sig->x1 |= fgAnyNon4Bytes;
switch (type->type) {
case TYPEVOID:
if (flag)
return pdVoid;
break;
case TYPEINT:
case TYPEENUM:
if (is_unsigned(type)) {
switch (type->size) {
case 1:
sig->x1 |= fgShortOrChars;
return pdUByte;
case 2:
sig->x1 |= fgShortOrChars;
return pdUHalf;
case 4:
return pdULong;
case 8:
return pdVLong;
}
} else {
switch (type->size) {
case 1:
sig->x1 |= fgShortOrChars;
return pdSByte;
case 2:
sig->x1 |= fgShortOrChars;
return pdSHalf;
case 4:
return pdSLong;
case 8:
return pdVLong;
}
}
break;
case TYPEFLOAT:
sig->x1 |= fgAnyFloats;
switch (type->size) {
case 4:
sig->x1 |= fgShortFloats;
return pdSFlt;
case 8:
return pdDFlt;
case 12:
case 16:
return pdLFlt;
}
break;
case TYPEPOINTER:
return pdNPtr;
case TYPESTRUCT:
case TYPECLASS:
if (flag) {
if (type->size <= 2) {
sig->x1 |= fgShortOrChars;
return pdVSAgg;
} else if (type->size <= 4) {
return pdSAgg;
} else {
return pdLAgg;
}
}
break;
}
CError_Error(CErrorStr273);
return 5;
}
static void CSOM_GetFuncSig(TypeFunc *tfunc, Boolean flag) {
FuncArg *arg;
Boolean pendingData;
UInt8 work;
TypeSig sig;
sig.x2 = CSOM_GetTypeSig(&sig, tfunc->functype, 1);
sig.x1 = 0;
sig.x0 = 0;
for (arg = tfunc->args; arg; arg = arg->next) {
if (arg == &elipsis || arg == &oldstyle || (++sig.x0 == 0)) {
CError_Error(CErrorStr273);
break;
}
CSOM_GetTypeSig(&sig, arg->type, 0);
}
if (flag) {
if ((arg = tfunc->args)) {
if (TYPE_METHOD(tfunc)->x26 == 0)
arg = arg->next;
if (arg && CMach_GetFunctionResultClass(tfunc) != 0)
arg = arg->next;
}
AppendGListByte(&name_mangle_list, sig.x0);
AppendGListByte(&name_mangle_list, (sig.x1 << 4) | sig.x2);
if (sig.x1) {
pendingData = 0;
work = 0;
while (arg) {
work = (work << 4) | CSOM_GetTypeSig(&sig, arg->type, 0);
if (pendingData) {
AppendGListByte(&name_mangle_list, work);
pendingData = 0;
work = 0;
} else {
pendingData = 1;
}
arg = arg->next;
}
if (pendingData)
AppendGListByte(&name_mangle_list, work << 4);
}
}
}
void CSOM_CheckFuncType(TypeFunc *tfunc) {
CSOM_GetFuncSig(tfunc, 0);
}
static Object *CSOM_MakeObject(char *name1, char *name2, SInt32 size) {
Object *object = CParser_NewCompilerDefDataObject();
object->name = CParser_NameConcat(name1, name2);
object->type = CDecl_NewStructType(size, 4);
CScope_AddObject(object->nspace, object->name, OBJ_BASE(object));
return object;
}
void CSOM_MakeSOMClass(TypeClass *tclass) {
ClassList *base;
for (base = tclass->bases; base; base = base->next) {
if (!base->base->sominfo) {
CError_Error(CErrorStr267);
break;
}
}
if (!tclass->sominfo) {
SOMInfo *info = galloc(sizeof(SOMInfo));
memclrw(info, sizeof(SOMInfo));
tclass->sominfo = info;
info->classdataobject = CSOM_MakeObject(tclass->classname->name, "ClassData", 28);
info->classdataobject->flags |= OBJECT_FLAGS_40;
}
}
static Boolean CSOM_IsTokenListFunc(Object *object) {
Type *type = object->type;
if (
IS_TYPE_FUNC(type) &&
!(TYPE_FUNC(type)->flags & FUNC_FLAGS_20) &&
!TYPE_METHOD(type)->x26 &&
(!(object->qual & Q_INLINE) || object->datatype == DVFUNC)
)
return 1;
return 0;
}
static Object **CSOM_GetLexicalOrderMethodArray(TypeClass *tclass, int *resultCount) {
Object *object;
int count;
Object **array;
CScopeObjectIterator iter;
count = 0;
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (IS_TYPE_METHOD(object->type)) {
if (CSOM_IsTokenListFunc(object)) {
if (TYPE_METHOD(object->type)->x1E > count)
count = TYPE_METHOD(object->type)->x1E;
} else {
TYPE_METHOD(object->type)->x1E = 0;
}
}
}
*resultCount = ++count;
array = lalloc(sizeof(Object *) * count);
memclrw(array, sizeof(Object *) * count);
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (CSOM_IsTokenListFunc(object))
array[TYPE_METHOD(object->type)->x1E] = object;
}
return array;
}
void CSOM_ClassComplete(TypeClass *tclass) {
Object *object;
CScopeObjectIterator iter;
SInt32 counter;
SOMReleaseOrder *order;
if (tclass->sominfo->order) {
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (CSOM_IsTokenListFunc(object)) {
HashNameNode *name;
name = CSOM_NameTranslate(object->name);
for (order = tclass->sominfo->order, counter = 0; order; order = order->next, counter++) {
if (order->name == name) {
order->state = SOMMS_Method;
TYPE_METHOD(object->type)->x1E = counter;
break;
}
}
if (!order)
CError_Error(CErrorStr278, object);
}
}
for (order = tclass->sominfo->order; order; order = order->next) {
if (order->state == SOMMS_Deleted) {
SOMReleaseOrder *order2;
VClassList *vbase;
for (vbase = tclass->vbases; vbase; vbase = vbase->next) {
for (order2 = vbase->base->sominfo->order; order2; order2 = order2->next) {
if (order->name == order2->name && order2->state == SOMMS_Method) {
order->state = SOMMS_Migrated;
break;
}
}
}
}
}
} else {
Object **array;
int arrayCount;
SInt32 i;
array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount);
for (i = counter = 0; i < arrayCount; i++) {
object = array[i];
if (object) {
if (counter == 0 && copts.pedantic)
CError_Warning(CErrorStr291);
TYPE_METHOD(object->type)->x1E = counter++;
}
}
}
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
NameSpaceObjectList *nsol;
if (!(nsol = CScope_NextObjectIteratorObjectList(&iter)))
break;
if (nsol->object->otype == OT_OBJECT && nsol->next && nsol->next->object->otype == OT_OBJECT) {
while (nsol) {
if (
nsol->object->otype == OT_OBJECT &&
(!(OBJECT(nsol->object)->qual & Q_INLINE) || OBJECT(nsol->object)->datatype == DVFUNC)
)
CError_Error(CErrorStr270, nsol->object);
nsol = nsol->next;
}
}
}
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (!(object->qual & Q_INLINE)) {
CError_ASSERT(529, IS_TYPE_FUNC(object->type));
TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_4;
tclass->action = 1;
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (IS_TYPE_FUNC(object->type))
TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_4;
}
break;
}
}
if (tclass->sominfo->oidl_callstyle == 0) {
Type *envType;
envType = CSOM_FindClassType(csom_envname);
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (
IS_TYPE_FUNC(object->type) &&
TYPE_METHOD(object->type)->x26 == 0 &&
!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20) &&
!(
TYPE_FUNC(object->type)->args &&
TYPE_FUNC(object->type)->args->next &&
IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->next->type) &&
TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == envType
)
)
{
CError_Error(CErrorStr282, object);
}
}
}
if (tclass->action == 0)
CError_Error(CErrorStr280);
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct SOMOverride {
struct SOMOverride *next;
Object *a;
Object *b;
} SOMOverride;
typedef struct SOMAncestor {
struct SOMAncestor *next;
TypeClass *tclass;
SOMOverride *overrides;
Boolean xC;
Boolean xD;
} SOMAncestor;
typedef struct SOMMethod {
struct SOMMethod *next;
HashNameNode *name;
union {
Object *object;
struct {
UInt16 a;
UInt16 b;
} pair;
} u;
SOMMethodState state;
} SOMMethod;
typedef struct SOMGenerator {
SOMMethod *methods;
SOMAncestor *ancestors;
Object *sciObj;
Object *classAncestorsObj;
Object *overrideProcsObj;
Object *dlldFunc;
Object *specialProcsObj;
somStaticClassCounts counts;
int overrideProcsCount;
Boolean hasNew;
Boolean hasDelete;
} SOMGenerator;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static SOMAncestor *CSOM_FindAddAncestor(SOMGenerator *gen, TypeClass *tclass, TypeClass *ancestorClass, UInt16 *resultIndex) {
SOMAncestor *ancestor;
SOMAncestor *scan;
int index;
ancestor = gen->ancestors;
for (scan = ancestor, index = 0; scan; scan = scan->next, index++) {
if (scan->tclass == ancestorClass) {
if (resultIndex)
*resultIndex = index;
return scan;
}
}
if (ancestor) {
index = 1;
while (ancestor->next) {
ancestor = ancestor->next;
index++;
}
ancestor->next = lalloc(sizeof(SOMAncestor));
memclrw(ancestor->next, sizeof(SOMAncestor));
ancestor = ancestor->next;
} else {
index = 0;
ancestor = lalloc(sizeof(SOMAncestor));
memclrw(ancestor, sizeof(SOMAncestor));
gen->ancestors = ancestor;
}
ancestor->tclass = ancestorClass;
if (resultIndex)
*resultIndex = index;
return ancestor;
}
static void CSOM_GenerateOverrideIntroLists(SOMGenerator *gen, TypeClass *tclass) {
Object *object;
VClassList *vbase;
ClassList *base;
SOMMethod *method;
SOMMethod **ptr;
CScopeObjectIterator iter;
for (base = tclass->bases; base; base = base->next) {
SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, base->base, NULL);
ancestor->xD = 1;
gen->counts.numDirectParents++;
}
if (tclass->sominfo->metaclass && tclass->sominfo->metaclass->sominfo) {
SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, tclass->sominfo->metaclass, NULL);
ancestor->xC = 1;
gen->counts.numMetaClasses++;
}
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (IS_TYPE_FUNC(object->type) && (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) {
for (vbase = tclass->vbases; vbase; vbase = vbase->next) {
Object *object2;
CScopeObjectIterator iter2;
CScope_InitObjectIterator(&iter2, vbase->base->nspace);
while (1) {
if (!(object2 = OBJECT(CScope_NextObjectIteratorObject(&iter2))))
break;
if (
IS_TYPE_FUNC(object2->type) &&
object->name == object2->name &&
object2->datatype == DVFUNC &&
!(TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_20) &&
CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(object2->type), 0) != 0
)
{
SOMAncestor *ancestor;
SOMOverride *override;
ancestor = CSOM_FindAddAncestor(gen, tclass, vbase->base, NULL);
if (ancestor->overrides) {
override = lalloc(sizeof(SOMOverride));
memclrw(override, sizeof(SOMOverride));
override->next = ancestor->overrides;
ancestor->overrides = override;
} else {
override = lalloc(sizeof(SOMOverride));
memclrw(override, sizeof(SOMOverride));
ancestor->overrides = override;
gen->counts.numOverriddenAncestors++;
}
override->a = object;
override->b = object2;
break;
}
}
}
gen->overrideProcsCount++;
}
}
ptr = &gen->methods;
if (tclass->sominfo->order) {
SOMReleaseOrder *order;
SOMReleaseOrder *order2;
SInt32 index;
SInt32 index2;
for (order = tclass->sominfo->order, index = 0; order; order = order->next, index++) {
method = lalloc(sizeof(SOMMethod));
memclrw(method, sizeof(SOMMethod));
*ptr = method;
ptr = &method->next;
method->name = order->name;
method->state = order->state;
switch (order->state) {
case SOMMS_Migrated:
for (vbase = tclass->vbases; vbase; vbase = vbase->next) {
for (order2 = vbase->base->sominfo->order, index2 = 0; order2; order2 = order2->next, index2++) {
if (order->name == order2->name && order2->state == SOMMS_Method) {
CSOM_FindAddAncestor(gen, tclass, vbase->base, &method->u.pair.a);
method->u.pair.b = index2;
break;
}
}
if (order2)
break;
}
gen->counts.numMigratedMethods++;
break;
case SOMMS_Method:
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (
IS_TYPE_FUNC(object->type) &&
CSOM_NameTranslate(object->name) == order->name
)
{
CError_ASSERT(733, TYPE_METHOD(object->type)->x1E == index);
method->u.object = object;
break;
}
}
CError_ASSERT(737, object != NULL);
break;
}
gen->counts.classTokenCount++;
}
} else {
Object **array;
int arrayCount;
SInt32 i;
array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount);
for (i = 0; i < arrayCount; i++) {
object = array[i];
if (object) {
method = lalloc(sizeof(SOMMethod));
memclrw(method, sizeof(SOMMethod));
*ptr = method;
ptr = &method->next;
method->u.object = object;
method->name = object->name;
method->state = SOMMS_Method;
gen->counts.classTokenCount++;
}
}
}
}
static void CSOM_GenerateClassAncestors(SOMGenerator *gen, TypeClass *tclass) {
SOMAncestor *ancestor;
Object *object;
OLinkList *relocs;
SInt32 size;
char *buf;
if (gen->ancestors) {
object = CSOM_MakeObject(tclass->classname->name, "ClassAncestors", 4);
object->sclass = TK_STATIC;
relocs = NULL;
size = 0;
ancestor = gen->ancestors;
while (ancestor) {
OLinkList *reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = ancestor->tclass->sominfo->classdataobject;
reloc->offset = size;
reloc->somevalue = 0;
ancestor = ancestor->next;
size += 4;
}
buf = lalloc(size);
memclrw(buf, size);
object->type->size = size;
CInit_DeclareData(object, buf, relocs, object->type->size);
gen->classAncestorsObj = object;
}
}
static void CSOM_GenerateOverrideProcs(SOMGenerator *gen, TypeClass *tclass) {
SOMOverride *override;
SOMAncestor *ancestor;
Object *object;
OLinkList *relocs;
SInt32 size;
SInt32 offset;
char *buf;
if (gen->overrideProcsCount) {
size = gen->overrideProcsCount * 4;
object = CSOM_MakeObject(tclass->classname->name, "OverrideProcs", size);
object->sclass = TK_STATIC;
relocs = NULL;
offset = 0;
ancestor = gen->ancestors;
while (ancestor) {
if (ancestor->overrides) {
override = ancestor->overrides;
while (override) {
OLinkList *reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = override->a;
reloc->offset = offset;
reloc->somevalue = 0;
override = override->next;
offset += 4;
}
}
ancestor = ancestor->next;
}
buf = lalloc(size);
memclrw(buf, size);
CInit_DeclareData(object, buf, relocs, object->type->size);
gen->overrideProcsObj = object;
}
}
static Object *CSOM_GenerateOverrideData(SOMGenerator *gen) {
SOMAncestor *ancestor;
Object *object;
short ancestorIndex;
name_mangle_list.size = 0;
for (ancestor = gen->ancestors, ancestorIndex = 0; ancestor; ancestor = ancestor->next, ancestorIndex++) {
if (ancestor->overrides) {
SOMOverride *override;
short overrideCount;
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(ancestorIndex));
override = ancestor->overrides;
overrideCount = 0;
while (override) {
override = override->next;
overrideCount++;
}
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(overrideCount));
for (override = ancestor->overrides; override; override = override->next) {
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(CSOM_GetTokenTableIndex(override->b)));
}
}
}
COS_LockHandle(name_mangle_list.data);
object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0);
COS_UnlockHandle(name_mangle_list.data);
return object;
}
static Object *CSOM_GenerateMigrateData(SOMGenerator *gen) {
SOMMethod *method;
Object *object;
int index;
name_mangle_list.size = 0;
for (method = gen->methods, index = 0; method; method = method->next, index++) {
if (method->state == SOMMS_Migrated) {
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.a));
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.b));
AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(index));
}
}
COS_LockHandle(name_mangle_list.data);
object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0);
COS_UnlockHandle(name_mangle_list.data);
return object;
}
static void CSOM_GenerateDLLDFunc(SOMGenerator *gen, TypeClass *tclass) {
TypeFunc *tfunc;
Object *object;
tfunc = galloc(sizeof(TypeFunc));
memclrw(tfunc, sizeof(TypeFunc));
tfunc->type = TYPEFUNC;
tfunc->functype = &stvoid;
object = CParser_NewCompilerDefFunctionObject();
object->type = TYPE(tfunc);
object->sclass = TK_STATIC;
object->name = CParser_NameConcat(tclass->classname->name, "DLLD");
if (CScope_GetLocalObject(cscope_root, object->name))
CError_Error(CErrorStr333, object);
gen->dlldFunc = object;
CFunc_GenerateDummyFunction(object);
}
static void CSOM_GenerateSpecialProcs(SOMGenerator *gen, TypeClass *tclass) {
Object *newFunc;
Object *deleteFunc;
Object *object;
OLinkList *relocs;
SInt32 size;
CScopeObjectIterator iter;
char buf[16];
newFunc = deleteFunc = NULL;
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (IS_TYPE_FUNC(object->type)) {
if (object->name == CMangler_OperatorName(TK_NEW)) {
newFunc = object;
gen->hasNew = 1;
} else if (object->name == CMangler_OperatorName(TK_DELETE)) {
deleteFunc = object;
gen->hasDelete = 1;
}
}
}
if (newFunc || deleteFunc) {
object = CSOM_MakeObject(tclass->classname->name, "SpecialProcs", 4);
object->sclass = TK_STATIC;
relocs = NULL;
size = 0;
if (newFunc) {
OLinkList *reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = newFunc;
reloc->offset = size;
reloc->somevalue = 0;
size += 4;
}
if (deleteFunc) {
OLinkList *reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = deleteFunc;
reloc->offset = size;
reloc->somevalue = 0;
size += 4;
}
memclrw(buf, sizeof(buf));
object->type->size = size;
CInit_DeclareData(object, buf, relocs, object->type->size);
gen->specialProcsObj = object;
}
}
static Object *CSOM_GenerateParentVersion(SOMGenerator *gen) {
SInt32 size;
UInt32 *buf;
SInt32 offset;
SOMAncestor *ancestor;
size = 8 * (gen->counts.numDirectParents + gen->counts.numMetaClasses);
buf = lalloc(size);
for (ancestor = gen->ancestors, offset = 0; ancestor; ancestor = ancestor->next) {
if (ancestor->xC || ancestor->xD) {
buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->majorversion);
buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->minorversion);
}
}
return CInit_DeclareString((char *) buf, size, 0, 0);
}
static void CSOM_SetNibble(UInt8 *buf, int offset, UInt8 value) {
int i = offset >> 1;
if (offset & 1) {
int left = buf[i] & 0xF0;
int right = value & 0xF;
buf[i] = left | right;
} else {
int left = value << 4;
int right = buf[i] & 0xF;
buf[i] = left | right;
}
}
static Object *CSOM_GenerateSlotUsage(SOMGenerator *gen) {
SInt32 size;
SOMMethod *method;
UInt8 *buf;
int offset;
size = (gen->counts.classTokenCount + 1) / 2;
buf = lalloc(size);
memclrw(buf, size);
for (method = gen->methods, offset = 0; method; method = method->next, offset++) {
switch (method->state) {
case SOMMS_Deleted:
case SOMMS_Migrated:
CSOM_SetNibble(buf, offset, mtEmpty);
break;
case SOMMS_Method:
CSOM_SetNibble(buf, offset, mtVirtualMethod);
break;
default:
CError_FATAL(1048);
}
}
return CInit_DeclareString((char *) buf, size, 0, 0);
}
static Object *CSOM_GenerateSignature(SOMGenerator *gen) {
Object *object;
SOMMethod *method;
name_mangle_list.size = 0;
for (method = gen->methods; method; method = method->next) {
if (method->state == SOMMS_Method)
CSOM_GetFuncSig(TYPE_FUNC(method->u.object->type), 1);
}
COS_LockHandle(name_mangle_list.data);
object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0);
COS_UnlockHandle(name_mangle_list.data);
return object;
}
static Object *CSOM_GenerateMethodNames(SOMGenerator *gen) {
Object *object;
SOMMethod *method;
HashNameNode *name;
name_mangle_list.size = 0;
for (method = gen->methods; method; method = method->next) {
if (method->name) {
name = CSOM_NameTranslate(method->name);
AppendGListID(&name_mangle_list, name->name);
}
}
COS_LockHandle(name_mangle_list.data);
object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0);
COS_UnlockHandle(name_mangle_list.data);
return object;
}
static void CSOM_SetupClassCounts(SOMGenerator *gen, TypeClass *tclass, somStaticClassCounts *counts) {
gen->counts.majorVersion = tclass->sominfo->majorversion;
gen->counts.minorVersion = tclass->sominfo->minorversion;
gen->counts.flags = cfSharedStrings;
if (gen->hasNew)
gen->counts.flags |= cfClassAllocate;
if (gen->hasDelete)
gen->counts.flags |= cfClassDeallocate;
switch (tclass->align) {
case 1:
gen->counts.dataAlignment = 0;
break;
case 2:
gen->counts.dataAlignment = 1;
break;
case 4:
gen->counts.dataAlignment = 2;
break;
case 8:
gen->counts.dataAlignment = 3;
break;
default:
gen->counts.dataAlignment = 4;
break;
}
gen->counts.numSelectInherited = 0;
memclrw(counts, sizeof(somStaticClassCounts));
counts->majorVersion = CTool_EndianConvertWord32(gen->counts.majorVersion);
counts->minorVersion = CTool_EndianConvertWord32(gen->counts.minorVersion);
counts->flags = CTool_EndianConvertWord32(gen->counts.flags);
counts->dataAlignment = CTool_EndianConvertWord16(gen->counts.dataAlignment);
counts->classTokenCount = CTool_EndianConvertWord16(gen->counts.classTokenCount);
counts->numDirectParents = CTool_EndianConvertWord16(gen->counts.numDirectParents);
counts->numMetaClasses = CTool_EndianConvertWord16(gen->counts.numMetaClasses);
counts->numOverriddenAncestors = CTool_EndianConvertWord16(gen->counts.numOverriddenAncestors);
counts->numMigratedMethods = CTool_EndianConvertWord16(gen->counts.numMigratedMethods);
counts->numSelectInherited = CTool_EndianConvertWord16(gen->counts.numSelectInherited);
}
static void CSOM_GenerateSCIObject(SOMGenerator *gen, TypeClass *tclass) {
Object *object;
OLinkList *relocs;
OLinkList *reloc;
somStaticClassInfo sci;
somStaticClassCounts classCounts;
object = CSOM_MakeObject(tclass->classname->name, "SCI", sizeof(sci));
object->sclass = TK_STATIC;
memclrw(&sci, sizeof(sci));
sci.layoutVersion = CTool_EndianConvertWord32(70);
reloc = lalloc(sizeof(OLinkList));
reloc->next = NULL;
relocs = reloc;
reloc->obj = tclass->sominfo->classdataobject;
reloc->offset = 4;
reloc->somevalue = 0;
if (gen->overrideProcsObj) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = gen->overrideProcsObj;
reloc->offset = 8;
reloc->somevalue = 0;
}
if (gen->classAncestorsObj) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = gen->classAncestorsObj;
reloc->offset = 12;
reloc->somevalue = 0;
}
if (gen->dlldFunc) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = gen->dlldFunc;
reloc->offset = 16;
reloc->somevalue = 0;
}
if (gen->specialProcsObj) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = gen->specialProcsObj;
reloc->offset = 20;
reloc->somevalue = 0;
}
CSOM_SetupClassCounts(gen, tclass, &classCounts);
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CInit_DeclareString((char *) &classCounts, sizeof(classCounts), 0, 0);
reloc->offset = 52;
reloc->somevalue = 0;
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CInit_DeclareString(tclass->classname->name, strlen(tclass->classname->name) + 1, 0, 0);
reloc->offset = 56;
reloc->somevalue = 0;
sci.classDescription.instanceDataSize = CTool_EndianConvertWord32(tclass->size);
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateParentVersion(gen);
reloc->offset = 64;
reloc->somevalue = 0;
if (gen->methods) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateSlotUsage(gen);
reloc->offset = 68;
reloc->somevalue = 0;
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateSignature(gen);
reloc->offset = 72;
reloc->somevalue = 0;
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateMethodNames(gen);
reloc->offset = 76;
reloc->somevalue = 0;
}
if (gen->overrideProcsObj) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateOverrideData(gen);
reloc->offset = 80;
reloc->somevalue = 0;
}
if (gen->counts.numMigratedMethods) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = CSOM_GenerateMigrateData(gen);
reloc->offset = 84;
reloc->somevalue = 0;
}
sci.classDescription.selectedInherited = 0;
CInit_DeclareData(object, &sci, relocs, object->type->size);
gen->sciObj = object;
}
static void CSOM_GenerateClassDataObject(SOMGenerator *gen, TypeClass *tclass) {
void *buf;
OLinkList *relocs;
OLinkList *reloc;
SInt32 size;
SOMMethod *method;
relocs = NULL;
for (size = 24, method = gen->methods; method; method = method->next, size += 4) {
if (method->state == SOMMS_Method) {
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = method->u.object;
reloc->offset = size;
reloc->somevalue = 0;
}
}
buf = lalloc(size);
memclrw(buf, size);
reloc = lalloc(sizeof(OLinkList));
reloc->next = relocs;
relocs = reloc;
reloc->obj = gen->sciObj;
reloc->offset = 4;
reloc->somevalue = 0;
tclass->sominfo->classdataobject->type->size = size;
CInit_DeclareData(tclass->sominfo->classdataobject, buf, relocs, tclass->sominfo->classdataobject->type->size);
}
void CSOM_GenerateClassStructures(TypeClass *tclass) {
SOMGenerator gen;
memclrw(&gen, sizeof(gen));
CSOM_GenerateOverrideIntroLists(&gen, tclass);
CSOM_GenerateClassAncestors(&gen, tclass);
CSOM_GenerateOverrideProcs(&gen, tclass);
CSOM_GenerateDLLDFunc(&gen, tclass);
CSOM_GenerateSpecialProcs(&gen, tclass);
CSOM_GenerateSCIObject(&gen, tclass);
CSOM_GenerateClassDataObject(&gen, tclass);
}
static TypeClass *CSOM_GetCurrentSOMClass(void) {
if (cscope_current->theclass && cscope_current->theclass->sominfo)
return cscope_current->theclass;
CError_Error(CErrorStr277);
return NULL;
}
void CSOM_PragmaReleaseOrder(void) {
TypeClass *tclass;
SOMReleaseOrder *firstOrder;
SOMReleaseOrder *order;
SOMReleaseOrder **ptr;
Boolean flag;
short token;
if (!(tclass = CSOM_GetCurrentSOMClass()))
return;
token = CPrep_PragmaLex(0);
if (token != '(') {
if (token != TK_IDENTIFIER) {
CPrep_Error(CErrorStr114);
return;
}
if (!strcmp(tkidentifier->name, "list")) {
token = CPrep_PragmaLex(0);
if (token != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
}
flag = 1;
} else {
flag = 0;
token = CPrep_PragmaLex(0);
}
firstOrder = NULL;
if (flag || token != ')') {
ptr = &firstOrder;
while (1) {
if (token != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
for (order = firstOrder; order; order = order->next) {
if (order->name == tkidentifier) {
CError_Error(CErrorStr122, tkidentifier->name);
return;
}
}
order = galloc(sizeof(SOMReleaseOrder));
*ptr = order;
ptr = &order->next;
order->next = NULL;
order->name = tkidentifier;
order->state = SOMMS_Deleted;
if (flag) {
token = CPrep_PragmaLex(1);
if (!token)
break;
} else {
token = CPrep_PragmaLex(0);
if (token == ')')
break;
}
if (token != ',') {
CPrep_Error(CErrorStr116);
return;
}
token = CPrep_PragmaLex(flag);
}
}
tclass->sominfo->order = firstOrder;
}
void CSOM_PragmaClassVersion(void) {
Type *type;
if (CPrep_PragmaLex(0) != '(') {
CPrep_Error(CErrorStr114);
return;
}
if (CPrep_PragmaLex(0) != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
type = CScope_GetTagType(cscope_current, tkidentifier);
if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) {
CPrep_ErrorName(CErrorStr276, tkidentifier->name);
return;
}
if (CPrep_PragmaLex(0) != ',') {
CPrep_Error(CErrorStr116);
return;
}
if (CPrep_PragmaLex(0) != TK_INTCONST) {
CPrep_Error(CErrorStr186);
return;
}
TYPE_CLASS(type)->sominfo->majorversion = CInt64_GetULong(&tkintconst);
if (CPrep_PragmaLex(0) != ',') {
CPrep_Error(CErrorStr116);
return;
}
if (CPrep_PragmaLex(0) != TK_INTCONST) {
CPrep_Error(CErrorStr186);
return;
}
TYPE_CLASS(type)->sominfo->minorversion = CInt64_GetULong(&tkintconst);
if (CPrep_PragmaLex(0) != ')') {
CPrep_Error(CErrorStr115);
return;
}
}
void CSOM_PragmaMetaClass(void) {
Type *type;
Type *type2;
if (CPrep_PragmaLex(0) != '(') {
CPrep_Error(CErrorStr114);
return;
}
if (CPrep_PragmaLex(0) != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
type = CScope_GetTagType(cscope_current, tkidentifier);
if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) {
CPrep_ErrorName(CErrorStr276, tkidentifier->name);
return;
}
if (CPrep_PragmaLex(0) != ',') {
CPrep_Error(CErrorStr116);
return;
}
if (CPrep_PragmaLex(0) != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
type2 = CScope_GetTagType(cscope_current, tkidentifier);
if (!(type2 && IS_TYPE_CLASS(type2) && TYPE_CLASS(type2)->sominfo)) {
CPrep_ErrorName(CErrorStr276, tkidentifier->name);
return;
}
TYPE_CLASS(type)->sominfo->metaclass = TYPE_CLASS(type2);
if (CPrep_PragmaLex(0) != ')') {
CPrep_Error(CErrorStr115);
return;
}
}
void CSOM_PragmaCallStyle(void) {
TypeClass *tclass;
if (!(tclass = CSOM_GetCurrentSOMClass()))
return;
if (CPrep_PragmaLex(0) != TK_IDENTIFIER) {
CPrep_Error(CErrorStr107);
return;
}
if (!strcmp(tkidentifier->name, "IDL")) {
tclass->sominfo->oidl_callstyle = 0;
return;
}
if (!strcmp(tkidentifier->name, "OIDL")) {
tclass->sominfo->oidl_callstyle = 1;
return;
}
CPrep_Error(CErrorStr186);
}
void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc) {
FuncArg *arg = CParser_NewFuncArg();
arg->name = GetHashNameNodeExport("__theclass");
arg->type = CDecl_NewPointerType(CSOM_FindClassType(GetHashNameNodeExport("SOMClass")));
arg->next = tfunc->args;
tfunc->args = arg;
}
static Object *CSOM_FindRTFunc(char *namestr, char *sig) {
NameSpaceObjectList *nsol;
Object *object;
FuncArg *arg;
if (
(nsol = CScope_GetLocalObject(cscope_root, GetHashNameNodeExport(namestr))) &&
nsol->object->otype == OT_OBJECT
)
{
object = OBJECT(nsol->object);
if (
IS_TYPE_FUNC(object->type) &&
*(sig++) == 'p' &&
IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype)
)
{
for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) {
switch (*(sig++)) {
case 'p':
if (IS_TYPE_POINTER_ONLY(arg->type))
continue;
break;
case 'i':
if (arg->type == TYPE(&stsignedint))
continue;
break;
case 'I':
if (arg->type == TYPE(&stunsignedint))
continue;
break;
case 'l':
if (arg->type == TYPE(&stsignedlong))
continue;
break;
case 'L':
if (arg->type == TYPE(&stunsignedlong))
continue;
break;
}
break;
}
if (arg == NULL && *sig == 0)
return object;
}
CError_Error(CErrorStr275, namestr);
} else {
CError_Error(CErrorStr274, namestr);
}
return NULL;
}
static ENode *CSOM_MakeTempCondition(ENode *left, ENode *cond, ENode *expr1, ENode *right) {
ENode *expr;
expr = lalloc(sizeof(ENode));
expr->type = ECOND;
expr->cost = 0;
expr->flags = 0;
expr->rtype = &stvoid;
expr->data.cond.cond = cond;
expr->data.cond.expr1 = expr1;
expr->data.cond.expr2 = nullnode();
expr->data.cond.expr2->rtype = &stvoid;
if (left)
expr = makediadicnode(left, expr, ECOMMA);
if (right) {
expr = makediadicnode(expr, right, ECOMMA);
expr->rtype = right->rtype;
}
return expr;
}
ENode *CSOM_New(TypeClass *tclass) {
Object *newFunc;
ENode *expr;
if (tk == '(') {
if ((tk = lex()) == ')') {
tk = lex();
} else {
CError_Error(CErrorStr272);
}
}
if (!copts.som_env_check || !copts.som_call_opt) {
newFunc = CSOM_FindRTFunc("somNewObjectInstance", "ppll");
if (!newFunc)
return nullnode();
} else {
newFunc = rt_som_new;
}
expr = funccallexpr(
newFunc,
create_objectrefnode(tclass->sominfo->classdataobject),
intconstnode(TYPE(&stunsignedlong), tclass->sominfo->majorversion),
intconstnode(TYPE(&stunsignedlong), tclass->sominfo->minorversion),
NULL
);
expr->rtype = CDecl_NewPointerType(TYPE(tclass));
if (copts.som_env_check && !copts.som_call_opt) {
ENode *tempExpr;
ENode *checkExpr;
ENode *notExpr;
tempExpr = CExpr_GetETEMPCopy(expr);
checkExpr = funccallexpr(rt_som_newcheck, nullnode(), NULL, NULL, NULL);
notExpr = makemonadicnode(tempExpr, ELOGNOT);
notExpr->rtype = CParser_GetBoolType();
expr = CSOM_MakeTempCondition(NULL, notExpr, checkExpr, tempExpr);
}
return expr;
}
ENode *CSOM_Delete(TypeClass *tclass, ENode *objExpr) {
Object *func;
if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp")))
return funccallexpr(func, objExpr, NULL, NULL, NULL);
return nullnode();
}
void CSOM_InitAutoClass(Object *object) {
Type *type;
Statement *stmt;
Object *func;
if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) {
type = object->type;
object->type = CDecl_NewPointerType(type);
TPTR_QUAL(object->type) = Q_REFERENCE;
stmt = CFunc_AppendStatement(ST_EXPRESSION);
stmt->expr = makediadicnode(create_objectnode2(object), CSOM_New(TYPE_CLASS(type)), EASS);
CExcept_RegisterDeleteObject(stmt, object, func);
}
}
static void CSOM_FindIntroClassOffset(TypeClass *tclass, Object *func, TypeClass **resultClass, SInt32 *resultOffset) {
Object *scan;
VClassList *vbase;
CScopeObjectIterator iter;
if (!(TYPE_FUNC(func->type)->flags & FUNC_FLAGS_20)) {
CScope_InitObjectIterator(&iter, tclass->nspace);
while (1) {
if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (scan == func) {
*resultClass = tclass;
*resultOffset = CSOM_GetTokenOffset(scan);
return;
}
}
for (vbase = tclass->vbases; vbase; vbase = vbase->next) {
CScope_InitObjectIterator(&iter, vbase->base->nspace);
while (1) {
if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (scan == func) {
*resultClass = vbase->base;
*resultOffset = CSOM_GetTokenOffset(scan);
return;
}
}
}
} else {
for (vbase = tclass->vbases; vbase; vbase = vbase->next) {
CScope_InitObjectIterator(&iter, vbase->base->nspace);
while (1) {
if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter))))
break;
if (scan->name == func->name) {
if (
IS_TYPE_FUNC(scan->type) &&
scan->datatype == DVFUNC &&
!(TYPE_FUNC(scan->type)->flags & FUNC_FLAGS_20) &&
CClass_GetOverrideKind(TYPE_FUNC(func->type), TYPE_FUNC(scan->type), 0)
)
{
*resultClass = vbase->base;
*resultOffset = CSOM_GetTokenOffset(scan);
return;
}
break;
}
}
}
}
CError_FATAL(1731);
}
static ENode *CSOM_ComputeSOMSelf(TypeClass *tclass, ENode *selfExpr) {
ENode *expr;
Object obj;
expr = create_objectrefnode(tclass->sominfo->classdataobject);
expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), 8), EADD);
expr->rtype = CDecl_NewPointerType(TYPE(&SOMIDT_type));
expr = makemonadicnode(expr, EINDIRECT);
memclrw(&obj, sizeof(Object));
obj.otype = OT_OBJECT;
obj.type = TYPE(&SOMIDT_type);
obj.name = no_name_node;
obj.datatype = DFUNC;
selfExpr = funccallexpr(&obj, selfExpr, NULL, NULL, NULL);
CError_ASSERT(1761, ENODE_IS(selfExpr, EFUNCCALL));
selfExpr->data.funccall.funcref = expr;
return selfExpr;
}
ENode *CSOM_SOMSelfObjectExpr(TypeClass *tclass) {
ObjectList *list;
Object *obj;
for (list = locals; list; list = list->next) {
if (list->object->name == csom_selfname)
return create_objectnode(list->object);
}
obj = CParser_NewLocalDataObject(NULL, 1);
obj->name = csom_selfname;
obj->type = CDecl_NewPointerType(TYPE(tclass));
CFunc_SetupLocalVarInfo(obj);
return create_objectnode(obj);
}
void CSOM_InitSOMSelf(TypeClass *tclass, Statement *stmt) {
ObjectList *list;
HashNameNode *name;
ENode *selfExpr;
name = GetHashNameNodeExport("__somself");
for (list = locals; list; list = list->next) {
if (list->object->name == name) {
selfExpr = CClass_CreateThisSelfExpr();
CError_ASSERT(1811, selfExpr);
selfExpr = CSOM_ComputeSOMSelf(tclass, selfExpr);
stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt);
stmt->expr = makediadicnode(create_objectnode(list->object), selfExpr, EASS);
break;
}
}
}
ENode *CSOM_EnvCheck(ENode *funccall, ENodeList *checkArg) {
ENodeList *arg; // r26
ENodeList *arg2; // r28
ENode *expr26; // r26
ENode *expr27; // r27
ENode *expr28; // r28
Type *returnType; // r31
returnType = funccall->rtype;
CError_ASSERT(1842, arg = funccall->data.funccall.args);
if (arg == checkArg)
CError_ASSERT(1845, arg = arg->next);
CError_ASSERT(1847, arg2 = arg->next);
if (arg2 == checkArg)
CError_ASSERT(1850, arg2 = arg2->next);
CError_ASSERT(1852, IS_TYPE_POINTER_ONLY(arg2->node->rtype));
if (!IS_TYPE_VOID(funccall->data.funccall.functype->functype)) {
if (checkArg) {
if (ENODE_IS(checkArg->node, ETEMP)) {
if (checkArg->node->data.temp.uniqueid == 0)
checkArg->node->data.temp.uniqueid = CParser_GetUniqueID();
expr26 = lalloc(sizeof(ENode));
*expr26 = *checkArg->node;
expr26->data.temp.needs_dtor = 0;
} else {
expr26 = CExpr_GetETEMPCopy(checkArg->node);
}
} else {
expr26 = CExpr_GetETEMPCopy(funccall);
}
} else {
expr26 = NULL;
}
if (!ENODE_IS(arg2->node, EOBJREF)) {
if (ENODE_IS_INDIRECT_TO(arg2->node, EOBJREF) && arg2->node->data.monadic->data.objref->datatype == DLOCAL) {
expr27 = lalloc(sizeof(ENode));
*expr27 = *arg2->node;
} else {
expr27 = CExpr_GetETEMPCopy(arg2->node);
}
} else {
expr27 = lalloc(sizeof(ENode));
*expr27 = *arg2->node;
}
if (copts.som_call_opt) {
funccall = makediadicnode(funccall, funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), ECOMMA);
if (expr26)
funccall = makediadicnode(funccall, expr26, ECOMMA);
} else {
expr28 = lalloc(sizeof(ENode));
*expr28 = *expr27;
expr28 = makemonadicnode(expr28, EINDIRECT);
expr28->rtype = TYPE(&stsignedlong);
funccall = CSOM_MakeTempCondition(
funccall,
expr28,
funccallexpr(rt_som_check, expr27, NULL, NULL, NULL),
expr26);
}
funccall->rtype = returnType;
return funccall;
}
static Boolean CSOM_CanUseGlueCall(TypeFunc *tfunc) {
int gprCounter;
int fprCounter;
FuncArg *arg;
gprCounter = 8;
fprCounter = 13;
if (CMach_GetFunctionResultClass(tfunc) != 0)
gprCounter = 7;
for (arg = tfunc->args; arg; arg = arg->next) {
if (arg == &elipsis || arg == &oldstyle)
return 0;
switch (arg->type->type) {
case TYPEINT:
case TYPEENUM:
case TYPEPOINTER:
if (--gprCounter < 0)
return 0;
break;
case TYPEFLOAT:
if (--fprCounter < 0)
return 0;
break;
default:
return 0;
}
}
return 1;
}
static char *CSOM_AppendString(char *dst, char *src) {
int ch;
while ((ch = *(src++)))
*(dst++) = ch;
return dst;
}
static ENode *CSOM_SOMGlueCall(TypeClass *tclass, SInt32 offset, Object *object) {
UInt8 funcResultClass;
UInt32 bufsize;
char *buf;
char *ptr;
Object *stubObj;
CSOMStub *stub;
ENode *expr;
char mybuf[256];
char numberbuf[16];
for (stub = csom_stubs; stub; stub = stub->next) {
if (stub->tclass == tclass && stub->offset == offset)
break;
}
if (!stub) {
funcResultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type));
bufsize = strlen(tclass->sominfo->classdataobject->name->name) + 32;
buf = (bufsize > sizeof(mybuf)) ? lalloc(bufsize) : mybuf;
ptr = CSOM_AppendString(buf, "___glue_");
if (tclass->sominfo->oidl_callstyle == 0) {
if (funcResultClass == 0) {
*(ptr++) = '4';
} else {
*(ptr++) = '5';
}
} else {
*(ptr++) = '_';
}
*(ptr++) = '_';
sprintf(numberbuf, "%ld", strlen(tclass->sominfo->classdataobject->name->name));
ptr = CSOM_AppendString(ptr, numberbuf);
ptr = CSOM_AppendString(ptr, tclass->sominfo->classdataobject->name->name);
*(ptr++) = '_';
sprintf(numberbuf, "%ld", offset);
ptr = CSOM_AppendString(ptr, numberbuf);
*ptr = 0;
stubObj = CParser_NewCompilerDefFunctionObject();
stubObj->nspace = cscope_root;
stubObj->name = GetHashNameNodeExport(buf);
stubObj->u.func.linkname = stubObj->name;
stubObj->type = object->type;
stubObj->qual = object->qual | Q_20000;
stubObj->flags = OBJECT_FLAGS_10;
CScope_AddObject(stubObj->nspace, stubObj->name, OBJ_BASE(stubObj));
stub = galloc(sizeof(CSOMStub));
stub->next = csom_stubs;
stub->object = stubObj;
stub->tclass = tclass;
stub->offset = offset;
csom_stubs = stub;
if (tclass->sominfo->oidl_callstyle == 0) {
if (funcResultClass == 0)
stub->x10 = 0;
else
stub->x10 = 1;
} else {
stub->x10 = 2;
}
}
expr = create_objectrefnode(stub->object);
expr->rtype = CDecl_NewPointerType(object->type);
return expr;
}
ENode *CSOM_MemberVarAccess(BClassList *path, ObjMemberVar *ivar, ENode *thisExpr) {
if (!thisExpr) {
if (
!cscope_currentfunc ||
!cscope_currentclass ||
!cscope_is_member_func ||
!(thisExpr = CClass_CreateThisSelfExpr())
)
{
CError_Error(CErrorStr221);
return NULL;
}
}
CError_ASSERT(2069, ENODE_IS(thisExpr, EINDIRECT));
thisExpr = thisExpr->data.monadic;
if (
path->next == NULL &&
cscope_currentclass == TYPE_CLASS(path->type) &&
ENODE_IS(thisExpr, EOBJREF) &&
thisExpr->data.objref->name == this_name_node
)
{
thisExpr = CSOM_SOMSelfObjectExpr(cscope_currentclass);
}
else
{
CClass_CheckPathAccess(path, NULL, ivar->access);
if (ivar->has_path)
path = OBJ_MEMBER_VAR_PATH(ivar)->path;
while (path->next)
path = path->next;
thisExpr = CSOM_ComputeSOMSelf(TYPE_CLASS(path->type), thisExpr);
}
thisExpr = makemonadicnode(thisExpr, EINDIRECT);
thisExpr->rtype = path->type;
return CClass_AccessMember(thisExpr, ivar->type, ivar->qual, ivar->offset);
}
ENode *CSOM_MethodAccess(BClassList *path, Object *func, Boolean flag) {
TypeClass *tclass;
TypeClass *tclass2;
TypeClass *tclass3;
ENode *expr;
SInt32 offset;
ClassList *base;
CError_ASSERT(2107, path != NULL);
tclass = TYPE_CLASS(path->type);
if (path->next)
path = path->next;
tclass2 = TYPE_CLASS(path->type);
if (flag) {
SInt32 counter;
ENode *indirectExpr;
Object *resolveFunc;
counter = 0;
if (tclass != tclass2) {
for (base = tclass->bases; base; base = base->next) {
counter++;
if (base->base == tclass2)
break;
}
if (!base)
CError_Error(CErrorStr279);
}
CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset);
expr = create_objectrefnode(tclass3->sominfo->classdataobject);
expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD);
indirectExpr = makemonadicnode(expr, EINDIRECT);
indirectExpr->rtype = CDecl_NewPointerType(func->type);
resolveFunc = CSOM_FindRTFunc("somParentNumResolve", "ppip");
if (!resolveFunc)
return nullnode();
expr = funccallexpr(
resolveFunc,
create_objectrefnode(tclass->sominfo->classdataobject),
intconstnode(TYPE(&stsignedint), counter),
indirectExpr,
NULL);
expr->rtype = indirectExpr->rtype;
if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0)
expr->flags |= ENODE_FLAG_10;
} else {
CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset);
if (copts.som_call_opt && CSOM_CanUseGlueCall(TYPE_FUNC(func->type)))
return CSOM_SOMGlueCall(tclass3, offset, func);
expr = create_objectrefnode(tclass3->sominfo->classdataobject);
expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD);
expr = makemonadicnode(expr, EINDIRECT);
expr->rtype = CDecl_NewPointerType(func->type);
if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0)
expr->flags |= ENODE_FLAG_10;
}
return expr;
}