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