diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/C/CSOM.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CSOM.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/C/CSOM.c | 2068 |
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; +} |