summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/C/CSOM.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CSOM.c')
-rw-r--r--compiler_and_linker/FrontEnd/C/CSOM.c2068
1 files changed, 2068 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CSOM.c b/compiler_and_linker/FrontEnd/C/CSOM.c
new file mode 100644
index 0000000..7e80e32
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/C/CSOM.c
@@ -0,0 +1,2068 @@
+#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
+};
+
+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->precompile != 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;
+}
+
+CW_INLINE UInt16 CSOM_GetTokenTableIndex(const Object *object) {
+ CError_ASSERT(173, IS_TYPE_METHOD(object->type));
+ return TYPE_METHOD(object->type)->vtbl_index;
+}
+
+static SInt32 CSOM_GetTokenOffset(Object *object) {
+ return 24 + 4 * CSOM_GetTokenTableIndex(object);
+}
+
+typedef struct TypeSig {
+ UInt8 x0;
+ UInt8 x1;
+ UInt8 x2;
+} TypeSig;
+
+static int 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)->is_static == 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 = info->classdataobject->flags | OBJECT_EXPORT;
+ }
+}
+
+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)->is_static &&
+ (!(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)->vtbl_index > count)
+ count = TYPE_METHOD(object->type)->vtbl_index;
+ } else {
+ TYPE_METHOD(object->type)->vtbl_index = 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)->vtbl_index] = 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)->vtbl_index = 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)->vtbl_index = 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 = CLASS_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)->is_static == 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 == CLASS_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;
+ UInt16 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) {
+ index++;
+ ancestor = ancestor->next;
+ }
+
+ 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;
+ UInt16 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)->vtbl_index == 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;
+ for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) {
+ OLinkList *reloc = lalloc(sizeof(OLinkList));
+ reloc->next = relocs;
+ relocs = reloc;
+ reloc->obj = ancestor->tclass->sominfo->classdataobject;
+ reloc->offset = size;
+ reloc->somevalue = 0;
+ 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;
+ for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) {
+ if (ancestor->overrides) {
+ for (override = ancestor->overrides; override; override = override->next) {
+ OLinkList *reloc = lalloc(sizeof(OLinkList));
+ reloc->next = relocs;
+ relocs = reloc;
+ reloc->obj = override->a;
+ reloc->offset = offset;
+ reloc->somevalue = 0;
+ offset += 4;
+ }
+ }
+ }
+
+ 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) {
+ overrideCount++;
+ override = override->next;
+ }
+ 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;
+ SOMAncestor *ancestor;
+ SInt32 offset;
+
+ 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(char *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;
+ char *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(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) {
+ 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;
+ }
+ size += 4;
+ }
+
+ 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_optimize) {
+ 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_optimize) {
+ 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_optimize) {
+ 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, "%" PRId32, 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_INTERNAL;
+ 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 = expr->flags | ENODE_FLAG_10;
+ } else {
+ CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset);
+ if (copts.som_call_optimize && 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 = expr->flags | ENODE_FLAG_10;
+ }
+
+ return expr;
+}