diff options
Diffstat (limited to 'compiler_and_linker/unsorted')
21 files changed, 22368 insertions, 14 deletions
diff --git a/compiler_and_linker/unsorted/CABI.c b/compiler_and_linker/unsorted/CABI.c new file mode 100644 index 0000000..0b29b9d --- /dev/null +++ b/compiler_and_linker/unsorted/CABI.c @@ -0,0 +1,93 @@ +#include "compiler/CABI.h" +#include "compiler/CMachine.h" +#include "compiler/types.h" +#include "compiler/CompilerTools.h" + +static void *trans_vtboffsets; // TODO type +static void *cabi_pathroot; // TODO type - 8 byte struct?? +static void *cabi_pathcur; // TODO type +static TypeClass *cabi_loop_class; +static Boolean cabi_loop_construct; + +short CABI_GetStructResultArgumentIndex(void) { + return 0; +} + +Type *CABI_GetSizeTType(void) { + return (Type *) &stunsignedlong; +} + +Type *CABI_GetPtrDiffTType(void) { + return (Type *) &stsignedlong; +} + +SInt16 CABI_StructSizeAlignValue(Type *type, SInt32 size) {} + +void CABI_ReverseBitField(TypeBitfield *tbitfield) {} + +// not sure about the sig for this, it's unused lmao +static void CABI_AllocateZeroVTablePointer() {} + +static SInt32 CABI_GetBaseSize(TypeClass *tclass) {} +static void CABI_AllocateBases() {} +static void CABI_AllocateVirtualBasePointers() {} +static void CABI_GetMemberOffset() {} +static void CABI_AllocateMembers() {} +static void CABI_AllocateVirtualBases() {} +static void CABI_FindZeroDeltaVPtr() {} +static void CABI_FindZeroVirtualBaseMember() {} + +void CABI_AddVTable(TypeClass *tclass) { + tclass->vtable = galloc(sizeof(VTable)); + memclrw(tclass->vtable, sizeof(VTable)); +} + +SInt32 CABI_GetVTableOffset(TypeClass *tclass) { + return 0; +} + +static void CABI_GetBaseVTableSize() {} +static void CABI_ApplyClassFlags() {} +static void CABI_AllocateVTable() {} +void CABI_LayoutClass(DeclE *decle, TypeClass *tclass) {} +void CABI_MakeDefaultArgConstructor(Object *obj, TypeClass *tclass) {} +static void CABI_ThisArg() {} +ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset) {} +static void CABI_VArg() {} +static void CABI_MakeVArgExpr() {} +static void CABI_MakeCopyConArgExpr() {} +static void CABI_InitVBasePtr1() {} +static void CABI_InitVBasePtrs() {} +static void CABI_GetVBasePath() {} +static void CABI_GetVBasePtr() {} +static SInt32 CABI_FindNVBase(TypeClass *tclass, TypeClass *base, SInt32 offset) {} +SInt32 CABI_GetCtorOffsetOffset(TypeClass *tclass, TypeClass *base) {} +static void CABI_InitVBaseCtorOffsets() {} +static void CABI_InitVTablePtrs() {} +static Boolean CABI_IsOperatorNew(Object *obj) {} +Object *CABI_ConstructorCallsNew(TypeClass *tclass) {} +void CABI_TransConstructor(Object *obj, Statement *stmt, TypeClass *tclass, TransConstructorCallback callback, Boolean flag) {} +void CABI_MakeDefaultConstructor(TypeClass *tclass, Object *obj) {} +static void CABI_AssignObject() {} +static void CABI_FindIntegralSizeType() {} +static void CABI_AppendCopyRegion() {} +static void CABI_ClassInitLoopCallBack() {} +static void CABI_CopyConAssignCB() {} +void CABI_MakeDefaultCopyConstructor(TypeClass *tclass, Object *obj) {} +void CABI_MakeDefaultAssignmentOperator(TypeClass *tclass, Object *obj) {} +static void CABI_DestroyMembers() {} +static void CABI_DestroyBases() {} +static void CABI_DestroyVBases() {} +void CABI_TransDestructor(Object *obj1, Object *obj2, Statement *stmt, TypeClass *tclass) {} +void CABI_MakeDefaultDestructor(TypeClass *tclass, Object *obj) {} +static void CABI_CreateLayeredDestructor() {} +void CABI_MakeLayeredDestructor(TypeClass *tclass, Object *obj) {} + +Object *CABI_GetDestructorObject(Object *obj, int what) { + return obj; +} + +static void CABI_AddLayeredDestructor() {} +void CABI_AddLayeredDestructors(TypeClass *tclass) {} + +ENode *CABI_DestroyObject(Object *dtor, ENode *objexpr, UInt8 mode, Boolean flag1, Boolean flag2) {} diff --git a/compiler_and_linker/unsorted/CClass.c b/compiler_and_linker/unsorted/CClass.c new file mode 100644 index 0000000..7932586 --- /dev/null +++ b/compiler_and_linker/unsorted/CClass.c @@ -0,0 +1,122 @@ +#include "compiler/CClass.h" + +typedef struct OVClassBase { + struct OVClassBase *next; + struct OVClass *ovclass; + Boolean is_virtual; +} OVClassBase; + +typedef struct OVFunc { + struct OVFunc *next; + Object *obj; + struct OVClass *ovc8; + struct OVFunc *ovfC; + struct OVFunc *ovf10; +} OVFunc; + +typedef struct OVClass { + TypeClass *tclass; + OVFunc *vfuncs; + OVClassBase *bases; + SInt32 offset; + SInt32 voffset; + Boolean alloced_vtable; +} OVClass; + +static TypeClass *main_class; +static void *cclass_thunklist; // TODO type +static TypeClass *cclass_isbase_mostderived; +static void *cclass_isbase_foundoffset; // TODO type +static Boolean cclass_isambigbase; +static short cclass_founddepth; +static void *vtable_object_data; // TODO type +static void *vtable_data_size; // TODO type +static VTableObjectLink *vtable_object_links; +static TypeClass *cclass_vbase; +static OVClass *cclass_ovbase; +static OVClass *cclass_root; +static Object *found_pure; +static Boolean check_pures; +static Object *cclass_dominator_vobject; +static SInt32 cclass_dominator_voffset; +static Object *cclass_dominator_oobject; +static TypeClass *cclass_dominator_oclass; +static SInt32 cclass_dominator_ooffset; +static Object *cclass_dominator_eobject; + +void CClass_Init(void) {} +void CClass_GenThunks(void) {} +static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) {} +static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) {} +static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB) {} +UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) {} +Boolean CClass_IsEmpty(TypeClass *tclass) {} +Boolean CClass_IsNonStaticMemberFunc(TypeMethod *tmethod) {} +Object *CClass_DefaultConstructor(TypeClass *tclass) {} +Object *CClass_DummyDefaultConstructor(TypeClass *tclass) {} +ENode *CClass_DefaultConstructorCall(TypeClass *a, TypeClass *b, ENode *expr, SInt32 unkshortparam, Boolean flag1, Boolean flag2, Boolean *errorflag) {} +Object *CClass_AssignmentOperator(TypeClass *tclass) {} +Object *CClass_CopyConstructor(TypeClass *tclass) {} +NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) {} +Object *CClass_Constructor(TypeClass *tclass) {} +Object *CClass_Destructor(TypeClass *tclass) {} +Boolean CClass_IsConstructor(Object *obj) {} +Boolean CClass_IsDestructor(Object *obj) {} +Boolean CClass_IsPODClass(TypeClass *tclass) {} +Boolean CClass_IsTrivialCopyClass(TypeClass *tclass) {} +Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass) {} +Boolean CClass_ReferenceArgument(TypeClass *tclass) {} +BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global) {} +BClassList *CClass_AppendPath(BClassList *a, BClassList *b) {} +static AccessType CClass_GetPathAccess(BClassList *path) {} +Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2) {} +static BClassList *CClass_GetBasePathRec(TypeClass *a, TypeClass *b, SInt32 offset, short depth) {} +BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase) {} +Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag) {} +TypeClass *CClass_GetQualifiedClass(void) {} +ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean flag) {} +ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag) {} +ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b) {} +SInt32 CClass_GetPathOffset(BClassList *path) {} +Boolean CClass_ClassDominates(TypeClass *a, TypeClass *b) {} +SInt32 CClass_VirtualBaseOffset(TypeClass *a, TypeClass *b) {} +SInt32 CClass_VirtualBaseVTableOffset(TypeClass *a, TypeClass *b) {} +SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **obj) {} +Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj) {} +static OVClass *CClass_FindOVClass(OVClass *ovclass, TypeClass *tclass, SInt32 offset) {} +static OVClass *CClass_BuildOVClassTree(OVClass *root, TypeClass *tclass, SInt32 offset, SInt32 voffset) {} +static Boolean CClass_IsBaseOf(OVClass *a, OVClass *b) {} +static void CClass_FindOVFunc(OVClass *a, OVClass *b, OVFunc *func) {} +static TypeList *CClass_GetCoVariantClassList(TypeList *list, TypeClass *tclass, Object *func, Boolean flag) {} +static TypeMethod *CClass_GetCovariantType(TypeMethod *tmethod, Type *type) {} +static Object *CClass_FindCovariantFunction(Object *func, Type *type) {} +static ObjectList *CClass_DeclareCovariantFuncs(ObjectList *list, Object *func, TypeClass *tclass) {} +void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata) {} +static void CClass_OverrideOVClassTree(OVClass *ovclass) {} +static void CClass_AllocVTableRec(OVClass *ovclass) {} +static Object *CClass_CheckClass(OVClass *ovclass, Boolean errorflag) {} +static void CClass_AllocVTable(TypeClass *tclass) {} +static Object *CClass_CheckVirtuals(TypeClass *tclass) {} +static void CClass_CheckVirtualBaseOverrides(OVClass *a, OVClass *b, Boolean flag) {} +static void CClass_CheckHideVirtual(OVClass *a, OVClass *b) {} +void CClass_CheckOverrides(TypeClass *tclass) {} +static void CClass_FindDominator(TypeClass *tclass1, SInt32 offset1, Object *object1, TypeClass *tclass2, SInt32 offset2, TypeClass *base) {} +static void CClass_ConstructVTable(TypeClass *tclass, SInt32 voffset, SInt32 offset, TypeClass *base) {} +void CClass_ClassDefaultFuncAction(TypeClass *tclass) {} +void CClass_ClassAction(TypeClass *tclass) {} +void CClass_MakeStaticActionClass(TypeClass *tclass) {} +Object *CClass_CheckPures(TypeClass *tclass) {} +void CClass_MemberDef(Object *obj, TypeClass *tclass) {} +Object *CClass_ThisSelfObject(void) {} +ENode *CClass_CreateThisSelfExpr(void) {} +static Boolean CClass_BaseMemberAccess(BClassList *path, AccessType access) {} +static Boolean CClass_CanAccess(BClassList *path, AccessType access) {} +void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access) {} +static BClassList *CClass_PathCleanup(BClassList *path, TypeClass *tclass) {} +void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access) {} +void CClass_CheckObjectAccess(BClassList *path, Object *obj) {} +void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec) {} +static Type *CClass_PointerTypeCopy(Type *type) {} +Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags) {} +static void CClass_OptimizeBitFieldAccess(Type **type, SInt32 *offset) {} +ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset) {} diff --git a/compiler_and_linker/unsorted/CCompiler.c b/compiler_and_linker/unsorted/CCompiler.c index d496389..8339cf6 100644 --- a/compiler_and_linker/unsorted/CCompiler.c +++ b/compiler_and_linker/unsorted/CCompiler.c @@ -3,6 +3,7 @@ #include "compiler/types.h" #include "pref_structs.h" #include "compiler/CompilerTools.h" +#include "compiler/CPrep.h" Boolean systemHandles; @@ -11,14 +12,6 @@ Boolean crippled; SInt32 license_cookie; CParams cparams; -// TODO move me to CParser.c, or maybe CMachine.c? -Type sttemplexpr = {TYPETEMPLDEPEXPR, 0}; -Type stillegal = {TYPEILLEGAL, 1}; -Type stvoid = {TYPEVOID, 0}; -TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0}; -TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0}; -// TODO move me to CParser.c - static void get_extension(ConstStringPtr src, char *dst) { int ep; diff --git a/compiler_and_linker/unsorted/CDecl.c b/compiler_and_linker/unsorted/CDecl.c new file mode 100644 index 0000000..d6665a6 --- /dev/null +++ b/compiler_and_linker/unsorted/CDecl.c @@ -0,0 +1,4902 @@ +#include "compiler/CDecl.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/tokens.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CMangler.h" +#include "compiler/CClass.h" +#include "compiler/CParser.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CExpr.h" +#include "compiler/CMachine.h" +#include "compiler/CInline.h" +#include "compiler/CABI.h" + +// TODO MOVE ME +extern void CExcept_ScanExceptionSpecification(TypeFunc *tfunc); +extern void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b); +extern void CObjC_ParseDefs(TypeStruct *tstruct); +extern void CTempl_Parse(TypeClass *tclass, short access); +extern Boolean CTempl_InstantiateTemplateClass(TemplClass *cls); +extern Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type); +extern TemplClass *CTemplTool_GetSelfRefTemplate(Type *type); +extern Type *CTemplTool_ResolveMemberSelfRefs(TypeClass *tclass, Type *type, UInt32 *qual); +extern Boolean CTempl_IsQualifiedMember(DeclInfo *declinfo, Type *type, NameSpace **nspace); +extern Object *CTempl_TemplateFunctionCheck(DeclInfo *declinfo, NameSpaceObjectList *list); +extern TemplArg *CTempl_ParseUncheckTemplArgs(void *a, Boolean flag); +extern TemplArg *CTemplTool_MakeGlobalTemplArgCopy(TemplArg *args); +extern void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *declinfo); +extern void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *baseclass, short access, Boolean is_virtual); +extern void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *obj); +extern void CTemplClass_RegisterObjectInit(TemplClass *tmclass, ObjBase *obj, ENode *expr); +extern void CTemplClass_DefineMember(TemplClass *tmclass, Object *obj, FileOffsetInfo *fileoffset, TStream *stream); +extern void CTemplClass_CompleteClass(TemplClass *tmclass, DeclE *decle); +extern void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *tenum); +extern void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *oec, ENode *expr); +extern TypeClass *CTemplClass_DefineNestedClass(TemplClass *tmclass, HashNameNode *name, short mode); +extern void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc); +extern void CSOM_CheckFuncType(TypeFunc *tfunc); +extern void CSOM_ClassComplete(TypeClass *tclass); +extern void CSOM_MakeSOMClass(TypeClass *tclass); +typedef struct BrowseStruct { + void *x0; + void *x4; + void *x8; + void *xC; +} BrowseStruct; +extern void CBrowse_BeginStruct(DeclInfo *declinfo, TypeStruct *type, BrowseStruct *bs); +extern void CBrowse_EndStruct(SInt32 offset, BrowseStruct *bs); +extern void CBrowse_AddStructMember(StructMember *member, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_BeginClass(DeclInfo *declinfo, BrowseStruct *bs); +extern void CBrowse_EndClass(SInt32 offset, BrowseStruct *bs); +extern void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, SInt32 tokenline, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_NewData(Object *obj, CPrepFileInfo *file, SInt32 tokenline, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_NewFunction(Object *obj, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file, CPrepFileInfo *file2, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_AddClassMemberData(Object *obj, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_AddClassMemberFunction(Object *obj, SInt32 tokenoffset, SInt32 fileoffset); +extern void CBrowse_AddClassMemberVar(ObjMemberVar *obj, SInt32 tokenoffset, SInt32 fileoffset); + +AccessType global_access; +FileOffsetInfo member_fileoffset; + +// forward declarations +static void scandirectdecl1(DeclInfo *declinfo); + +Type *CDecl_NewStructType(SInt32 size, SInt16 align) { + TypeStruct *tstruct = galloc(sizeof(TypeStruct)); + memclrw(tstruct, sizeof(TypeStruct)); + + tstruct->type = TYPESTRUCT; + tstruct->size = size; + tstruct->align = align; + tstruct->stype = STRUCT_TYPE_STRUCT; + + return (Type *) tstruct; +} + +Type *CDecl_NewArrayType(Type *type, SInt32 size) { + TypePointer *tarray = galloc(sizeof(TypePointer)); + memclrw(tarray, sizeof(TypePointer)); + + tarray->type = TYPEARRAY; + tarray->size = size; + tarray->target = type; + tarray->qual = 0; + + return (Type *) tarray; +} + +Type *CDecl_NewPointerType(Type *type) { + TypePointer *tptr = galloc(sizeof(TypePointer)); + memclrw(tptr, sizeof(TypePointer)); + + tptr->type = TYPEPOINTER; + tptr->size = 4; + tptr->target = type; + + return (Type *) tptr; +} + +Type *CDecl_NewRefPointerType(Type *type) { + TypePointer *tptr = galloc(sizeof(TypePointer)); + memclrw(tptr, sizeof(TypePointer)); + + tptr->type = TYPEPOINTER; + tptr->size = 4; + tptr->target = type; + tptr->qual = Q_REFERENCE; + + return (Type *) tptr; +} + +Type *CDecl_NewTemplDepType(TypeTemplDepType tdt) { + TypeTemplDep *t = galloc(sizeof(TypeTemplDep)); + memclrw(t, sizeof(TypeTemplDep)); + + t->type = TYPETEMPLATE; + t->size = 1; + t->dtype = tdt; + + return (Type *) t; +} + +void CDecl_SetResultReg(TypeFunc *tfunc) { +} + +static void CDecl_SetFuncResultReg(TypeFunc *tfunc) { +} + +void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags) { + CDecl_SetResultReg(tfunc); +} + +static void CDecl_ParseCPPFuncDecl(TypeFunc *tfunc) { + for (;;) { + if (tk == TK_CONST) { + if (tfunc->flags & FUNC_FLAGS_CONST) + CError_Warning(313, "const"); + tfunc->flags |= FUNC_FLAGS_CONST; + tk = lex(); + } else if (tk == TK_VOLATILE) { + if (tfunc->flags & FUNC_FLAGS_VOLATILE) + CError_Warning(313, "volatile"); + tfunc->flags |= FUNC_FLAGS_VOLATILE; + tk = lex(); + } else { + break; + } + } + + if (tk == TK_THROW) + CExcept_ScanExceptionSpecification(tfunc); +} + +void CDecl_NewConvFuncType(DeclInfo *declinfo) { + TypeFunc *tfunc; + + if (tk != '(') + CError_Error(114); + else + tk = lex(); + + if (tk == TK_VOID) + tk = lex(); + + if (tk != ')') + CError_Error(115); + else + tk = lex(); + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + declinfo->name = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); + tfunc->type = TYPEFUNC; + tfunc->functype = declinfo->thetype; + tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); + tfunc->flags = FUNC_FLAGS_40; + declinfo->x49 = 0; + CDecl_SetFuncFlags(tfunc, 1); + CDecl_ParseCPPFuncDecl(tfunc); + + declinfo->thetype = (Type *) tfunc; + declinfo->qual &= ~(Q_CONST | Q_VOLATILE); + declinfo->storageclass = 0; +} + +void CDecl_CompleteType(Type *type) { + switch (type->type) { + case TYPEPOINTER: + if ((TYPE_POINTER(type)->qual & Q_REFERENCE) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + type = TYPE_POINTER(type)->target; + break; + } + return; + case TYPEARRAY: + do { + type = TYPE_POINTER(type)->target; + } while (IS_TYPE_ARRAY(type)); + if (IS_TYPE_CLASS(type)) + break; + return; + case TYPECLASS: + break; + default: + return; + } + + if ((TYPE_CLASS(type)->flags & (CLASS_FLAGS_2 | CLASS_FLAGS_800)) == CLASS_FLAGS_800) + CTempl_InstantiateTemplateClass(TEMPL_CLASS(type)); +} + +Boolean IsCompleteType(Type *type) { + switch (type->type) { + case TYPEVOID: + CError_Error(126); + return 0; + case TYPEFUNC: + CError_Error(146); + return 0; + case TYPESTRUCT: + if (!type->size) { + CError_Error(136, type, 0); + return 0; + } + return 1; + case TYPECLASS: + if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2) && (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_800) || !CTempl_InstantiateTemplateClass( + TEMPL_CLASS(type)))) { + CError_Error(136, type, 0); + return 0; + } + return 1; + default: + if (!type->size) { + CError_Error(145); + return 0; + } + return 1; + } +} + +Boolean CanAllocObject(Type *type) { + switch (type->type) { + case TYPEVOID: + CError_Error(126); + return 0; + case TYPEFUNC: + CError_Error(146); + return 0; + case TYPECLASS: + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_ABSTRACT) { + CError_AbstractClassError(TYPE_CLASS(type)); + return 0; + } + default: + return 1; + } +} + +Boolean CanCreateObject(Type *type) { + if (!CanAllocObject(type)) + return 0; + + if (IS_TYPE_CLASS(type)) { + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) { + CError_Error(191); + return 0; + } + if (TYPE_CLASS(type)->objcinfo) { + CError_Error(307); + return 0; + } + } + + return 1; +} + +static Boolean CanCreateHandleMemberObject(Type *type) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + if (!CanCreateObject(type)) + return 0; + + if (IS_TYPE_CLASS(type)) { + if (CClass_Destructor(TYPE_CLASS(type)) || CClass_Constructor(TYPE_CLASS(type))) { + CError_Error(191); + return 0; + } + } + + return 1; +} + +void makethetypepointer(DeclInfo *declinfo, UInt32 qual) { + declinfo->thetype = CDecl_NewPointerType(declinfo->thetype); + TYPE_POINTER(declinfo->thetype)->qual = qual; +} + +void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass) { + Type *ptype; + FuncArg *arg; + + ptype = CDecl_NewPointerType(!tclass->sominfo ? (Type *) tclass : &stvoid); + TYPE_POINTER(ptype)->qual = Q_CONST; + + arg = CParser_NewFuncArg(); + arg->name = this_name_node; + arg->type = ptype; + if (tfunc->flags & FUNC_FLAGS_CONST) + arg->qual |= Q_CONST; + if (tfunc->flags & FUNC_FLAGS_VOLATILE) + arg->qual |= Q_VOLATILE; + arg->next = tfunc->args; + tfunc->args = arg; +} + +void CDecl_MakePTMFuncType(TypeFunc *tfunc) { + Type *cvoidp; + FuncArg *arg1; + FuncArg *arg2; + + cvoidp = CDecl_NewPointerType(&stvoid); + TYPE_POINTER(cvoidp)->qual = Q_CONST; + + arg1 = CParser_NewFuncArg(); + arg1->name = this_name_node; + arg1->type = cvoidp; + if (tfunc->flags & FUNC_FLAGS_CONST) + arg1->qual |= Q_CONST; + if (tfunc->flags & FUNC_FLAGS_VOLATILE) + arg1->qual |= Q_VOLATILE; + + arg2 = CParser_NewFuncArg(); + arg2->name = this_name_node; + arg2->type = cvoidp; + arg2->qual = Q_CONST; + + arg1->next = tfunc->args; + arg2->next = arg1; + tfunc->args = arg2; + tfunc->flags |= FUNC_FLAGS_80; +} + +void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype) { + FuncArg *arg = CParser_NewFuncArg(); + arg->type = argtype; + + arg->next = tfunc->args; + tfunc->args = arg; + + if (arg->next && arg->next->type == &stvoid) + arg->next = NULL; +} + +Boolean CDecl_CheckArrayIntegr(Type *type) { + if (!IsCompleteType(type)) + return 0; + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { + CError_Error(289); + return 0; + } + + if (IS_TYPE_REFERENCE(type)) { + CError_Error(196); + return 0; + } + + return CanCreateObject(type); +} + +static Boolean checkfuncintegr(Type *type) { + if (IS_TYPE_VOID(type)) + return 1; + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { + CError_Error(283); + return 0; + } + + return CanCreateObject(type); +} + +void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo) { + FuncArg *list; + TypeFunc *tfunc; + + if (tk == ')') { + if (copts.cplusplus) + list = NULL; + else + list = &oldstyle; + tk = lex(); + } else { + list = parameter_type_list(declinfo); + if (tk != ')') + CError_ErrorSkip(115); + else + tk = lex(); + } + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->args = list; + if (declinfo->qual & Q_PASCAL) { + declinfo->qual &= ~Q_PASCAL; + tfunc->flags = FUNC_FLAGS_PASCAL; + } + + if (copts.cplusplus) { + CDecl_ParseCPPFuncDecl(tfunc); + if (declinfo->storageclass == OBJECT_SCLASS_104 && tfunc->exspecs) + CError_Error(264); + } + + scandirectdecl1(declinfo); + if (!checkfuncintegr(declinfo->thetype)) + declinfo->thetype = &stvoid; + + tfunc->functype = declinfo->thetype; + tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); + declinfo->thetype = (Type *) tfunc; + declinfo->qual &= ~(Q_CONST | Q_VOLATILE); + declinfo->x49 = 0; +} + +static void scandirectdecl1(DeclInfo *declinfo) { + Boolean flag; + CInt64 len; + ENode *expr; + TypeTemplDep *ttempl; + + flag = 0; + if (tk == '[') { + if ((tk = lex()) == ']') { + len = cint64_zero; + tk = lex(); + flag = 1; + } else { + if (!declinfo->x46 || declinfo->x47) { + expr = CExpr_IntegralConstOrDepExpr(); + if (!ENODE_IS(expr, EINTCONST)) { + if (tk != ']') + CError_ErrorSkip(125); + else + tk = lex(); + declinfo->x47 = 1; + scandirectdecl1(declinfo); + if (!CDecl_CheckArrayIntegr(declinfo->thetype)) + declinfo->thetype = (Type *) &stsignedchar; + ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); + ttempl->u.array.type = declinfo->thetype; + ttempl->u.array.index = CInline_CopyExpression(expr, CopyMode1); + declinfo->thetype = (Type *) ttempl; + return; + } + len = expr->data.intval; + if (CInt64_IsNegative(&len)) { + CError_Error(124); + len = cint64_one; + } else if (CInt64_IsZero(&len)) { + if (!copts.ANSI_strict && declinfo->x50) { + flag = 1; + } else { + CError_Error(124); + len = cint64_one; + } + } + } else { + len = cint64_one; + expr = expression(); + if (IS_TYPE_INT(expr->rtype)) { + if (!ENODE_IS(expr, EINTCONST)) + declinfo->x24 = expr; + else + len = expr->data.intval; + } else { + CError_Error(124); + } + } + + if (tk != ']') + CError_ErrorSkip(125); + else + tk = lex(); + } + + declinfo->x47 = 1; + scandirectdecl1(declinfo); + + if (!flag && !CDecl_CheckArrayIntegr(declinfo->thetype)) + declinfo->thetype = (Type *) &stsignedchar; + + if (!declinfo->thetype->size && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) { + ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); + ttempl->u.array.type = declinfo->thetype; + ttempl->u.array.index = CInline_CopyExpression(intconstnode((Type *) &stsignedint, CInt64_GetULong(&len)), CopyMode1); + declinfo->thetype = (Type *) ttempl; + } else { + declinfo->thetype = CDecl_NewArrayType(declinfo->thetype, declinfo->thetype->size * CInt64_GetULong(&len)); + } + } else if (tk == '(') { + if (!copts.cplusplus || !declinfo->name || IS_TYPE_VOID(declinfo->thetype) || CParser_TryParamList(!IS_TYPE_CLASS(declinfo->thetype))) { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + } + } +} + +static void substitute_type(Type *type1, Type *type2) { + SInt32 oldsize; + + while (1) { + switch (type1->type) { + case TYPEPOINTER: + if (TYPE_POINTER(type1)->target == &stillegal) { + TYPE_POINTER(type1)->target = type2; + type1->size = 4; + return; + } + type1 = TYPE_POINTER(type1)->target; + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type1)->ty1 == &stillegal) { + TYPE_MEMBER_POINTER(type1)->ty1 = type2; + if (IS_TYPE_FUNC(type2)) { + CDecl_MakePTMFuncType(TYPE_FUNC(type2)); + type1->size = 12; + } else { + type1->size = 4; + } + return; + } + type1 = TYPE_MEMBER_POINTER(type1)->ty1; + break; + case TYPEARRAY: + if (TYPE_POINTER(type1)->target == &stillegal) { + if (!CDecl_CheckArrayIntegr(type2)) + type2 = (Type *) &stsignedchar; + type1->size *= type2->size; + TYPE_POINTER(type1)->target = type2; + return; + } + oldsize = TYPE_POINTER(type1)->target->size; + substitute_type(TYPE_POINTER(type1)->target, type2); + if (oldsize != TYPE_POINTER(type1)->target->size && oldsize != 0) + type1->size = TYPE_POINTER(type1)->target->size * (type1->size / oldsize); + return; + case TYPEFUNC: + if (TYPE_FUNC(type1)->functype == &stillegal) { + if (!checkfuncintegr(type2)) + type2 = &stvoid; + TYPE_FUNC(type1)->functype = type2; + CDecl_SetFuncResultReg((TypeFunc *) type1); + return; + } + type1 = TYPE_FUNC(type1)->functype; + break; + case TYPETEMPLATE: + if (TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_ARRAY) { + if (TYPE_TEMPLATE(type1)->u.array.type == &stillegal) { + if (!CDecl_CheckArrayIntegr(type2)) + type2 = (Type *) &stsignedchar; + TYPE_TEMPLATE(type1)->u.array.type = type2; + return; + } + type1 = TYPE_TEMPLATE(type1)->u.array.type; + } else { + CError_Error(146); + return; + } + break; + default: + CError_Error(121); + return; + } + } +} + +static void scandecl(DeclInfo *declinfo) { + Type *oldtype; + Type *newtype; + + oldtype = declinfo->thetype; + declinfo->thetype = &stillegal; + scandeclarator(declinfo); + + if (tk != ')') + CError_ErrorSkip(115); + else + tk = lex(); + + newtype = declinfo->thetype; + if (newtype == &stillegal) { + declinfo->thetype = oldtype; + scandirectdecl1(declinfo); + } else { + declinfo->thetype = oldtype; + scandirectdecl1(declinfo); + substitute_type(newtype, declinfo->thetype); + declinfo->thetype = newtype; + } +} + +static Boolean CDecl_ParseOperatorDecl(DeclInfo *declinfo) { + if (declinfo->x3E) { + CError_Error(121); + return 0; + } + + declinfo->x3E = 0; + if (!CParser_ParseOperatorName(&declinfo->x3E, declinfo->x4A && cscope_current->theclass, 0)) + return 0; + + if (!declinfo->x3E) { + conversion_type_name(declinfo); + tkidentifier = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); + declinfo->x54 = 1; + } + return 1; +} + +static Boolean CDecl_IsEnumClassTypeOrRef(Type *type) { + if (IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type)) + return 1; + if (!IS_TYPE_REFERENCE(type)) + return 0; + type = TYPE_POINTER(type)->target; + return IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type); +} + +#define OpMysteryValue0 0 +#define OpMysteryValue1 1 +#define OpMysteryValue2 2 +#define OpMysteryValue3 3 +#define OpMysteryValue4 4 + +static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) { + FuncArg *args; + FuncArg *secondarg; + Type *functype; + short r27; + Boolean r6; + + if (!IS_TYPE_FUNC(declinfo->thetype)) { + CError_Error(193); + return 0; + } + + functype = TYPE_FUNC(declinfo->thetype)->functype; + args = TYPE_FUNC(declinfo->thetype)->args; + if (args) { + if (args != &elipsis && args != &oldstyle) { + r27 = OpMysteryValue1; + if (args->dexpr) { + switch (declinfo->x3E) { + case TK_NEW: + case TK_DELETE: + case TK_NEW_ARRAY: + case TK_DELETE_ARRAY: + break; + default: + CError_Error(205); + } + } + + secondarg = args->next; + if (secondarg) { + r27 = ((secondarg != &elipsis && !secondarg->next) != 0) ? OpMysteryValue4 : OpMysteryValue3; + if (secondarg->dexpr) { + switch (declinfo->x3E) { + case '(': + case TK_NEW: + case TK_DELETE: + case TK_NEW_ARRAY: + case TK_DELETE_ARRAY: + break; + default: + CError_Error(205); + } + } + } + } else { + r27 = OpMysteryValue3; + } + } else { + CError_Error(193); + return 0; + } + + r6 = flag && IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) && !TYPE_METHOD(declinfo->thetype)->x26; + switch (declinfo->x3E) { + case TK_NEW: + case TK_NEW_ARRAY: + if (r6 || !is_typesame(functype, (Type *) &void_ptr) || r27 < OpMysteryValue1 || args->type != CABI_GetSizeTType()) { + CError_Error(193); + return 0; + } + return 1; + case TK_DELETE: + case TK_DELETE_ARRAY: + if (r6 || !IS_TYPE_VOID(functype) || r27 < OpMysteryValue1 || !is_typesame(args->type, (Type *) &void_ptr)) { + CError_Error(193); + return 0; + } + return 1; + case '=': + if (!r6) { + CError_Error(193); + return 0; + } + break; + case '(': + if (!r6) { + CError_Error(193); + return 0; + } + return 1; + case '[': + if (!r6) { + CError_Error(193); + return 0; + } + break; + case TK_ARROW: + if (r27 != OpMysteryValue1 || r6 == 0) { + CError_Error(193); + return 0; + } + return 1; + case TK_INCREMENT: + case TK_DECREMENT: + if (r27 == OpMysteryValue2 && secondarg->type != (Type *) &stsignedint) { + CError_Error(193); + return 0; + } + break; + } + + if (flag && !r6) { + CError_Error(193); + return 0; + } + + switch (declinfo->x3E) { + case '&': + case '*': + case '+': + case '-': + case TK_INCREMENT: + case TK_DECREMENT: + if (r27 != OpMysteryValue1) + goto whatever; + case '!': + case '~': + if (r27 == OpMysteryValue1) { + if (flag || CDecl_IsEnumClassTypeOrRef(args->type)) + return 1; + } + break; + case '%': + case ',': + case '/': + case '<': + case '=': + case '>': + case '[': + case '^': + case '|': + case TK_MULT_ASSIGN: + case TK_DIV_ASSIGN: + case TK_MOD_ASSIGN: + case TK_ADD_ASSIGN: + case TK_SUB_ASSIGN: + case TK_SHL_ASSIGN: + case TK_SHR_ASSIGN: + case TK_AND_ASSIGN: + case TK_XOR_ASSIGN: + case TK_OR_ASSIGN: + case TK_LOGICAL_OR: + case TK_LOGICAL_AND: + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + case TK_SHL: + case TK_SHR: + case TK_ARROW: + case TK_DOT_STAR: + case TK_ARROW_STAR: + whatever: + if (r27 == OpMysteryValue2) { + if (flag || CDecl_IsEnumClassTypeOrRef(args->type) || CDecl_IsEnumClassTypeOrRef(secondarg->type)) + return 1; + } + break; + } + + CError_Error(193); + return 0; +} + +static void scandirectdeclarator(DeclInfo *declinfo, NameSpace *nspace) { + HashNameNode *saveident; + CScopeSave scopesave; + Boolean flag; + + if (nspace) + CScope_SetNameSpaceScope(nspace, &scopesave); + + if (tk == '(') { + if ((tk = lex()) == ')') { + if (declinfo->x55) { + CDecl_ParseDirectFuncDecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } else { + CError_Error(121); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + } + + if (!(tk >= TK_AUTO && tk <= TK_BYREF)) { + if (!(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + scandecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } else { + saveident = tkidentifier; + switch (lookahead()) { + case ')': + case ',': + break; + default: + tkidentifier = saveident; + scandecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + } + } + + if (declinfo->name) + CError_Error(121); + + CDecl_ParseDirectFuncDecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + + if (nspace) { + if (tk == TK_OPERATOR) { + if (!CDecl_ParseOperatorDecl(declinfo)) { + CScope_RestoreScope(&scopesave); + return; + } + + if (declinfo->x54) { + declinfo->nspace = nspace; + declinfo->name = tkidentifier; + if (nspace) + CScope_RestoreScope(&scopesave); + + if (tk == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + if (IS_TYPE_FUNC(declinfo->thetype)) + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40; + else + CError_Error(121); + } else { + CError_Error(114); + } + return; + } + + flag = 1; + } else if (tk != TK_IDENTIFIER) { + CError_Error(107); + CScope_RestoreScope(&scopesave); + return; + } else { + flag = 0; + } + + if (declinfo->name) { + CError_Error(121); + CScope_RestoreScope(&scopesave); + return; + } + + declinfo->nspace = nspace; + declinfo->name = tkidentifier; + if (!flag) + tk = lex(); + } else if (tk == TK_IDENTIFIER) { + if (declinfo->name) + CError_Error(121); + declinfo->name = tkidentifier; + tk = lex(); + } else if (tk == TK_OPERATOR) { + if (!CDecl_ParseOperatorDecl(declinfo)) + return; + declinfo->name = tkidentifier; + } + + if (tk == '<' && declinfo->x51) { + declinfo->expltargs = CTempl_ParseUncheckTemplArgs(NULL, 0); + declinfo->has_expltargs = 1; + declinfo->x51 = 0; + tk = lex(); + } + + scandirectdecl1(declinfo); + + if (nspace) + CScope_RestoreScope(&scopesave); +} + +void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual) { + TypeMemberPointer *tmemp; + TypeFunc *tfunc; + + if (tclass->flags & CLASS_FLAGS_1) { + CError_Error(191); + declinfo->thetype = (Type *) &stsignedint; + return; + } + if (tclass->sominfo) { + CError_Error(290); + declinfo->thetype = (Type *) &stsignedint; + return; + } + + tmemp = galloc(sizeof(TypeMemberPointer)); + memclrw(tmemp, sizeof(TypeMemberPointer)); + tmemp->type = TYPEMEMBERPOINTER; + tmemp->ty2 = (Type *) tclass; + tmemp->qual = qual; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + tfunc = galloc(sizeof(TypeFunc)); + *tfunc = *TYPE_FUNC(declinfo->thetype); + tmemp->ty1 = (Type *) tfunc; + tmemp->size = 12; + CDecl_MakePTMFuncType(tfunc); + } else { + tmemp->size = 4; + tmemp->ty1 = declinfo->thetype; + } + declinfo->thetype = (Type *) tmemp; +} + +void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag) { + CScopeParseResult pr; + UInt32 qual; + + while (1) { + qual = (tk == '&') ? Q_REFERENCE : 0; + + for (tk = lex(); ; tk = lex()) { + switch (tk) { + case TK_CONST: + if (qual & Q_CONST) + CError_Error(121); + qual |= Q_CONST; + continue; + case TK_VOLATILE: + if (qual & Q_VOLATILE) + CError_Error(121); + qual |= Q_VOLATILE; + continue; + case TK_RESTRICT: + if (qual & Q_RESTRICT) + CError_Error(121); + qual |= Q_RESTRICT; + continue; + default: + break; + } + break; + } + + if (IS_TYPE_REFERENCE(declinfo->thetype) || ((qual & Q_REFERENCE) && IS_TYPE_VOID(declinfo->thetype))) { + CError_Error(196); + return; + } + + if (nspace) { + makememberpointertype(declinfo, nspace->theclass, qual); + nspace = NULL; + } else { + makethetypepointer(declinfo, qual); + } + + switch (tk) { + case '*': + continue; + case '&': + if (!copts.cplusplus) { + if (flag) + scandirectdeclarator(declinfo, NULL); + return; + } + continue; + case TK_IDENTIFIER: + if (!copts.cplusplus) + break; + if (copts.cpp_extensions && cscope_current->theclass && cscope_current->theclass->classname == tkidentifier && lookahead() == TK_COLON_COLON) { + tk = lex(); + tk = lex(); + break; + } + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { + if ((nspace = pr.nspace_0)) { + if (nspace->theclass && tk == '*') + continue; + } else { + if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8) && declinfo->x30) { + if (CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace)) + scandirectdeclarator(declinfo, nspace); + else + declinfo->x20 = pr.x8; + return; + } + CError_Error(121); + } + } + break; + } + break; + } + + if (flag) + scandirectdeclarator(declinfo, nspace); +} + +static void CDecl_TemplatePTM(DeclInfo *declinfo, Type *type) { + TypeMemberPointer *tmemp = galloc(sizeof(TypeMemberPointer)); + tmemp->type = TYPEMEMBERPOINTER; + if (IS_TYPE_FUNC(declinfo->thetype)) { + CDecl_MakePTMFuncType((TypeFunc *) declinfo->thetype); + tmemp->size = 12; + } else { + tmemp->size = 4; + } + + tmemp->ty1 = declinfo->thetype; + tmemp->ty2 = type; + tmemp->qual = 0; + declinfo->thetype = (Type *) tmemp; +} + +void scandeclarator(DeclInfo *declinfo) { + CScopeParseResult pr; + NameSpace *nspace; + + switch (tk) { + case '&': + if (!copts.cplusplus) + break; + case '*': + CDecl_ScanPointer(declinfo, NULL, 1); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, declinfo); + return; + case TK_IDENTIFIER: + if (!copts.cplusplus) + break; + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { + nspace = pr.nspace_0; + if (nspace) { + if (nspace->theclass && tk == '*') + CDecl_ScanPointer(declinfo, nspace, 1); + else + scandirectdeclarator(declinfo, nspace); + return; + } + if (pr.x8 && IS_TYPE_TEMPLATE(pr.x8)) { + if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.x8, &nspace)) { + scandirectdeclarator(declinfo, nspace); + return; + } else if (declinfo->x30 && tk == TK_OPERATOR) { + declinfo->x20 = pr.x8; + return; + } else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') { + CDecl_TemplatePTM(declinfo, pr.x8); + tk = lex(); + break; + } else if (declinfo->x30) { + declinfo->x20 = pr.x8; + return; + } + } + CError_Error(121); + } + break; + } + + scandirectdeclarator(declinfo, NULL); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, declinfo); +} + +void conversion_type_name(DeclInfo *declinfo) { + CScopeParseResult pr; + DeclInfo subdeclinfo; + + memclrw(&subdeclinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&subdeclinfo, 0); + + switch (tk) { + case '&': + case '*': + CDecl_ScanPointer(&subdeclinfo, NULL, 0); + break; + case TK_IDENTIFIER: + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 0, 0)) { + if (pr.nspace_0 && pr.nspace_0->theclass && tk == '*') + CDecl_ScanPointer(&subdeclinfo, pr.nspace_0, 0); + else + CError_Error(121); + } + break; + } + + declinfo->name = subdeclinfo.name; + declinfo->thetype = subdeclinfo.thetype; + declinfo->qual |= subdeclinfo.qual; +} + +static void scaninlinefunc(Object *obj) { + short array[256]; + short r29; + CInt64 val; + + if (tk == '{') { + tk = lex(); + r29 = 0; + while (1) { + if (r29 >= 256) { + CError_Error(127); + r29 = 255; + } + val = CExpr_IntegralConstExpr(); + array[r29++] = CInt64_GetULong(&val); + if (tk != '}') { + if (tk != ',') + CError_Error(116); + tk = lex(); + } else { + tk = lex(); + break; + } + } + } else { + val = CExpr_IntegralConstExpr(); + array[0] = CInt64_GetULong(&val); + r29 = 1; + } + + obj->datatype = DINLINEFUNC; + obj->u.ifunc.size = r29 * 2; + obj->u.ifunc.data = galloc(obj->u.ifunc.size); + obj->u.ifunc.xrefs = NULL; + memcpy(obj->u.ifunc.data, array, obj->u.ifunc.size); + + if (tk != ';') + CError_Error(123); +} + +typedef enum { + OverloadMode0, + OverloadMode1, + OverloadMode2, + OverloadMode3 +} OverloadMode; + +static Object *CDecl_OverloadFunctionObject(NameSpaceObjectList *list, DeclInfo *declinfo, Boolean *outflag, OverloadMode mode, Boolean flag2) { + TypeFunc *scanfunc; + NameSpaceObjectList *scan; + TypeFunc *tfunc; + FuncArg *args; + FuncArg *scanargs; + Object *obj; + Boolean r24; + short compareresult; + + if (outflag) + *outflag = 0; + + tfunc = (TypeFunc *) declinfo->thetype; + args = tfunc->args; + r24 = 0; + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if (obj->otype != OT_OBJECT) + continue; + + scanfunc = TYPE_FUNC(obj->type); + if (!IS_TYPE_FUNC(scanfunc)) + continue; + + scanargs = scanfunc->args; + if (scanfunc->flags & FUNC_FLAGS_100000) + r24 = 1; + + if (IS_TYPEFUNC_METHOD(scanfunc)) { + switch (mode) { + case OverloadMode0: + CError_Error(197); + break; + case OverloadMode1: + if (!TYPE_METHOD(scanfunc)->x26) + continue; + break; + case OverloadMode2: + if (TYPE_METHOD(scanfunc)->x26) + continue; + break; + case OverloadMode3: + if (!TYPE_METHOD(scanfunc)->x26) { + if (scanargs->qual & (Q_CONST | Q_VOLATILE)) + continue; + scanargs = scanargs->next; + } + break; + } + } else { + if (mode) + CError_Error(197); + } + + compareresult = CParser_CompareArgLists(args, scanargs); + if (compareresult == 1) { + if (scanfunc->flags & FUNC_FLAGS_40) { + if (!(tfunc->flags & FUNC_FLAGS_40)) { + CError_Error(197); + break; + } + if (!is_typesame(tfunc->functype, scanfunc->functype)) + continue; + if ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) + continue; + if ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) { + CError_Error(197); + break; + } + if (tfunc->exspecs || scanfunc->exspecs) + CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); + return obj; + } + + if (tfunc->flags & FUNC_FLAGS_40) { + CError_Error(197); + break; + } + + if (!is_typesame(tfunc->functype, scanfunc->functype) || ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) || ((tfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (scanfunc->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))) { + CError_Error(197); + break; + } + + if (tfunc->exspecs || scanfunc->exspecs) { + if (obj->name != newp_fobj->name && obj->name != newa_fobj->name && obj->name != delp_fobj->name && obj->name != dela_fobj->name) + CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); + } + + return obj; + } else if (compareresult == 2) { + CError_Error(197); + break; + } + } + + if (r24 && (flag2 || declinfo->x3C)) { + if ((obj = CTempl_TemplateFunctionCheck(declinfo, list))) + return obj; + } + + if (!outflag) { + CError_Error(197); + return NULL; + } + + if (declinfo->nspace) + CError_Error(336); + + *outflag = 1; + obj = CParser_NewFunctionObject(declinfo); + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + + if (tfunc->flags & FUNC_FLAGS_PASCAL) { + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { + if (TYPE_FUNC(OBJECT(scan->object)->type)->flags & FUNC_FLAGS_PASCAL) + CError_Error(226); + } + } + } + + if (copts.cplusplus && declinfo->x4E) { + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_80000)) + CError_Error(197); + } + } + + CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj)); + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(cscope_current->theclass), OBJ_BASE(obj)); + + return obj; +} + +void MergeDefaultArgs(FuncArg *a, FuncArg *b) { + FuncArg *scan_a; + FuncArg *scan_b; + + if (a == &oldstyle || b == &oldstyle) + return; + + scan_a = a; + scan_b = b; + while (scan_a && scan_b) { + if (scan_a->dexpr) { + while (scan_b) { + if (scan_b->dexpr) { + while (a) { + a->dexpr = NULL; + a = a->next; + } + while (b) { + b->dexpr = NULL; + b = b->next; + } + CError_Error(205); + return; + } + scan_b = scan_b->next; + } + break; + } else if (scan_b->dexpr) { + do { + scan_a = scan_a->next; + scan_b = scan_b->next; + if (!scan_a) goto secondpart; + if (scan_a == &elipsis) goto secondpart; + if (scan_a->dexpr && scan_b->dexpr) break; + } while (scan_a->dexpr || scan_b->dexpr); + + while (a) { + a->dexpr = NULL; + a = a->next; + } + while (b) { + b->dexpr = NULL; + b = b->next; + } + CError_Error(205); + return; + } else { + scan_a = scan_a->next; + scan_b = scan_b->next; + } + } + +secondpart: + while (a && b) { + if (b->dexpr) + a->dexpr = b->dexpr; + else + b->dexpr = a->dexpr; + a = a->next; + b = b->next; + } +} + +void CheckDefaultArgs(FuncArg *args) { + FuncArg *scan; + + scan = args; + while (scan && !scan->dexpr) + scan = scan->next; + + while (scan && scan != &elipsis && scan != &oldstyle) { + if (!scan->dexpr) { + while (args) { + args->dexpr = NULL; + args = args->next; + } + CError_Error(205); + return; + } + scan = scan->next; + } +} + +static void CDecl_FuncRedeclCheck(Object *obj, DeclInfo *declinfo, Boolean flag) { + if (declinfo->storageclass == OBJECT_SCLASS_102 && obj->sclass != OBJECT_SCLASS_102) { + if (copts.cplusplus) + CError_Error(260); + else + obj->sclass = OBJECT_SCLASS_102; + } + + obj->qual |= declinfo->qual; + if (flag) + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + else + MergeDefaultArgs(TYPE_FUNC(obj->type)->args, TYPE_FUNC(declinfo->thetype)->args); + + if (!declinfo->x45) + TYPE_FUNC(obj->type)->args = TYPE_FUNC(declinfo->thetype)->args; +} + +Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag) { + Boolean r27; + Object *obj; + Type *type; + NameSpace *nspace2; + NameSpaceObjectList *list; + TypeMethod tmp; + Boolean outflag; + + r27 = 0; + if (pflag) + *pflag = 0; + + nspace2 = declinfo->nspace; + if (!nspace2) + nspace2 = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_INLINE | Q_PASCAL | Q_ASM | Q_VOLATILE | Q_CONST)); + switch (TYPE_FUNC(declinfo->thetype)->functype->type) { + case TYPEFUNC: + case TYPEARRAY: + CError_Error(128); + TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint; + break; + } + + if (nspace2->theclass) { +#line 1969 + CError_ASSERT(declinfo->name); + if (!nspace2->theclass->size) + CDecl_CompleteType((Type *) nspace2->theclass); + if (!(list = CScope_GetLocalObject(nspace2, declinfo->name))) { + CError_Error(140, declinfo->name->name); + return NULL; + } + + obj = OBJECT(list->object); + type = obj->type; + if (!IS_TYPE_FUNC(type)) { + CError_Error(249, CError_GetObjectName(obj), type, obj->qual, declinfo->thetype, declinfo->qual); + return NULL; + } + + if (declinfo->has_expltargs) + return CTempl_TemplateFunctionCheck(declinfo, list); + + if (declinfo->x3C || (list->next && list->next->object->otype == OT_OBJECT)) { + if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE)) { + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode2, someotherflag); + if (!obj) + return NULL; + } else { + obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode3, someotherflag); + if (!obj) + return NULL; + if (!TYPE_METHOD(obj->type)->x26) + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + } + } else { + if (TYPE_METHOD(type)->x26) { + if (nspace2->theclass->sominfo) + CSOM_FixNewDeleteFunctype(TYPE_FUNC(declinfo->thetype)); + } else { + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + } + + if (copts.cpp_extensions) { + declinfo->qual |= obj->qual & (Q_PASCAL | Q_CONST); + TYPE_FUNC(declinfo->thetype)->qual |= TYPE_FUNC(obj->type)->qual & (Q_PASCAL | Q_CONST); + TYPE_FUNC(declinfo->thetype)->flags |= TYPE_FUNC(obj->type)->flags & (FUNC_FLAGS_4000000 | FUNC_FLAGS_10000000); + } + + if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_PASCAL | Q_CONST)) != (obj->qual & (Q_PASCAL | Q_CONST))) { + tmp = *TYPE_METHOD(obj->type); + *(TYPE_FUNC(&tmp)) = *TYPE_FUNC(declinfo->thetype); + tmp.flags |= FUNC_FLAGS_METHOD; + CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, &tmp, declinfo->qual); + } + + if (TYPE_FUNC(declinfo->thetype)->exspecs || TYPE_FUNC(obj->type)->exspecs) + CExcept_CompareSpecifications(TYPE_FUNC(declinfo->thetype)->exspecs, TYPE_FUNC(obj->type)->exspecs); + } + + CDecl_FuncRedeclCheck(obj, declinfo, 0); + if (declinfo->x3C) { + if (obj->nspace->theclass && !(obj->nspace->theclass->flags & CLASS_FLAGS_800)) + CError_Error(335); + declinfo->x3C = 0; + } + } else { + if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_FLAGS_VOLATILE | FUNC_FLAGS_CONST)) + CError_Error(384); + + if (declinfo->x3E && !CDecl_CheckOperatorType(declinfo, 0)) + return NULL; + + list = CScope_GetLocalObject(nspace2, declinfo->name); + if (declinfo->has_expltargs) + return CTempl_TemplateFunctionCheck(declinfo, list); + + if (list) { + if (copts.cplusplus) { + obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, OverloadMode0, someotherflag); + if (!obj) + return NULL; + if (pflag) + *pflag = outflag; + if (nspace) + obj->nspace = nspace; + } else { + obj = OBJECT(list->object); + if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_CONST | Q_PASCAL)) != (obj->qual & (Q_CONST | Q_PASCAL))) { + CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); + r27 = 1; + if (!IS_TYPE_FUNC(obj->type)) + return NULL; + } + } + + if (!r27 && pflag) + CDecl_FuncRedeclCheck(obj, declinfo, *pflag); + } else { + if (declinfo->nspace) + CError_Error(336); + + if (declinfo->has_expltargs) { + if (declinfo->name) + CError_Error(140, declinfo->name->name); + else + CError_Error(127); + } + + obj = CParser_NewFunctionObject(declinfo); + if (nspace) + obj->nspace = nspace; + if (pflag) + *pflag = 1; + else + CError_Error(127); + + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + CScope_AddObject(nspace2, declinfo->name, OBJ_BASE(obj)); + } + } + + return obj; +} + +void CDecl_TypedefDeclarator(DeclInfo *declinfo) { + NameSpace *nspace; + NameSpaceObjectList *list; + ObjType *objt; + + nspace = declinfo->nspace; + if (!nspace) + nspace = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST)); + if (declinfo->x48 || declinfo->x44) + CError_Error(121); + if (declinfo->x3E) + CError_Error(193); + + objt = NULL; + list = CScope_FindName(nspace, declinfo->name); + if (list) { + switch (list->object->otype) { + case OT_TYPE: + objt = OBJ_TYPE(list->object); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_Error(321); + return; + case OT_ENUMCONST: + case OT_OBJECT: + CError_Error(322); + return; + default: +#line 2156 + CError_FATAL(); + } + } + + if (objt) { + const UInt32 mask = Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST; + if (!is_typesame(objt->type, declinfo->thetype) || (objt->qual & mask) != (declinfo->qual & mask)) { + CError_Error(249, declinfo->name->name, objt->type, objt->qual, declinfo->thetype, declinfo->qual); + } else if (!copts.cplusplus && (copts.pedantic || copts.ANSI_strict)) { + if (copts.pedantic) + CError_Warning(122, declinfo->name->name); + else + CError_Error(122, declinfo->name->name); + } + return; + } + + objt = galloc(sizeof(ObjType)); + memclrw(objt, sizeof(ObjType)); + objt->otype = OT_TYPE; + objt->access = ACCESSPUBLIC; + objt->type = declinfo->thetype; + objt->qual = declinfo->qual; + CScope_AddObject(nspace, declinfo->name, OBJ_BASE(objt)); + + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(objt)); + + if (copts.cplusplus) { + if (IS_TYPE_CLASS(declinfo->thetype) && IsTempName(TYPE_CLASS(declinfo->thetype)->classname)) { + TYPE_CLASS(declinfo->thetype)->classname = declinfo->name; + TYPE_CLASS(declinfo->thetype)->nspace->name = declinfo->name; + } + if (IS_TYPE_ENUM(declinfo->thetype) && IsTempName(TYPE_ENUM(declinfo->thetype)->enumname)) { + TYPE_ENUM(declinfo->thetype)->enumname = declinfo->name; + } + } + + if (cparamblkptr->browseOptions.recordTypedefs && declinfo->fileoffsetinfo.file->recordbrowseinfo) + CBrowse_NewTypedef(nspace, declinfo->name, declinfo->fileoffsetinfo.file, declinfo->fileoffsetinfo.tokenline, declinfo->fileoffsetinfo.tokenoffset, CPrep_BrowserFileOffset()); +} + +static void CDecl_DataDeclarator(DeclInfo *declinfo, short access, Boolean flag) { + NameSpaceObjectList *list; + Object *obj; + NameSpace *nspace; + Boolean tmpflag; + ENode *expr; + + nspace = declinfo->nspace; + if (!nspace) + nspace = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)); + if (declinfo->x48 || declinfo->x44) + CError_Error(121); + if (declinfo->x3E) + CError_Error(193); + + obj = NULL; + list = CScope_FindName(nspace, declinfo->name); + if (list) { + switch (list->object->otype) { + case OT_OBJECT: + obj = OBJECT(list->object); + if (flag) + CError_Error(122, declinfo->name->name); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_Error(321); + return; + case OT_ENUMCONST: + case OT_TYPE: + CError_Error(322); + break; + case OT_MEMBERVAR: + CError_Error(221); + break; + default: +#line 2281 + CError_FATAL(); + } + } + + if (copts.cplusplus) { + if (!flag) + CDecl_CompleteType(declinfo->thetype); + switch (declinfo->storageclass) { + case OBJECT_SCLASS_103: + if (tk == '=' || tk == '(') + declinfo->storageclass = 0; + break; + case 0: + if (CParser_IsConst(declinfo->thetype, declinfo->qual)) { + if ((!obj && !nspace->theclass) || (obj && obj->sclass != OBJECT_SCLASS_103 && !obj->nspace->theclass)) + declinfo->storageclass = OBJECT_SCLASS_102; + } + break; + } + } else { + if (declinfo->storageclass == OBJECT_SCLASS_103 && tk == '=') + declinfo->storageclass = 0; + } + + if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size && !declinfo->storageclass && tk != '=') + declinfo->storageclass = OBJECT_SCLASS_103; + + if (obj) { + if ((!obj->type->size || !declinfo->thetype->size) && IS_TYPE_ARRAY(declinfo->thetype) && IS_TYPE_ARRAY(obj->type)) + tmpflag = is_typesame(TYPE_POINTER(declinfo->thetype)->target, TYPE_POINTER(obj->type)->target); + else + tmpflag = is_typesame(declinfo->thetype, obj->type); + + if (!tmpflag || (obj->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)) != (declinfo->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST))) + CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); + + if (obj->qual & Q_10000) { + if (tk == ',' || tk == ';') + return; + CError_Error(333, obj); + } + + if (declinfo->storageclass != OBJECT_SCLASS_103) { + if (obj->sclass != OBJECT_SCLASS_103 && declinfo->storageclass && obj->sclass != declinfo->storageclass) + CError_Error(333, obj); + + if (tmpflag) { + obj->sclass = declinfo->storageclass; + obj->qual |= declinfo->qual; + if (declinfo->thetype->size) + obj->type = declinfo->thetype; + } + + CParser_UpdateObject(obj, declinfo); + } else { + flag = 1; + } + } else { + if (declinfo->nspace) + CError_Error(336); + if (IS_TYPE_CLASS(declinfo->thetype) && TYPE_CLASS(declinfo->thetype)->sominfo) + CError_Error(288); + if (!CanCreateObject(declinfo->thetype)) + declinfo->thetype = (Type *) &stsignedint; + + obj = CParser_NewGlobalDataObject(declinfo); + obj->access = access; + CScope_AddObject(nspace, declinfo->name, OBJ_BASE(obj)); + + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj)); + + if (flag && nspace->theclass && cparamblkptr->browseOptions.recordClasses) + CBrowse_AddClassMemberData(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + + if (!flag) { + if (declinfo->nspace) { + CScopeSave save; + CScope_SetNameSpaceScope(declinfo->nspace, &save); + CInit_InitializeData(obj); + CScope_RestoreScope(&save); + + if (declinfo->x3C && obj->nspace->theclass && (TYPE_CLASS(obj->nspace->theclass)->flags & CLASS_FLAGS_800)) + declinfo->x3C = 0; + } else { + CInit_InitializeData(obj); + } + + if (declinfo->fileoffsetinfo.file->recordbrowseinfo && obj->sclass != OBJECT_SCLASS_103) + CBrowse_NewData(obj, declinfo->fileoffsetinfo.file, declinfo->fileoffsetinfo.tokenline, declinfo->fileoffsetinfo.tokenoffset, CPrep_BrowserFileOffset()); + } else if (tk == '=') { + tk = lex(); + expr = CExpr_IntegralConstOrDepExpr(); + if (IS_TYPE_TEMPLATE(obj->type) || !ENODE_IS(expr, EINTCONST)) { +#line 2426 + CError_ASSERT(nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)); + CTemplClass_RegisterObjectInit(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj), expr); + } else if ((obj->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(obj->type)) { + obj->u.data.u.intconst = expr->data.intval; + obj->qual |= Q_10000 | Q_20000; + } else { + CError_Error(354, obj->name->name); + } + } +} + +Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2) { + Object *obj; + Boolean pflag; + + obj = CDecl_GetFunctionObject(declinfo, nspace, &pflag, 0); + if (obj) { + if (declinfo->x44 || tk == '{' || tk == TK_TRY || (declinfo->x4B && tk == ':') || (!copts.cplusplus && isdeclaration(0, 0, 0, 0))) { + if (!flag || cscope_currentfunc) { + CError_Error(127); + if (cscope_currentfunc) + return 0; + } + + if (obj->nspace == cscope_root && !strcmp(obj->name->name, "main")) { + if (obj->sclass == OBJECT_SCLASS_102 || (copts.ANSI_strict && TYPE_FUNC(obj->type)->functype != (Type *) &stsignedint)) + CError_Error(334); + } else if (copts.require_prototypes && (pflag || declinfo->fileoffsetinfo.is_inline)) { + if (obj->sclass != OBJECT_SCLASS_102 && !(obj->qual & Q_INLINE) && !obj->nspace->is_unnamed) + CError_Warning(178); + } + + CFunc_ParseFuncDef(obj, declinfo, NULL, 0, 0, NULL); + // WARNING: WEIRD FileOffsetInfo ALERT + if (declinfo->fileoffsetinfo.file->recordbrowseinfo) + CBrowse_NewFunction( + obj, + declinfo->fileoffsetinfo.file, + (CPrepFileInfo *) declinfo->fileoffsetinfo.tokenline, + declinfo->fileoffsetinfo.tokenoffset, + CPrep_BrowserFileOffset()); + + if (copts.cplusplus && lookahead() == ';') + tk = lex(); + return 0; + } + } + + return 1; +} + +static void CDecl_ParseSpecialMember(DeclInfo *declinfo, Boolean flag) { + Object *r28; + NameSpace *r25; + + if (!(r28 = declinfo->x10)) { +#line 2544 + CError_ASSERT(declinfo->x14); + r28 = declinfo->x14->object; +#line 2546 + CError_ASSERT(r28->otype == OT_OBJECT); + } + + if (!r28->nspace->theclass) { + CError_Error(121); + return; + } + + if (IS_TYPE_FUNC(r28->type)) { + if (TYPE_FUNC(r28->type)->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)) { + if (r28->nspace->theclass->sominfo) + declinfo->thetype = TYPE(&stvoid); + else + declinfo->thetype = TYPE(&void_ptr); + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000) + declinfo->x4B = 1; + + if ((tk = lex()) == '(') { + tk = lex(); + + r25 = cscope_current; + cscope_current = r28->nspace; + CDecl_ParseDirectFuncDecl(declinfo); + cscope_current = r25; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_1000) { + if ((r28->nspace->theclass->flags & CLASS_FLAGS_20) && !r28->nspace->theclass->sominfo) + CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); + } else { + if (!r28->nspace->theclass->sominfo) + CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); + } + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + } else { + CError_Error(121); + } + } else { + CError_Error(114); + } + return; + } else if (TYPE_FUNC(r28->type)->flags & FUNC_FLAGS_40) { +#line 2603 + CError_FATAL(); + + declinfo->thetype = TYPE_FUNC(r28->type)->functype; + declinfo->qual |= TYPE_FUNC(r28->type)->qual; + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + + if ((tk = lex()) == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + if (IS_TYPE_FUNC(declinfo->thetype)) { + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_40; + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + } else { + CError_Error(121); + } + } else { + CError_Error(114); + } + return; + } else { + declinfo->thetype = TYPE(&stsignedint); + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + + if ((tk = lex()) == '(') { + tk = lex(); + + r25 = cscope_current; + cscope_current = r28->nspace; + CDecl_ParseDirectFuncDecl(declinfo); + cscope_current = r25; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + return; + } + } else { + CError_Error(114); + } + } + } + + CError_Error(121); +} + +void CDecl_ScanDeclarator(DeclInfo *declinfo) { + if (declinfo->x14 || declinfo->x10) { + CDecl_ParseSpecialMember(declinfo, 0); + CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); + return; + } + + if (IS_TYPE_FUNC(declinfo->thetype)) { + TypeFunc *copy = galloc(sizeof(TypeFunc)); + *copy = *TYPE_FUNC(declinfo->thetype); + declinfo->thetype = TYPE(copy); + } + scandeclarator(declinfo); + if (!declinfo->name) { + CError_Error(121); + return; + } + + if (declinfo->storageclass && declinfo->storageclass != OBJECT_SCLASS_103) + CError_Error(177); + + if (IS_TYPE_FUNC(declinfo->thetype)) { + CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); + return; + } + + if (declinfo->x48 || declinfo->x44) + CError_Error(121); + + if (declinfo->x3E) + CError_Error(193); + + if ( + (declinfo->qual & ~(Q_ALIGNED_MASK | Q_OVERLOAD | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)) || + (declinfo->storageclass == OBJECT_SCLASS_104 && (declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST))) + ) + CError_Error(176); +} + +void scandeclaratorlist(DeclInfo *declinfo) { + CScopeSave savescope; + Type *r30; + UInt32 r29; + Boolean r28; + + if (declinfo->x14 || declinfo->x10) { + CDecl_ParseSpecialMember(declinfo, 1); + return; + } + + CScope_GetScope(&savescope); +#line 2707 + CError_ASSERT(declinfo->thetype); + + r28 = 1; + while (1) { + r30 = declinfo->thetype; + r29 = declinfo->qual; + declinfo->nspace = NULL; + declinfo->x3E = 0; + if (IS_TYPE_FUNC(r30)) { + declinfo->thetype = galloc(sizeof(TypeFunc)); + *TYPE_FUNC(declinfo->thetype) = *TYPE_FUNC(r30); + } + declinfo->name = NULL; + scandeclarator(declinfo); + if (!declinfo->name) { + CError_Error(121); + break; + } + + if (declinfo->storageclass != OBJECT_SCLASS_104) { + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (!CDecl_FunctionDeclarator(declinfo, NULL, r28, 1)) + return; + } else { + CDecl_DataDeclarator(declinfo, ACCESSPUBLIC, 0); + } + } else { + CDecl_TypedefDeclarator(declinfo); + } + + CScope_RestoreScope(&savescope); + declinfo->thetype = r30; + declinfo->qual = r29; + + if (tk != ',') + break; + tk = lex(); + r28 = 0; + } + + if (tk != ';') + CError_Error(123); +} + +static TypeIntegral *CDecl_FindSignedType(short size) { + if (stsignedchar.size == size) + return &stsignedchar; + if (stsignedshort.size == size) + return &stsignedshort; + if (stsignedint.size == size) + return &stsignedint; + if (stsignedlong.size == size) + return &stsignedlong; + if (copts.longlong && copts.longlong_enums && stsignedlonglong.size == size) + return &stsignedlonglong; + return &stsignedlong; +} + +static TypeIntegral *CDecl_FindUnsignedType(short size) { + if (stunsignedchar.size == size) + return &stunsignedchar; + if (stunsignedshort.size == size) + return &stunsignedshort; + if (stunsignedint.size == size) + return &stunsignedint; + if (stunsignedlong.size == size) + return &stunsignedlong; + if (copts.longlong && copts.longlong_enums && stunsignedlonglong.size == size) + return &stunsignedlonglong; + return &stunsignedlong; +} + +static TypeIntegral *CDecl_IterateIntegralEnumType(int *t) { + switch (*t) { + case 0: + *t = 1; + return &stsignedchar; + case 1: + if (stsignedshort.size > stsignedchar.size) { + *t = 2; + return &stsignedshort; + } + case 2: + if (stsignedint.size > stsignedshort.size) { + *t = 3; + return &stsignedint; + } + case 3: + if (stsignedlong.size > stsignedint.size) { + *t = 4; + return &stsignedlong; + } + case 4: + *t = 5; + if (stsignedlonglong.size > stsignedlong.size && copts.longlong && copts.longlong_enums) + return &stsignedlonglong; + default: + return NULL; + } +} + +static TypeIntegral *CDecl_IterateUIntegralEnumType(int *t) { + switch (*t) { + case 0: + *t = 1; + return &stunsignedchar; + case 1: + if (stunsignedshort.size > stunsignedchar.size) { + *t = 2; + return &stunsignedshort; + } + case 2: + if (stunsignedint.size > stunsignedshort.size) { + *t = 3; + return &stunsignedint; + } + case 3: + if (stunsignedlong.size > stunsignedint.size) { + *t = 4; + return &stunsignedlong; + } + case 4: + *t = 5; + if (stunsignedlonglong.size > stunsignedlong.size && copts.longlong && copts.longlong_enums) + return &stunsignedlonglong; + default: + return NULL; + } +} + +static TypeEnum *CDecl_OldParseEnumList(TypeEnum *tenum, HashNameNode *name) { + AccessType access; + Boolean has_template_value; + Boolean r24; + Boolean r23; + ObjEnumConst *oec; + ObjEnumConst *last; + Boolean overflowed; + CInt64 val; + CInt64 minimum; + CInt64 maximum; + CInt64 var_74; + CInt64 unused; + Type *basetype; + Type *basetype2; + CPrepFileInfo *fileinfo; + SInt32 offset; + ENode *expr; + Type *tmp; + + if (!tenum) { + tenum = galloc(sizeof(TypeEnum)); + memclrw(tenum, sizeof(TypeEnum)); + tenum->type = TYPEENUM; + tenum->nspace = cscope_current; + + if (name) { + tenum->enumname = name; + CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); + } + + if (!cscope_current->is_global) { + do { + tenum->nspace = tenum->nspace->parent; + } while (!tenum->nspace->is_global); + if (tenum->enumname) + tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); + } + } + + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) { + CTemplClass_RegisterEnumType(TEMPL_CLASS(cscope_current->theclass), tenum); + } + + access = cscope_current->theclass ? global_access : ACCESSPUBLIC; + last = NULL; + unused = cint64_zero; + val = cint64_zero; + minimum = cint64_zero; + maximum = cint64_zero; + r23 = 0; + if (copts.enumsalwaysint) { + basetype = TYPE(&stsignedint); + r24 = 1; + } else { + basetype = TYPE(&stunsignedchar); + r24 = 0; + } + + tk = lex(); + if (!copts.cplusplus || tk != '}') { + do { + if (tk != TK_IDENTIFIER) { + if (tk == '}') { + if (copts.cpp_extensions) + break; + if (!copts.warn_extracomma) + break; + } + CError_Warning(107); + break; + } + + oec = galloc(sizeof(ObjEnumConst)); + memclrw(oec, sizeof(ObjEnumConst)); + oec->otype = OT_ENUMCONST; + oec->access = access; + oec->type = TYPE(tenum); + oec->name = tkidentifier; + CPrep_BrowserFilePosition(&fileinfo, &offset); + overflowed = 0; + if ((tk = lex()) == '=') { + tk = lex(); + val = CExpr_IntegralConstExprType(&basetype2); + if (!CInt64_IsNegative(&val) || is_unsigned(basetype2)) { + if (CInt64_GreaterU(val, minimum)) { + minimum = val; + overflowed = 1; + } + } else { + if (CInt64_Less(val, maximum)) { + maximum = val; + overflowed = 1; + } + if (!r24) { + basetype = TYPE(&stsignedchar); + r24 = 1; + } + } + r23 = 0; + } else { + if (r23) + CError_Error(154); + + if (!r24 || !CInt64_IsNegative(&val)) { + if (CInt64_GreaterU(val, minimum)) { + minimum = val; + overflowed = 1; + } + } else { + if (CInt64_Less(val, maximum)) { + maximum = val; + overflowed = 1; + } + } + } + + if (copts.enumsalwaysint) { + if (copts.ANSI_strict) { + if (!CInt64_IsInRange(val, stsignedint.size)) + CError_Error(154); + } else { + if (!CInt64_IsInRange(val, stsignedint.size) && !CInt64_IsInURange(val, stunsignedint.size)) + CError_Error(154); + } + } else if (r24) { + switch (basetype->size) { + case 1: + if (CInt64_IsInRange(minimum, 1) && CInt64_IsInRange(maximum, 1)) + break; + basetype = TYPE(CDecl_FindSignedType(2)); + case 2: + if (CInt64_IsInRange(minimum, 2) && CInt64_IsInRange(maximum, 2)) + break; + basetype = TYPE(CDecl_FindSignedType(4)); + case 4: + if (CInt64_IsInRange(minimum, 4) && CInt64_IsInRange(maximum, 4)) + break; + basetype = TYPE(CDecl_FindSignedType(8)); + if (basetype->size != 8) { + if (!copts.ANSI_strict && CInt64_IsInRange(maximum, 4) && CInt64_IsInURange(minimum, 4)) + break; + if (overflowed) + CError_Error(154); + break; + } + case 8: + if (CInt64_Equal(val, minimum) && CInt64_IsNegative(&val)) + CError_Error(154); + break; + default: +#line 3071 + CError_FATAL(); + } + } else { + switch (basetype->size) { + case 1: + if (CInt64_IsInURange(minimum, 1)) + break; + basetype = TYPE(CDecl_FindUnsignedType(2)); + case 2: + if (CInt64_IsInURange(minimum, 2)) + break; + basetype = TYPE(CDecl_FindUnsignedType(4)); + case 4: + if (CInt64_IsInURange(minimum, 4)) + break; + basetype = TYPE(CDecl_FindUnsignedType(8)); + if (basetype->size != 8) { + if (overflowed) + CError_Error(154); + break; + } + case 8: + break; + default: +#line 3099 + CError_FATAL(); + } + } + + tenum->size = basetype->size; + tenum->enumtype = basetype; + oec->val = val; + CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); + + if (last) { + last->next = oec; + last = oec; + } else { + last = oec; + tenum->enumlist = oec; + } + + if (cparamblkptr->browseOptions.recordEnums) { + CPrepFileInfo *f = CPrep_BrowserCurrentFile(); + if (f->recordbrowseinfo) { + CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); + } + } + + var_74 = CInt64_Add(val, cint64_one); + if (r24) { + if (CInt64_IsNegative(&var_74) && !CInt64_IsNegative(&val)) + r23 = 1; + } else { + if (CInt64_IsZero(&var_74)) + r23 = 1; + } + val = var_74; + + if (tk != ',') + break; + tk = lex(); + } while (1); + } + + tenum->size = basetype->size; + tenum->enumtype = basetype; + + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); + + if (tk != '}') + CError_ErrorSkip(130); + else + tk = lex(); + + return tenum; +} + +static Type *CDecl_MaxType(Type *a, Type *b) { + if (a->size > b->size) + return a; + if (b->size > a->size) + return b; + if (is_unsigned(b)) + return b; + else + return a; +} + +void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum) { + ObjEnumConst *oec; + ObjEnumConst *oec2; + Type *r26; + int t; + CInt64 maximumU; + CInt64 unused; + CInt64 minimum, maximum; + + if (!copts.enumsalwaysint) { + for (oec2 = tenum->enumlist; oec2; oec2 = oec2->next) { + if (CInt64_IsNegative(&oec2->val) && !is_unsigned(oec2->type)) + break; + } + + if (oec2) { + unused = cint64_zero; + minimum = cint64_zero; + maximum = cint64_zero; + for (oec = tenum->enumlist; oec; oec = oec->next) { + if (CInt64_IsNegative(&oec->val) && !is_unsigned(oec->type)) { + if (CInt64_Less(oec->val, minimum)) + minimum = oec->val; + } else { + if (CInt64_GreaterU(oec->val, maximum)) + maximum = oec->val; + } + } + + if (CInt64_IsNegative(&maximum)) + CError_Error(154); + + t = 0; + do { + r26 = TYPE(CDecl_IterateIntegralEnumType(&t)); + if (!r26) { + r26 = TYPE(&stsignedlong); + CError_Error(154); + break; + } + + if (CInt64_IsInRange(maximum, r26->size) && CInt64_IsInRange(minimum, r26->size)) + break; + if (r26->size == stsignedlong.size && !copts.ANSI_strict && CInt64_IsInRange(minimum, r26->size) && CInt64_IsInURange(maximum, r26->size)) + break; + } while (1); + } else { + maximumU = cint64_zero; + + for (oec = tenum->enumlist; oec; oec = oec->next) { + if (CInt64_GreaterU(oec->val, maximumU)) + maximumU = oec->val; + } + + t = 0; + do { + r26 = TYPE(CDecl_IterateUIntegralEnumType(&t)); + if (!r26) { + r26 = TYPE(&stunsignedlong); + CError_Error(154); + break; + } + if (CInt64_IsInURange(maximumU, r26->size)) + break; + } while (1); + } + } else { + r26 = TYPE(&stsignedint); + } + + tenum->size = r26->size; + tenum->enumtype = r26; + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); +} + +static Type *CDecl_FindUnderlyingType(short size, CInt64 *a, CInt64 *b) { + if (CInt64_IsZero(a)) { + if (size <= stsignedchar.size && CInt64_IsInURange(*b, stunsignedchar.size)) + return TYPE(&stunsignedchar); + if (size <= stsignedshort.size && CInt64_IsInURange(*b, stunsignedshort.size)) + return TYPE(&stunsignedshort); + if (size <= stsignedint.size && CInt64_IsInURange(*b, stunsignedint.size)) + return TYPE(&stunsignedint); + if (size <= stsignedlong.size && CInt64_IsInURange(*b, stunsignedlong.size)) + return TYPE(&stunsignedlong); + if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInURange(*b, stunsignedlonglong.size)) + return TYPE(&stunsignedlonglong); + } else { + if (size <= stsignedchar.size && CInt64_IsInRange(*a, stsignedchar.size) && CInt64_IsInRange(*b, stsignedchar.size)) + return TYPE(&stsignedchar); + if (size <= stsignedshort.size && CInt64_IsInRange(*a, stsignedshort.size) && CInt64_IsInRange(*b, stsignedshort.size)) + return TYPE(&stsignedshort); + if (size <= stsignedint.size && CInt64_IsInRange(*a, stsignedint.size) && CInt64_IsInRange(*b, stsignedint.size)) + return TYPE(&stsignedint); + if (size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInRange(*b, stsignedlong.size)) + return TYPE(&stsignedlong); + if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInRange(*a, stsignedlonglong.size) && CInt64_IsInRange(*b, stsignedlonglong.size)) + return TYPE(&stsignedlonglong); + if (!copts.ANSI_strict && size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInURange(*b, stunsignedlong.size)) + return TYPE(&stsignedlong); + } + + return NULL; +} + +static TypeEnum *CDecl_ParseEnumList(TypeEnum *tenum, HashNameNode *name) { + AccessType access; + TemplClass *tmclass; + ObjEnumConst *oec; + Boolean has_template_value; + Boolean overflowed; + Boolean is_first; + CInt64 val; + CInt64 minimum; + CInt64 maximum; + CInt64 unused; + Type *basetype; + CPrepFileInfo *fileinfo; + SInt32 offset; + ENode *expr; + Type *tmp; + ObjEnumConst *last; + + if (!tenum) { + tenum = galloc(sizeof(TypeEnum)); + memclrw(tenum, sizeof(TypeEnum)); + tenum->type = TYPEENUM; + tenum->nspace = cscope_current; + + if (name) { + tenum->enumname = name; + CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); + } + + if (!cscope_current->is_global) { + do { + tenum->nspace = tenum->nspace->parent; + } while (!tenum->nspace->is_global); + if (tenum->enumname) + tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); + } + } + + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_FLAGS_100)) { + tmclass = TEMPL_CLASS(cscope_current->theclass); + CTemplClass_RegisterEnumType(tmclass, tenum); + } else { + tmclass = NULL; + } + + access = cscope_current->theclass ? global_access : ACCESSPUBLIC; + last = NULL; + is_first = 1; + has_template_value = 0; + unused = cint64_zero; + val = cint64_zero; + minimum = cint64_zero; + maximum = cint64_zero; + basetype = copts.enumsalwaysint ? TYPE(&stsignedint) : TYPE(&stsignedchar); + tenum->size = basetype->size; + tenum->enumtype = basetype; + + do { + if ((tk = lex()) != TK_IDENTIFIER) { + if (tk == '}') { + if (is_first) { + if (copts.cplusplus) + break; + } else { + if (!copts.warn_extracomma) + break; + if (copts.c9x) + break; + if (copts.cpp_extensions) + break; + } + CError_Warning(107); + } else { + CError_Error(107); + } + break; + } + + oec = galloc(sizeof(ObjEnumConst)); + memclrw(oec, sizeof(ObjEnumConst)); + oec->otype = OT_ENUMCONST; + oec->access = access; + oec->name = tkidentifier; + CPrep_BrowserFilePosition(&fileinfo, &offset); + overflowed = 0; + if ((tk = lex()) == '=') { + tk = lex(); + if (tmclass) { + expr = CExpr_IntegralConstOrDepExpr(); + if (ENODE_IS(expr, EINTCONST)) { + val = expr->data.intval; + basetype = expr->rtype; + has_template_value = 0; + } else { + val = cint64_zero; + basetype = TYPE(tenum); + CTemplClass_RegisterEnumerator(tmclass, oec, expr); + has_template_value = 1; + } + } else { + val = CExpr_IntegralConstExprType(&basetype); + has_template_value = 0; + } + } else if (has_template_value) { + CTemplClass_RegisterEnumerator(tmclass, oec, NULL); + } else if (!is_first) { + if (is_unsigned(basetype)) { + val = CInt64_Add(val, cint64_one); + if (CInt64_IsZero(&val)) + overflowed = 1; + } else if (!CInt64_IsNegative(&val)) { + val = CInt64_Add(val, cint64_one); + if (CInt64_IsNegative(&val)) + overflowed = 1; + } else { + val = CInt64_Add(val, cint64_one); + } + } + + if (!has_template_value) { + if (copts.enumsalwaysint) { + if (!CInt64_IsInRange(val, stsignedint.size) && (copts.ANSI_strict || !CInt64_IsInURange(val, stunsignedint.size))) + overflowed = 1; + basetype = TYPE(&stsignedint); + } else if (CInt64_IsNegative(&val) && !is_unsigned(basetype)) { + if (CInt64_Less(val, minimum)) { + minimum = val; + if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { + tenum->size = tmp->size; + tenum->enumtype = tmp; + } else { + overflowed = 1; + } + } + } else { + if (CInt64_GreaterU(val, maximum)) { + maximum = val; + if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { + tenum->size = tmp->size; + tenum->enumtype = tmp; + } else { + overflowed = 1; + } + } + } + } + + if (overflowed) + CError_Error(154); + + oec->val = val; + oec->type = basetype; + CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); + + if (last) { + last->next = oec; + last = oec; + } else { + last = oec; + tenum->enumlist = oec; + } + + if (cparamblkptr->browseOptions.recordEnums) { + CPrepFileInfo *f = CPrep_BrowserCurrentFile(); + if (f->recordbrowseinfo) { + CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); + } + } + + is_first = 0; + } while (tk == ','); + + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); + + if (tk != '}') + CError_ErrorSkip(130); + else + tk = lex(); + + return tenum; +} + +void scanenum(DeclInfo *declinfo) { + HashNameNode *name; + Type *type; + CScopeParseResult pr; + + if (tk == '{') { + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); + TYPE_ENUM(declinfo->thetype)->enumname = CParser_AppendUniqueNameFile("@enum"); + return; + } + + if (tk == TK_IDENTIFIER) { + name = tkidentifier; + if (lookahead() == '{') { + type = CScope_GetLocalTagType(cscope_current, name); + if (type) { + lex(); + do_shit: + if (type->size || !IS_TYPE_ENUM(type)) { + CError_Error(122, name->name); + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); + return; + } + declinfo->thetype = TYPE(CDecl_ParseEnumList(TYPE_ENUM(type), NULL)); + } else { + lex(); + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, name)); + } + + if (cparamblkptr->browseOptions.recordEnums && declinfo->fileoffsetinfo.file->recordbrowseinfo) + CBrowse_NewEnum( + cscope_current, + TYPE_ENUM(declinfo->thetype)->enumname, + declinfo->fileoffsetinfo.file, + (CPrepFileInfo *) declinfo->fileoffsetinfo.tokenline, + declinfo->fileoffsetinfo.tokenoffset, + CPrep_BrowserFileOffset()); + return; + } else { +#line 3851 + CError_ASSERT(!copts.cplusplus || tk != ';'); + tkidentifier = name; + } + } + + if (CScope_ParseElaborateName(&pr)) { + if ((type = pr.x8)) { + if (!IS_TYPE_ENUM(type)) + CError_Error(121); + if ((tk = lex()) == '{') + goto do_shit; + declinfo->thetype = type; + return; + } else { +#line 3865 + CError_ASSERT(pr.name_4); + if ((tk = lex()) == '{') { + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, pr.name_4)); + return; + } else { + CError_Error(140, pr.name_4->name); + } + } + } else { + CError_Error(121); + } + + declinfo->thetype = TYPE(&stsignedint); +} + +void CDecl_ScanStructDeclarator(BigDeclInfo *bde) { + ENode *expr; + short val; + short bits; + Boolean is_bitfield; + TypeTemplDep *ttempl; + TypeBitfield *tbitfield; + Type *type; + + bde->declinfo2 = bde->declinfo; + bde->declinfo2.name = NULL; + bde->declinfo2.x3E = 0; + bde->xCD = 0; + is_bitfield = 0; + + if (tk == ':') { + bde->declinfo2.name = no_name_node; + is_bitfield = 1; + } else { + bde->declinfo2.x50 = 1; + scandeclarator(&bde->declinfo2); + if (!bde->declinfo2.name) { + CError_Error(131); + return; + } + + if ((!copts.ANSI_strict || copts.c9x) && !bde->declinfo2.thetype->size && IS_TYPE_ARRAY(bde->declinfo2.thetype)) { + if (bde->declinfo2.storageclass != OBJECT_SCLASS_102 && bde->declinfo2.storageclass != OBJECT_SCLASS_104) { + type = TYPE_POINTER(bde->declinfo2.thetype)->target; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IsCompleteType(type)) + return; + if (tk != ';' || lookahead() != '}') { + CError_Error(145); + return; + } + } + } else { + if (bde->declinfo2.storageclass != OBJECT_SCLASS_102 && bde->declinfo2.storageclass != OBJECT_SCLASS_104) { + if (!IS_TYPE_FUNC(bde->declinfo2.thetype) && !IsCompleteType(bde->declinfo2.thetype)) + return; + } + } + + if (IS_TYPE_CLASS(bde->declinfo2.thetype) && TYPE_CLASS(bde->declinfo2.thetype)->sominfo) { + CError_Error(287); + return; + } + + if (tk != ':') + goto not_a_bitfield; + } + + if (!IS_TYPE_INT_OR_ENUM(bde->declinfo2.thetype)) { + if (CTemplTool_IsTemplateArgumentDependentType(bde->declinfo2.thetype)) + goto fuckup; + CError_Error(138); + bde->declinfo2.thetype = TYPE(&stunsignedint); + } else if (copts.ANSI_strict && !copts.cplusplus) { + if (bde->declinfo2.thetype != TYPE(&stsignedint) && bde->declinfo2.thetype != TYPE(&stunsignedint)) { + CError_Error(138); + bde->declinfo2.thetype = TYPE(&stunsignedint); + } + } + + switch (bde->declinfo2.thetype->size) { + case 1: + bits = 8; + break; + case 2: + bits = 16; + break; + case 4: + bits = 32; + break; + default: + CError_Error(138); + return; + } +fuckup: + tk = lex(); + expr = CExpr_IntegralConstOrDepExpr(); + if (!ENODE_IS(expr, EINTCONST)) { + ttempl = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_BITFIELD)); + ttempl->u.bitfield.type = bde->declinfo2.thetype; + ttempl->u.bitfield.size = CInline_CopyExpression(expr, CopyMode1); + bde->declinfo2.thetype = TYPE(ttempl); + bde->xCD = 1; + return; + } + val = CInt64_GetULong(&expr->data.intval); + if (is_bitfield) { + if (val < 0 || val > bits) { + CError_Error(138); + return; + } + } else { + if (val <= 0 || val > bits) { + CError_Error(138); + return; + } + } + + tbitfield = galloc(sizeof(TypeBitfield)); + memclrw(tbitfield, sizeof(TypeBitfield)); + tbitfield->type = TYPEBITFIELD; + tbitfield->size = bde->declinfo2.thetype->size; + tbitfield->bitfieldtype = bde->declinfo2.thetype; + tbitfield->unkB = val; + bde->declinfo2.thetype = TYPE(tbitfield); + + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, &bde->declinfo2); + +not_a_bitfield: + bde->xCD = 1; +} + +static void CDecl_LayoutStruct(TypeStruct *tstruct) { + StructMember *member; + SInt32 r28; + StructMember *innermember; + SInt32 innerbase; + StructMember *newmember; + StructMember **memberp; + TypeBitfield *bf; + SInt32 r24; + Boolean r23; + SInt32 tmp; + + r28 = 0; + r23 = 0; + CMach_StructLayoutInitOffset(0); + for (member = tstruct->members; member; member = member->next) { + if (tstruct->stype == STRUCT_TYPE_UNION) + CMach_StructLayoutInitOffset(0); + + if (IS_TYPE_BITFIELD(member->type)) + member->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(member->type), member->qual); + else + member->offset = CMach_StructLayoutGetOffset(member->type, member->qual); + + if (tstruct->stype == STRUCT_TYPE_UNION) { + tmp = CMach_StructLayoutGetCurSize(); + if (tmp > r28) + r28 = tmp; + } + + if (member->name == no_name_node) + r23 = 1; + + if (!member->name) { +#line 4064 + CError_ASSERT(IS_TYPE_STRUCT(member->type)); + innerbase = member->offset; + innermember = TYPE_STRUCT(member->type)->members; + r23 = 1; + while (innermember) { + if (ismember(tstruct, innermember->name)) + CError_Error(133, innermember->name->name); + if (r23) { + member->type = innermember->type; + member->name = innermember->name; + member->qual = innermember->qual; + member->offset = innerbase + innermember->offset; + } else { + newmember = galloc(sizeof(StructMember)); + memclrw(newmember, sizeof(StructMember)); + newmember->next = member->next; + newmember->type = innermember->type; + newmember->name = innermember->name; + newmember->qual = innermember->qual | Q_OVERLOAD; + newmember->offset = innerbase + innermember->offset; + member->next = newmember; + member = newmember; + } + if (copts.reverse_bitfields && IS_TYPE_BITFIELD(member->type)) { + bf = galloc(sizeof(TypeBitfield)); + *bf = *TYPE_BITFIELD(member->type); + CABI_ReverseBitField(bf); + member->type = TYPE(bf); + } + r23 = 0; + innermember = innermember->next; + } + r23 = 1; + } + } + + if (r23) { + memberp = &tstruct->members; + while (*memberp) { + if ((*memberp)->name == no_name_node || !(*memberp)->name) + *memberp = (*memberp)->next; + else + memberp = &(*memberp)->next; + } + } + + if (tstruct->stype == STRUCT_TYPE_UNION) + r24 = r28; + else + r24 = CMach_StructLayoutGetCurSize(); + tstruct->size = r24; + tstruct->align = CMach_GetStructAlign(tstruct); + tstruct->size = r24 + CABI_StructSizeAlignValue(TYPE(tstruct), r24); + + if (copts.reverse_bitfields) { + for (member = tstruct->members; member; member = member->next) { + if (IS_TYPE_BITFIELD(member->type)) + CABI_ReverseBitField(TYPE_BITFIELD(member->type)); + } + } + + if (copts.warn_padding && tstruct->stype != STRUCT_TYPE_UNION) { + StructMember *prev; + + member = tstruct->members; + prev = NULL; + while (member) { + if (prev && (prev->offset + prev->type->size) < member->offset) { + CError_Warning(350, member->offset - (prev->offset + prev->type->size), prev->name->name); + } + prev = member; + member = member->next; + } + + if (prev && (prev->offset + prev->type->size) < tstruct->size) { + CError_Warning(350, tstruct->size - (prev->offset + prev->type->size), prev->name->name); + } + } +} + +static SInt32 scanstructdeclarationlist(TypeStruct *tstruct, Boolean flag) { + SInt32 offset; + StructMember *member; + BigDeclInfo bde; + + offset = -1; + memclrw(&bde, sizeof(BigDeclInfo)); + + if (tk == TK_AT_DEFS) { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + CObjC_ParseDefs(tstruct); + if ((tk = lex()) != '}') + CError_Error(130); + } else { + do { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + memclrw(&bde.declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&bde.declinfo, 0); + if (bde.declinfo.storageclass || bde.declinfo.x44) { + CError_Error(131); + tstruct->members = NULL; + return -1; + } + + if (tk != ';') { + while (1) { + CDecl_ScanStructDeclarator(&bde); + if (!CanCreateObject(bde.declinfo2.thetype)) { + CError_Error(131); + bde.xCD = 0; + } + + if (bde.declinfo2.x3E) { + CError_Error(131); + bde.xCD = 0; + } + + if (bde.xCD) { + if (bde.declinfo2.name == no_name_node || !ismember(tstruct, bde.declinfo2.name)) { + member = galloc(sizeof(StructMember)); + memclrw(member, sizeof(StructMember)); + member->type = bde.declinfo2.thetype; + member->name = bde.declinfo2.name; + member->qual = bde.declinfo2.qual; + appendmember(tstruct, member); + + if (flag) { + CBrowse_AddStructMember(member, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + } else { + CError_Error(133, bde.declinfo2.name->name); + } + } + + if (tk != ',') + break; + tk = lex(); + } + } else if (!copts.ANSI_strict && IS_TYPE_STRUCT(bde.declinfo.thetype)) { + member = galloc(sizeof(StructMember)); + memclrw(member, sizeof(StructMember)); + member->type = bde.declinfo.thetype; + appendmember(tstruct, member); + } else { + CError_Error(131); + } + + if (tk != ';') { + tstruct->members = NULL; + CError_Error(123); + return -1; + } + + CPrep_TokenStreamFlush(); + } while ((tk = lex()) != '}'); + CDecl_LayoutStruct(tstruct); + } + + if (flag) { + offset = CPrep_BrowserFileOffset(); + if (tk == ';') + offset++; + } + + tk = lex(); + return offset; +} + +static TypeStruct *CDecl_DefineStruct(HashNameNode *name, short stype) { + TypeStruct *tstruct; + + tstruct = galloc(sizeof(TypeStruct)); + memclrw(tstruct, sizeof(TypeStruct)); + + tstruct->type = TYPESTRUCT; + tstruct->align = 1; + tstruct->stype = stype; + if (name) { + tstruct->name = name; + CScope_DefineTypeTag((in_func_arglist && !copts.cplusplus) ? cscope_root : cscope_current, name, (Type *) tstruct); + } + + return tstruct; +} + +void scanstruct(DeclInfo *declinfo, short structtype) { + Type *type; + HashNameNode *name; + TypeStruct typecopy; + Boolean add_to_browse; + BrowseStruct bs; + SInt32 offset; + + if (copts.cplusplus) { + CDecl_ParseClass(declinfo, structtype, 1, 0); + return; + } + + if (tk == TK_IDENTIFIER) { + name = tkidentifier; + type = CScope_GetTagType(cscope_current, name); + if (type) { + if (IS_TYPE_CLASS(type)) { + CDecl_ParseClass(declinfo, structtype, 1, 0); + return; + } + + tk = lex(); + if (!CScope_GetLocalTagType(cscope_current, name) && (tk == ';' || tk == '{')) + type = (Type *) CDecl_DefineStruct(name, structtype); + + if (!IS_TYPE_STRUCT(type) || TYPE_STRUCT(type)->stype != structtype) { + CError_Error(132, name->name); + declinfo->thetype = type; + return; + } + + if (tk != '{') { + declinfo->thetype = type; + return; + } + + if (type->size) { + CError_Error(132, name->name); + type = (Type *) CDecl_DefineStruct(NULL, structtype); + } + } else { + type = (Type *) CDecl_DefineStruct(name, structtype); + if ((tk = lex()) != '{') { + declinfo->thetype = type; + return; + } + } + } else if (tk != '{') { + CError_Error(131); + declinfo->thetype = (Type *) &stsignedint; + return; + } else { + type = (Type *) CDecl_DefineStruct(NULL, structtype); + } + + if ((add_to_browse = cparamblkptr->browseOptions.recordClasses && declinfo->fileoffsetinfo.file->recordbrowseinfo)) + CBrowse_BeginStruct(declinfo, TYPE_STRUCT(type), &bs); + + typecopy = *TYPE_STRUCT(type); + tk = lex(); + offset = scanstructdeclarationlist(&typecopy, add_to_browse); + *TYPE_STRUCT(type) = typecopy; + declinfo->thetype = type; + + if (add_to_browse) + CBrowse_EndStruct(offset, &bs); +} + +static void InlineFunctionObject(Object *obj, TypeClass *tclass) { + TStream stream; + CPrepFileInfo *file; + + obj->qual |= Q_INLINE; + TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_2; + + CPrep_StreamGetBlock(&stream, NULL, 1); + if (stream.tokens) { + if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_FLAGS_100)) { + TYPE_FUNC(obj->type)->flags |= FUNC_FLAGS_800000; + CTemplClass_DefineMember(TEMPL_CLASS(TYPE_METHOD(obj->type)->theclass), obj, &member_fileoffset, &stream); + } else { + CInline_AddInlineFunctionAction(obj, tclass, &member_fileoffset, &stream, 0); + } + } + + file = CPrep_BrowserCurrentFile(); + if (file->recordbrowseinfo) { + CBrowse_NewFunction( + obj, file, + member_fileoffset.file, + CPrep_BrowserTokenOffset(&member_fileoffset) + 1, + CPrep_BrowserFileOffset()); + } + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; +} + +void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags) { + if (flags & CLASS_EFLAGS_INTERNAL) + declinfo->exportflags |= EXPORT_FLAGS_INTERNAL; + if (flags & CLASS_EFLAGS_IMPORT) + declinfo->exportflags |= EXPORT_FLAGS_IMPORT; + if (flags & CLASS_EFLAGS_EXPORT) + declinfo->exportflags |= EXPORT_FLAGS_EXPORT; +} + +TypeMethod *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag) { + TypeMethod *method; + + method = galloc(sizeof(TypeMethod)); + memclrw(method, sizeof(TypeMethod)); + *TYPE_FUNC(method) = *tfunc; + method->theclass = tclass; + method->x26 = flag; + method->flags |= FUNC_FLAGS_METHOD; + if (!flag) + CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass); + + if ((flag || (tfunc->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000))) && (tfunc->flags & (FUNC_FLAGS_CONST | FUNC_FLAGS_VOLATILE))) + CError_Error(384); + + return method; +} + +static void CDecl_MakeFunctionVirtual(TypeClass *tclass, Object *func) { + if (is_pascal_object(func)) + CError_Error(219); + if (tclass->mode == CLASS_MODE_1) + CError_Error(352, func); + func->datatype = DVFUNC; +} + +static void CDecl_AddFunctionMember(DeclE *decle, TypeClass *tclass, DeclInfo *declinfo, short access, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { + NameSpaceObjectList *list; // r20 + Object *obj; // also r20 + TypeMethod *tfunc; // r19 + Boolean r31; + Boolean outflag; + + if (IS_TYPE_ARRAY(TYPE_FUNC(declinfo->thetype)->functype) || IS_TYPE_FUNC(TYPE_FUNC(declinfo->thetype)->functype)) { + CError_Error(128); + TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint; + } + + if (tclass->sominfo) + CSOM_CheckFuncType(TYPE_FUNC(declinfo->thetype)); + + r31 = 0; + if (declinfo->qual & Q_VIRTUAL) { + declinfo->qual &= ~Q_VIRTUAL; + r31 = 1; + flag1 = 1; + } + + if ((list = CScope_FindName(tclass->nspace, declinfo->name))) { + if (list->object->otype != OT_TYPETAG) { + if (list->object->otype != OT_OBJECT || !IS_TYPE_FUNC(OBJECT(list->object)->type)) + CError_Error(133, declinfo->name->name); + } else { + list = NULL; + } + } + + if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype))) { + tfunc = CDecl_MakeTypeMemberFunc(TYPE_FUNC(declinfo->thetype), tclass, flag4); + declinfo->thetype = (Type *) tfunc; + } else { + tfunc = TYPE_METHOD(declinfo->thetype); +#line 4579 + CError_ASSERT(!tclass->sominfo); + } + + CDecl_ExtractClassExportFlags(declinfo, tclass->eflags); + +#line 4597 + CError_ASSERT(cscope_current == tclass->nspace); + + if (list) { + obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, flag4 ? OverloadMode1 : OverloadMode2, 0); + if (!obj) + return; + if (outflag) + tfunc->x1E = ++decle->x8; + else + CError_Error(133, CError_GetObjectName(obj)); + } else { + tfunc->x1E = ++decle->x8; + obj = CParser_NewFunctionObject(declinfo); + if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(obj)); + CScope_AddObject(tclass->nspace, declinfo->name, OBJ_BASE(obj)); + } + + obj->access = access; + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + + if (flag2) { + tfunc->flags |= FUNC_FLAGS_40; + tclass->flags |= CLASS_FLAGS_40; + } + + if (r31) { + CDecl_MakeFunctionVirtual(tclass, obj); + decle->xC = 1; + } + + if ((flag1 || r31) && flag3 && (tk == '=')) { + if ((tk = lex()) == TK_INTCONST) { + if (!CInt64_IsZero(&tkintconst)) + CError_Error(121); + tfunc->flags |= FUNC_FLAGS_8; + tclass->flags |= CLASS_FLAGS_ABSTRACT; + tk = lex(); + } else { + CError_Error(121); + } + } + + if (flag3 && ((tk == '{') || (tk == TK_TRY) || ((tk == ':') && CClass_IsConstructor(obj)))) { + if (declinfo->x49) + CError_Error(127); + InlineFunctionObject(obj, NULL); + } + + if (cparamblkptr->browseOptions.recordClasses) + CBrowse_AddClassMemberFunction(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); +} + +static Boolean CDecl_IsAccessDeclaration(TypeClass *tclass, short access) { + SInt32 state; + Boolean flag; + + CPrep_TokenStreamGetState(&state); + flag = 0; + +restart: + switch (tk) { + case TK_IDENTIFIER: + if ((tk = lex()) != ';') + break; + case TK_OPERATOR: + CPrep_TokenStreamSetCurState(&state); + if (flag) { + CScope_ParseUsingDeclaration(tclass->nspace, access, 1); + return 1; + } + return 0; + default: + CPrep_TokenStreamSetCurState(&state); + return 0; + } + + switch (tk) { + case TK_COLON_COLON: + flag = 1; + tk = lex(); + goto restart; + case '<': + tk = lex(); + while (1) { + switch (tk) { + case 0: + case ';': + case '{': + case '}': + CPrep_TokenStreamSetCurState(&state); + return 0; + case '>': + if ((tk = lex()) == TK_COLON_COLON) { + flag = 1; + tk = lex(); + goto restart; + } + default: + tk = lex(); + } + } + } + + CPrep_TokenStreamSetCurState(&state); + return 0; +} + +void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo) { + packed->thetype = declinfo->thetype; + packed->qual = declinfo->qual; + packed->nspace = declinfo->nspace; + packed->name = declinfo->name; + packed->expltargs = CTemplTool_MakeGlobalTemplArgCopy(declinfo->expltargs); + packed->storageclass = declinfo->storageclass; + packed->section = declinfo->section; + packed->exportflags = declinfo->exportflags; + packed->has_expltargs = declinfo->has_expltargs; +} + +void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed) { + memclrw(declinfo, sizeof(DeclInfo)); + declinfo->thetype = packed->thetype; + declinfo->qual = packed->qual; + declinfo->nspace = packed->nspace; + declinfo->name = packed->name; + declinfo->expltargs = packed->expltargs; + declinfo->storageclass = packed->storageclass; + declinfo->section = packed->section; + declinfo->exportflags = packed->exportflags; + declinfo->has_expltargs = packed->has_expltargs; +} + +void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass) { + ClassFriend *scan; + ClassFriend *newfriend; + + if (friendfunc) { + for (scan = tclass->friends; scan; scan = scan->next) { + if (!scan->isclass && scan->u.obj == friendfunc) + break; + } + if (!scan) { + newfriend = galloc(sizeof(ClassFriend)); + memclrw(newfriend, sizeof(ClassFriend)); + newfriend->next = tclass->friends; + tclass->friends = newfriend; + newfriend->u.obj = friendfunc; + newfriend->isclass = 0; + } + } + + if (friendclass) { + for (scan = tclass->friends; scan; scan = scan->next) { + if (scan->isclass && scan->u.theclass == friendclass) + break; + } + if (!scan) { + newfriend = galloc(sizeof(ClassFriend)); + memclrw(newfriend, sizeof(ClassFriend)); + newfriend->next = tclass->friends; + tclass->friends = newfriend; + newfriend->u.theclass = friendclass; + newfriend->isclass = 1; + } + } +} + +static void CDecl_ParseFriendDecl(TypeClass *tclass) { + DeclInfo declinfo; + DeclInfo declinfo_copy; + Boolean is_templ; + Boolean r27; + Boolean pflag; + CScopeSave save; + Object *obj; + NameSpace *nspace; + + is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0; + r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION); + memclrw(&declinfo, sizeof(DeclInfo)); + + declinfo.x4C = 1; + CParser_GetDeclSpecs(&declinfo, 1); + if (declinfo.storageclass) { + CError_Error(177); + declinfo.storageclass = 0; + } + declinfo.x4C = 0; + + if (tk == ';') { + if (!r27) + CError_Error(201); + + if (IS_TYPE_CLASS(declinfo.thetype)) { + if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_FLAGS_100) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(declinfo.thetype), 1)) { + if (!is_templ) + CDecl_AddFriend(tclass, NULL, TYPE_CLASS(declinfo.thetype)); + else + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + } + } else { + if (IS_TYPE_TEMPLATE(declinfo.thetype) && is_templ) + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + else + CError_Error(201); + } + } else { + if (declinfo.x14 || declinfo.x10) { + CDecl_ParseSpecialMember(&declinfo, 0); + if (declinfo.name) { + obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); + if (obj) + CDecl_AddFriend(tclass, obj, NULL); + if (tk != ';') + CError_Error(123); + else + tk = lex(); + } + return; + } else { + nspace = CScope_FindGlobalNS(cscope_current); + declinfo_copy = declinfo; + while (1) { + declinfo = declinfo_copy; + declinfo.x4D = 1; + declinfo.x51 = 1; + scandeclarator(&declinfo); + + if (IS_TYPE_FUNC(declinfo.thetype)) { + if (!is_templ) { + CScope_SetNameSpaceScope(nspace, &save); + obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); + CScope_RestoreScope(&save); + + if (obj) { + CDecl_AddFriend(tclass, obj, NULL); + if (!declinfo.nspace && tk == '{') { + InlineFunctionObject(obj, tclass); + } else { + if (!obj->sclass) + obj->sclass = OBJECT_SCLASS_103; + } + } + } else { + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + } + } else { + CError_Error(201); + } + + if (tk != ',') + break; + tk = lex(); + } + } + } + + if (tk == ';') + tk = lex(); + else + CError_Error(123); +} + +static ObjMemberVar *CDecl_InstanceDataDeclarator(DeclE *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, short access) { + NameSpaceObjectList *list; + ObjMemberVar *ivar; + ObjMemberVar *scan; + + if (name && (list = CScope_FindName(tclass->nspace, name))) { + switch (list->object->otype) { + case OT_NAMESPACE: + CError_Error(321); + return NULL; + case OT_ENUMCONST: + case OT_TYPE: + case OT_OBJECT: + CError_Error(322); + return NULL; + case OT_MEMBERVAR: + CError_Error(122, name->name); + return NULL; + case OT_TYPETAG: + break; + default: +#line 4989 + CError_FATAL(); + } + } + + ivar = galloc(sizeof(ObjMemberVar)); + memclrw(ivar, sizeof(ObjMemberVar)); + ivar->otype = OT_MEMBERVAR; + ivar->access = access; + ivar->name = name; + ivar->type = type; + ivar->qual = qual; + if (!tclass->sominfo) + decle->x8++; + + if ((scan = tclass->ivars)) { + while (scan->next) + scan = scan->next; + scan->next = ivar; + } else { + tclass->ivars = ivar; + } + + if (name && name != no_name_node) { + CScope_AddObject(tclass->nspace, name, OBJ_BASE(ivar)); + if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(type)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(ivar)); + if (cparamblkptr->browseOptions.recordClasses) + CBrowse_AddClassMemberVar(ivar, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + + return ivar; +} + +void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass) { + if (args && args->type == TYPE(tclass)) { + if (!args->next || args->next->dexpr) { + CError_Error(239); + args->type = &stvoid; + } + } +} + +static void CDecl_ParseClassMembers(DeclE *decle, TypeClass *tclass, short mode) { + short access; + UInt32 r22; + UInt32 r21; + UInt8 r20; + Boolean r19; + UInt8 r18; + Boolean r17; + BigDeclInfo bde; + DeclInfo declinfo; + //Type *newtype + ObjMemberVar *ivar; + ObjMemberVar *scanivar; + Type *tmptype; + short t; + + r17 = (tclass->flags & CLASS_FLAGS_100) && TEMPL_CLASS(tclass)->pspec_owner; + memclrw(&bde, sizeof(BigDeclInfo)); + + if (mode == CLASS_MODE_2) + access = ACCESSPRIVATE; + else + access = ACCESSPUBLIC; + global_access = access; + //global_access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC; + //access = (mode == CLASS_MODE_2) ? ACCESSPRIVATE : ACCESSPUBLIC; + + restart: + while (tk != '}') { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + r21 = 0; + r22 = 0; + r20 = 0; + r18 = 0; + + if (tk == TK_TEMPLATE) { + NameSpace *nspace = cscope_current; + TemplClass *tmclass; + + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) { + tmclass = TEMPL_CLASS(nspace->theclass); + } else { + for (; nspace; nspace = nspace->parent) { + if (!nspace->name && !nspace->theclass && nspace->parent && !nspace->is_templ) { + CError_Error(347); + break; + } + } + } + + CTempl_Parse(tclass, access); + tk = lex(); + continue; + } + + restart2: + r19 = 0; + switch (tk) { + case TK_UU_DECLSPEC: + if ((tk = lex()) != '(') + CError_Error(114); + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_ParseDeclSpec(&declinfo, 1); + r21 |= declinfo.qual; + r20 |= declinfo.exportflags; + r18 = declinfo.section; + if ((tk = lex()) != ')') + CError_Error(115); + tk = lex(); + goto restart2; + case TK_PRIVATE: + global_access = access = ACCESSPRIVATE; + goto check_access; + case TK_PROTECTED: + global_access = access = ACCESSPROTECTED; + goto check_access; + case TK_PUBLIC: + global_access = access = ACCESSPUBLIC; + check_access: + if (r22 || r20) + CError_Error(121); + if ((tk = lex()) != ':') + CError_Error(170); + else + tk = lex(); + goto restart; + case TK_EXPLICIT: + CError_QualifierCheck(r22 & Q_EXPLICIT); + r22 |= Q_EXPLICIT; + tk = lex(); + goto restart2; + case TK_INLINE: + CError_QualifierCheck(r22 & Q_INLINE); + r22 |= Q_INLINE; + tk = lex(); + goto restart2; + case TK_ASM: + CError_QualifierCheck(r22 & Q_ASM); + r22 |= Q_ASM; + tk = lex(); + goto restart2; + case TK_VIRTUAL: + CError_QualifierCheck(r22 & Q_VIRTUAL); + r22 |= Q_VIRTUAL; + tk = lex(); + goto restart2; + case TK_IDENTIFIER: + while (1) { + if (tkidentifier == tclass->classname) { + t = lookahead(); + tkidentifier = tclass->classname; + r19 = 1; + if (copts.cpp_extensions && t == TK_COLON_COLON) { + lex(); + tk = lex(); + if (tk == TK_IDENTIFIER) + continue; + if (tk == '~') + goto restart2; + CError_Error(107); + } + + if (t == '(') { + redo_thing: + CError_QualifierCheck(r22 & ~(Q_EXPLICIT | Q_INLINE | Q_ASM)); + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + if (tclass->sominfo) + bde.declinfo2.thetype = &stvoid; + else + bde.declinfo2.thetype = TYPE(&void_ptr); + + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + bde.declinfo2.x4B = 1; + scandeclarator(&bde.declinfo2); + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + if (r17) + bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(tclass, bde.declinfo2.thetype, &bde.declinfo2.qual); + if (tclass->sominfo) { + if (TYPE_FUNC(bde.declinfo2.thetype)->args) + CError_Error(272); + bde.declinfo2.qual |= Q_VIRTUAL; + } else { + CDecl_CheckCtorIntegrity(TYPE_FUNC(bde.declinfo2.thetype)->args, tclass); + if (tclass->flags & CLASS_FLAGS_20) + CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); + bde.declinfo2.qual &= ~Q_VIRTUAL; + } + TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_1000; + bde.declinfo2.name = constructor_name_node; + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 0); + } else { + CError_Error(241); + } + if (tk == ';') + tk = lex(); + else + CError_Error(123); + goto restart; + } + } + // 6F8D8 + if (!r22 && CDecl_IsAccessDeclaration(tclass, access)) { + tk = lex(); + goto restart; + } + break; + } + break; + case TK_USING: + CError_QualifierCheck(r22); + tk = lex(); + CScope_ParseUsingDeclaration(tclass->nspace, access, 0); + tk = lex(); + goto restart; + case '~': + if ((tk = lex()) != TK_IDENTIFIER || tkidentifier != tclass->classname) { + CError_Error(241); + goto restart; + } + CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); + if (tclass->flags & CLASS_FLAGS_900) { + t = lookahead(); + tkidentifier = tclass->classname; + if (t == '<') { + memclrw(&bde.declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&bde.declinfo, 0); + if (tk != '(' || bde.declinfo.thetype != TYPE(tclass) || bde.declinfo.nspace) { + CError_Error(241); + goto restart; + } + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass->classname; + } + } + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + if (tclass->sominfo) + bde.declinfo2.thetype = &stvoid; + else + bde.declinfo2.thetype = TYPE(&void_ptr); + scandeclarator(&bde.declinfo2); + if (IS_TYPE_FUNC(bde.declinfo2.thetype) && !TYPE_FUNC(bde.declinfo2.thetype)->args) { + if (!CScope_FindName(tclass->nspace, destructor_name_node)) { + if (tclass->sominfo) + bde.declinfo2.qual |= Q_VIRTUAL; + else + CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); + bde.declinfo2.name = destructor_name_node; + TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_FLAGS_2000; + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); + } else { + CError_Error(133, CError_GetFunctionName(tclass->nspace, destructor_name_node, NULL)); + } + } else { + CError_Error(146); + } + if (tk == ';') + tk = lex(); + else + CError_Error(123); + goto restart; + case TK_OPERATOR: + if (CMangler_OperatorName(lookahead())) { + memclrw(&bde.declinfo, sizeof(DeclInfo)); + bde.declinfo.thetype = TYPE(&stsignedint); + goto after_various_things; + } else { + tk = lex(); + CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + conversion_type_name(&bde.declinfo2); + bde.declinfo2.qual |= r21; + tmptype = bde.declinfo2.thetype; + CDecl_NewConvFuncType(&bde.declinfo2); + if ((tclass->flags & CLASS_FLAGS_100) && CTemplTool_IsTemplateArgumentDependentType(tmptype)) + bde.declinfo2.name = CParser_GetUniqueName(); + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 1, 1, 0); + if (tk == ';') + tk = lex(); + else + CError_Error(123); + goto restart; + } + case TK_FRIEND: + tk = lex(); + CDecl_ParseFriendDecl(tclass); + goto restart; + } + + CError_QualifierCheck(r22 & Q_EXPLICIT); + global_access = access; + memclrw(&bde.declinfo, sizeof(DeclInfo)); + bde.declinfo.qual = r22; + bde.declinfo.exportflags = r20; + bde.declinfo.section = r18; + CParser_GetDeclSpecs(&bde.declinfo, 0); + + if (r19 && tk == '(' && (tclass->flags & CLASS_FLAGS_900) && bde.declinfo.thetype == TYPE(tclass) && !bde.declinfo.nspace) { + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass->classname; + r22 = bde.declinfo.qual; + goto redo_thing; + } + + after_various_things: + switch (bde.declinfo.storageclass) { + case 0: + case OBJECT_SCLASS_102: + case OBJECT_SCLASS_104: + case OBJECT_SCLASS_12B: + break; + default: + CError_Error(177); + bde.declinfo.storageclass = 0; + } + + if (tk != ';') { + while (1) { + CDecl_ScanStructDeclarator(&bde); + if (r17) + bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(tclass, bde.declinfo2.thetype, &bde.declinfo2.qual); + if (bde.declinfo2.nspace) + CError_Error(200); + if (bde.declinfo2.x3E) { + if (bde.declinfo.storageclass == OBJECT_SCLASS_12B) + CError_QualifierCheck(Q_MUTABLE); + r19 = 0; + switch (bde.declinfo2.x3E) { + case TK_NEW: + case TK_NEW_ARRAY: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + r19 = 1; + break; + case TK_DELETE: + case TK_DELETE_ARRAY: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + r19 = 1; + break; + default: + if (bde.declinfo2.storageclass == OBJECT_SCLASS_102) + CError_Error(193); + if (tclass->sominfo) + CError_Error(193); + } + + bde.declinfo2.storageclass = 0; + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, r19 == 0, 0, 1, r19); + CDecl_CheckOperatorType(&bde.declinfo2, 1); + if (tclass->sominfo) + CSOM_FixNewDeleteFunctype(TYPE_FUNC(bde.declinfo2.thetype)); + } else { + CError_Error(121); + } + } else if (bde.xCD) { + if (bde.declinfo2.name == constructor_name_node || bde.declinfo2.name == destructor_name_node) + CError_Error(241); + switch (bde.declinfo2.storageclass) { + case OBJECT_SCLASS_104: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + CDecl_TypedefDeclarator(&bde.declinfo2); + break; + case OBJECT_SCLASS_102: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + if (tclass->sominfo) + CError_Error(271); + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + bde.declinfo2.qual |= r21; + bde.declinfo2.storageclass = 0; + if (bde.declinfo2.name == tclass->classname) + CError_Error(241); + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 1); + } else { + CDecl_ExtractClassExportFlags(&bde.declinfo2, tclass->eflags); + bde.declinfo2.storageclass = 0; + CDecl_DataDeclarator(&bde.declinfo2, access, 1); + } + break; + case 0: + case OBJECT_SCLASS_12B: + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + if (bde.declinfo2.name == tclass->classname) + CError_Error(241); + if (bde.declinfo.storageclass == OBJECT_SCLASS_12B) + CError_QualifierCheck(Q_MUTABLE); + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); + } else { + CDecl_CompleteType(bde.declinfo2.thetype); + CanCreateObject(bde.declinfo2.thetype); + CError_QualifierCheck(bde.declinfo2.qual & (Q_VIRTUAL | Q_INLINE)); + if (bde.declinfo2.storageclass == OBJECT_SCLASS_12B) + bde.declinfo2.qual |= Q_MUTABLE; + CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo2.thetype, bde.declinfo2.qual, bde.declinfo2.name, access); + } + break; + default: + CError_Error(177); + } + } + + // this should be 70058 + if (tk != ',') + break; // goes to 70148 + tk = lex(); + } + } else if (CParser_IsAnonymousUnion(&bde.declinfo, 1)) { + if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo.thetype, 0, NULL, access))) + ivar->anonunion = 1; + for (scanivar = TYPE_CLASS(bde.declinfo.thetype)->ivars; scanivar; scanivar = scanivar->next) { + tmptype = scanivar->type; + if (IS_TYPE_BITFIELD(tmptype) && copts.reverse_bitfields) { + TypeBitfield *newtype = galloc(sizeof(TypeBitfield)); + *newtype = *TYPE_BITFIELD(tmptype); + CABI_ReverseBitField(newtype); + tmptype = TYPE(newtype); + } + if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, tmptype, scanivar->qual, scanivar->name, access))) + ivar->offset = scanivar->offset | 0x80000000; + } + } + + // this should be 70148 i think + if (tk != ';') { + CError_Error(123); + return; + } + CPrep_TokenStreamFlush(); + tk = lex(); + } +} + +static VClassList *AddVBaseToList(TypeClass *tclass, TypeClass *baseclass) { + VClassList *scan; + VClassList *vbase; + + for (scan = tclass->vbases; scan; scan = scan->next) { + if (scan->base == baseclass) + return NULL; + } + + vbase = galloc(sizeof(VClassList)); + memclrw(vbase, sizeof(VClassList)); + vbase->base = baseclass; + + if ((scan = tclass->vbases)) { + while (scan->next) + scan = scan->next; + scan->next = vbase; + } else { + tclass->vbases = vbase; + } + + return vbase; +} + +void CDecl_MakeVBaseList(TypeClass *tclass) { + ClassList *base; + VClassList *vbase; + VClassList *new_vbase; + SInt32 offset; + + if (copts.vbase_ctor_offset) + tclass->flags |= CLASS_FLAGS_8000; + + for (base = tclass->bases, offset = tclass->size; base; base = base->next) { + for (vbase = base->base->vbases; vbase; vbase = vbase->next) { + if ((new_vbase = AddVBaseToList(tclass, vbase->base))) { + new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(vbase->base), offset); + offset = new_vbase->offset + vbase->base->size; + } + } + + if (base->is_virtual && (new_vbase = AddVBaseToList(tclass, base->base))) { + new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(base->base), offset); + offset = new_vbase->offset + base->base->size; + } + } +} + +Boolean CDecl_CheckNewBase(TypeClass *tclass, TypeClass *baseclass, Boolean is_virtual) { + ClassList *scan; + + if (tclass == baseclass) { + CError_Error(131); + return 0; + } + + if (!(baseclass->flags & CLASS_FLAGS_2)) { + CError_Error(136, baseclass, 0); + return 0; + } + + if (baseclass->flags & CLASS_FLAGS_10) { + if (is_virtual || tclass->bases) { + CError_Error(191); + return 0; + } + tclass->flags |= CLASS_FLAGS_10; + } + + if (baseclass->flags & CLASS_FLAGS_1) { + if (is_virtual || tclass->bases) { + CError_Error(191); + return 0; + } + tclass->flags |= CLASS_FLAGS_1; + } + + if (baseclass->sominfo) { + if (!is_virtual) + CError_Error(268); + CSOM_MakeSOMClass(tclass); + } else if (tclass->sominfo) { + CError_Error(267); + } + + if (tclass->bases && (tclass->flags & CLASS_FLAGS_10) && (tclass->flags & CLASS_FLAGS_10)) { + CError_Error(131); + return 0; + } + + if (copts.ecplusplus && (is_virtual || tclass->bases)) { + CError_Error(339); + return 0; + } + + for (scan = tclass->bases; scan; scan = scan->next) { + if (scan->base == baseclass) { + CError_Error(131); + return 0; + } + } + + if (baseclass->flags & CLASS_FLAGS_2000) + tclass->flags |= CLASS_FLAGS_2000; + if (baseclass->flags & CLASS_FLAGS_40) + tclass->flags |= CLASS_FLAGS_40; + if (baseclass->flags & CLASS_FLAGS_20) + tclass->flags |= CLASS_FLAGS_20; + + if (is_virtual) + tclass->flags |= CLASS_FLAGS_20; + + return 1; +} + +static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) { + Boolean is_virtual; + short access; + CScopeParseResult pr; + ObjType *inherited_type; + ClassList *base; + ClassList *scan; + TypeClass *baseclass; + + do { + if (mode == CLASS_MODE_2) + access = ACCESSPRIVATE; + else + access = ACCESSPUBLIC; + + is_virtual = 0; + if ((tk = lex()) == TK_VIRTUAL) { + tk = lex(); + is_virtual = 1; + } + + switch (tk) { + case TK_PRIVATE: + access = ACCESSPRIVATE; + tk = lex(); + break; + case TK_PUBLIC: + access = ACCESSPUBLIC; + tk = lex(); + break; + case TK_PROTECTED: + if (!copts.ARM_conform) { + access = ACCESSPROTECTED; + tk = lex(); + } + break; + } + + if (tk == TK_VIRTUAL) { + if (is_virtual) + CError_Error(121); + is_virtual = 1; + tk = lex(); + } + + if (CScope_ParseDeclName(&pr)) { + if (!pr.x8) { + if (!pr.name_4) { + CError_Error(121); + } else if (tk == TK_IDENTIFIER && pr.name_4 == tkidentifier) { + goto special_parsing; + } + CError_Error(140, tkidentifier->name); + continue; + } + + CDecl_CompleteType(pr.x8); + if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.x8)) { + if (!IS_TYPE_CLASS(pr.x8) || !(TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100) || + CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 1)) { + CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.x8, access, is_virtual); + if (is_virtual) + tclass->flags |= CLASS_FLAGS_20; + } + continue; + } + + if (!IS_TYPE_CLASS(pr.x8) || (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) { + CError_Error(131); + continue; + } + baseclass = TYPE_CLASS(pr.x8); + } else { + special_parsing: + if (!strcmp(tkidentifier->name, "HandleObject")) { + if (tclass->bases) + CError_Error(191); + tclass->flags |= CLASS_FLAGS_10 | CLASS_FLAGS_1; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) { + if (tclass->bases) + CError_Error(191); + tclass->flags |= CLASS_FLAGS_10; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__comobject")) { + tclass->flags |= CLASS_FLAGS_2000; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__somobject")) { + if (!is_virtual) + CError_Error(268); + CSOM_MakeSOMClass(tclass); + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__javaobject")) { + tk = lex(); + tclass->action = CLASS_ACTION_3; + break; + } + + CError_Error(140, tkidentifier->name); + continue; + } + + if (CDecl_CheckNewBase(tclass, baseclass, is_virtual)) { + base = galloc(sizeof(ClassList)); + memclrw(base, sizeof(ClassList)); + base->base = baseclass; + base->access = access; + base->is_virtual = is_virtual; + if ((scan = tclass->bases)) { + while (scan->next) + scan = scan->next; + scan->next = base; + } else { + tclass->bases = base; + } + } + } while ((tk = lex()) == ','); + + if (tclass->flags & CLASS_FLAGS_20) + CDecl_MakeVBaseList(tclass); + + if (copts.def_inherited && tclass->bases && !tclass->bases->next) { + inherited_type = galloc(sizeof(ObjType)); + memclrw(inherited_type, sizeof(ObjType)); + inherited_type->otype = OT_TYPE; + inherited_type->access = ACCESSPUBLIC; + inherited_type->type = TYPE(tclass->bases->base); + CScope_AddObject(tclass->nspace, GetHashNameNodeExport("inherited"), OBJ_BASE(inherited_type)); + } +} + +static short getaccesstype(short a, short b, short c) { + AccessType a1 = (AccessType) a; + AccessType b1 = (AccessType) b; + AccessType c1 = (AccessType) c; + + if (a1 == ACCESSNONE || b1 == ACCESSNONE || b1 == ACCESSPRIVATE) + return ACCESSNONE; + else if (c1 == ACCESSPUBLIC && a1 != ACCESSPUBLIC) + return ACCESSNONE; + else + return ACCESSPUBLIC; +} + +static TypeMethod *CDecl_MakeDefaultCtorType(TypeClass *tclass) { + TypeMethod *tmeth = galloc(sizeof(TypeMethod)); + memclrw(tmeth, sizeof(TypeMethod)); + tmeth->type = TYPEFUNC; + tmeth->functype = TYPE(&void_ptr); + tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + if (tclass->flags & CLASS_FLAGS_20) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefArgConstructor(TypeClass *tclass) { + // empty +} + +static void CDecl_AddMemberFunctionObject(TypeClass *tclass, HashNameNode *name, TypeMethod *tmeth, short access) { + Object *obj = CParser_NewCompilerDefFunctionObject(); + obj->name = name; + obj->type = TYPE(tmeth); + obj->qual = Q_80000; + obj->access = access; + obj->nspace = tclass->nspace; + obj->qual |= Q_INLINE; + CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj)); +} + +static void CDecl_AddDefaultConstructor(DeclE *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + Boolean has_ctor; + + if (CClass_Constructor(tclass)) { + CDecl_AddDefArgConstructor(tclass); + return; + } + + has_ctor = 0; + + if (tclass->flags & CLASS_FLAGS_20) + has_ctor = 1; + if (decle->xC) + has_ctor = 1; + + for (base = tclass->bases; base; base = base->next) { + if (CClass_Constructor(base->base)) + has_ctor = 1; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) + has_ctor = 1; + } + + if (has_ctor) { + CDecl_AddMemberFunctionObject( + tclass, + constructor_name_node, + CDecl_MakeDefaultCtorType(tclass), + ACCESSPUBLIC + ); + } +} + +static TypeMethod *CDecl_MakeCopyCtorType(TypeClass *tclass, Boolean is_const) { + FuncArg *arg; + TypeMethod *tmeth = galloc(sizeof(TypeMethod)); + memclrw(tmeth, sizeof(TypeMethod)); + tmeth->type = TYPEFUNC; + tmeth->functype = TYPE(&void_ptr); + tmeth->flags = FUNC_FLAGS_1000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + arg = CParser_NewFuncArg(); + if (is_const) + arg->qual = Q_CONST; + arg->type = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->args = arg; + + if (tclass->flags & CLASS_FLAGS_20) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultCopyConstructor(DeclE *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + short access; + Boolean has_copyctor; + Boolean is_const; + FuncArg *arg; + + if (CClass_CopyConstructor(tclass)) + return; + + access = ACCESSPUBLIC; + is_const = 1; + has_copyctor = 0; + + if (CClass_Constructor(tclass)) + has_copyctor = 1; + if ((tclass->flags & CLASS_FLAGS_20) || decle->xC) + has_copyctor = 1; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_CopyConstructor(base->base))) { + has_copyctor = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + arg = TYPE_FUNC(obj->type)->args->next; + if (base->base->flags & CLASS_FLAGS_20) + arg = arg->next; + if (!(arg->qual & Q_CONST)) + is_const = 0; + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_CopyConstructor(TYPE_CLASS(type)))) { + has_copyctor = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + arg = TYPE_FUNC(obj->type)->args->next; + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_20) + arg = arg->next; + if (!(arg->qual & Q_CONST)) + is_const = 0; + } + } + + if (has_copyctor) { + CDecl_AddMemberFunctionObject( + tclass, + constructor_name_node, + CDecl_MakeCopyCtorType(tclass, is_const), + access + ); + } +} + +static TypeMethod *CDecl_MakeAssignmentOperatorType(TypeClass *tclass, Boolean is_const) { + FuncArg *arg; + TypeMethod *tmeth = galloc(sizeof(TypeMethod)); + memclrw(tmeth, sizeof(TypeMethod)); + tmeth->type = TYPEFUNC; + tmeth->functype = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->flags = FUNC_FLAGS_100 | FUNC_FLAGS_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + arg = CParser_NewFuncArg(); + if (is_const) + arg->qual = Q_CONST; + arg->type = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->args = arg; + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultAssignmentOperator(DeclE *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + short access; + Boolean is_const; + Boolean has_ass; + DeclInfo declinfo; + + is_const = 1; + has_ass = 0; + access = ACCESSPUBLIC; + + if (!CClass_AssignmentOperator(tclass)) { + if (!copts.old_argmatch) + has_ass = 1; + + if ((tclass->flags & CLASS_FLAGS_20) || decle->xC || CClass_MemberObject(tclass, asop_name_node)) + has_ass = 1; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_AssignmentOperator(base->base))) { + has_ass = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) + is_const = 0; + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_AssignmentOperator(TYPE_CLASS(type)))) { + has_ass = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) + is_const = 0; + } + } + } + + if (has_ass) { + memclrw(&declinfo, sizeof(DeclInfo)); + declinfo.qual |= Q_INLINE; + declinfo.thetype = (Type *) CDecl_MakeAssignmentOperatorType(tclass, is_const); + declinfo.name = asop_name_node; + CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); + } +} + +TypeMethod *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual) { + TypeMethod *tmeth = galloc(sizeof(TypeMethod)); + memclrw(tmeth, sizeof(TypeMethod)); + tmeth->type = TYPEFUNC; + tmeth->functype = (Type *) &void_ptr; + tmeth->flags = FUNC_FLAGS_2000 | FUNC_FLAGS_100 | FUNC_FLAGS_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + if (is_virtual) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultDestructor(DeclE *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + short access; + Boolean has_dtor; + Boolean is_virtual; + DeclInfo declinfo; + + if (CClass_Destructor(tclass)) + return; + + has_dtor = 0; + is_virtual = 0; + access = ACCESSPUBLIC; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_Destructor(base->base))) { + has_dtor = 1; + if (obj->datatype == DVFUNC) + is_virtual = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_Destructor(TYPE_CLASS(type)))) { + has_dtor = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + } + } + + if (has_dtor) { + memclrw(&declinfo, sizeof(DeclInfo)); + declinfo.qual |= Q_INLINE; + if (is_virtual) + declinfo.qual |= Q_VIRTUAL; + + declinfo.thetype = (Type *) CDecl_MakeDefaultDtorType(tclass, 1); + declinfo.name = destructor_name_node; + CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); + } +} + +static void CDecl_SetupClassLayout(DeclE *decle, TypeClass *tclass, ObjBase **objbuf) { + SInt32 index; + SInt32 i; + Object *obj; + CScopeObjectIterator iter; + ObjMemberVar *ivar; + SInt32 bufsize; + + if (decle->x8 > 32) { + bufsize = decle->x8 * sizeof(ObjBase *); + objbuf = lalloc(bufsize); + } else { + bufsize = 32 * sizeof(ObjBase *); + } + memclrw(objbuf, bufsize); + decle->objlist = objbuf; + + CScope_InitObjectIterator(&iter, tclass->nspace); + index = 0; + while (1) { + obj = OBJECT(CScope_NextObjectIteratorObject(&iter)); + if (!obj) break; + + if (!IS_TYPE_FUNC(obj->type)) + continue; + if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type))) + continue; + if (obj->datatype == DALIAS) + continue; + + i = TYPE_METHOD(obj->type)->x1E; + if (i > 0) { +#line 6363 + CError_ASSERT((i - 1) < decle->x8 && !objbuf[(int) (i - 1)]); + objbuf[(int) (i - 1)] = OBJ_BASE(obj); + index++; + if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->x26 && CClass_OverridesBaseMember(tclass, obj->name, obj)) + CDecl_MakeFunctionVirtual(tclass, obj); + + if (obj->datatype == DVFUNC) { + decle->xC = 1; + if (!tclass->vtable) { + CABI_AddVTable(tclass); + decle->xA = i - 1; + } else { + if ((i - 1) < decle->xA) + decle->xA = i - 1; + } + } else if (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_8) { + CError_Error(351, obj); + TYPE_FUNC(obj->type)->flags &= ~FUNC_FLAGS_8; + } + } else { +#line 6412 + CError_ASSERT(i == 0); + } + + if (!tclass->sominfo) + TYPE_METHOD(obj->type)->x1E = 0; + } + + if (!tclass->action) { + for (i = 0; i < decle->x8; i++) { + Object *obj2 = OBJECT(objbuf[i]); + if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_FLAGS_8)) { + tclass->action = CLASS_ACTION_1; + TYPE_FUNC(obj2->type)->flags |= FUNC_FLAGS_4; + break; + } + } + } + + if (!tclass->sominfo) { + for (i = 0, ivar = tclass->ivars; i < decle->x8; i++) { + if (!objbuf[i]) { +#line 6449 + CError_ASSERT(ivar); + objbuf[i] = OBJ_BASE(ivar); + ivar = ivar->next; + index++; + } + } +#line 6455 + CError_ASSERT(ivar == NULL); + } + +#line 6458 + CError_ASSERT(index == decle->x8); +} + +void CDecl_CompleteClass(DeclE *decle, TypeClass *tclass) { + ClassList *base; + ObjBase *buf[32]; + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable) + decle->xC = 1; + } + + if (!tclass->sominfo) { + CDecl_AddDefaultDestructor(decle, tclass); + CDecl_AddDefaultAssignmentOperator(decle, tclass); + CDecl_AddDefaultConstructor(decle, tclass); + CDecl_AddDefaultCopyConstructor(decle, tclass); + } + + CDecl_SetupClassLayout(decle, tclass, buf); + if (decle->xC) + CClass_CheckOverrides(tclass); + CABI_LayoutClass(decle, tclass); + if (tclass->sominfo) + CSOM_ClassComplete(tclass); + + if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->x47) + tclass->action = CLASS_ACTION_0; + + if (!tclass->action) + CClass_MakeStaticActionClass(tclass); + CClass_ClassDefaultFuncAction(tclass); +} + +TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3) { + NameSpace *mynspace; + ObjType *objtype; + + if (!tclass && nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) { +#line 6556 + CError_ASSERT(!flag2); + return CTemplClass_DefineNestedClass(TEMPL_CLASS(nspace->theclass), name, mode); + } + + mynspace = CScope_NewListNameSpace(name, 1); + if (!tclass) { + tclass = galloc(sizeof(TypeClass)); + memclrw(tclass, sizeof(TypeClass)); + } + + tclass->type = TYPECLASS; + tclass->align = 1; + tclass->mode = mode; + tclass->action = CLASS_ACTION_0; + if (name) { + tclass->classname = name; + if (flag3) { + if (flag2) { + objtype = galloc(sizeof(ObjType)); + memclrw(objtype, sizeof(ObjType)); + objtype->otype = OT_TYPE; + objtype->access = ACCESSPUBLIC; + objtype->type = (Type *) tclass; + CScope_AddObject(nspace, name, OBJ_BASE(objtype)); + } else { + CScope_DefineTypeTag(nspace, name, (Type *) tclass); + } + } + CScope_DefineTypeTag(mynspace, name, (Type *) tclass); + + if (cscope_currentfunc) + mynspace->name = CParser_AppendUniqueNameFile(name->name); + + if (copts.direct_to_som && nspace == cscope_root && !strcmp(name->name, "SOMObject")) + CSOM_MakeSOMClass(tclass); + } else { + tclass->classname = CParser_AppendUniqueNameFile("@class"); + mynspace->name = tclass->classname; + } + + tclass->nspace = mynspace; + mynspace->theclass = tclass; + mynspace->parent = nspace; + if (!nspace->is_global) + CParser_RegisterNonGlobalClass(tclass); + + return tclass; +} + +void CDecl_ParseClassDeclSpec(UInt8 *declspec) { + DeclInfo declinfo; + + if ((tk = lex()) == '(') { + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_ParseDeclSpec(&declinfo, 1); + if (declinfo.exportflags & EXPORT_FLAGS_INTERNAL) + *declspec |= CLASS_EFLAGS_INTERNAL; + if (declinfo.exportflags & EXPORT_FLAGS_IMPORT) + *declspec |= CLASS_EFLAGS_IMPORT; + if (declinfo.exportflags & EXPORT_FLAGS_EXPORT) + *declspec |= CLASS_EFLAGS_EXPORT; + if ((tk = lex()) != ')') + CError_Error(115); + else + tk = lex(); + } else { + CError_Error(114); + } +} + +static TemplClass *CDecl_SpecializeTemplateClass(TemplClass *tmclass) { + tmclass->theclass.nspace->names = 0; + tmclass->theclass.nspace->data.list = NULL; + tmclass->theclass.ivars = NULL; + tmclass->theclass.bases = NULL; + tmclass->theclass.vbases = NULL; + tmclass->theclass.friends = NULL; + tmclass->theclass.vtable = NULL; + tmclass->members = NULL; + tmclass->instances = NULL; + tmclass->pspec_owner = NULL; + tmclass->pspecs = NULL; + tmclass->actions = NULL; + tmclass->lex_order_count = 0; + tmclass->align = 0; + tmclass->flags = TEMPLCLASS_FLAGS_2; + return tmclass; +} + +void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec) { + DeclE decle; + TypeClass *tclass; + HashNameNode *classname; + Type *search; + short t; + NameSpace *nspace; + CScopeParseResult pr; + CScopeSave scopesave; + BrowseStruct bs; + FileOffsetInfo offsetsave; + SInt32 offset; + Boolean is_templ; + Boolean add_to_browse; + + memclrw(&decle, sizeof(DeclE)); + if (declinfo->x28) { + tclass = TYPE_CLASS(declinfo->x28); + } else { + if (tk == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&class_declspec); + + switch (tk) { + case ':': + case '{': + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + break; + case TK_IDENTIFIER: + classname = tkidentifier; + if (!declinfo->x4C && !declinfo->x4F && ((t = lookahead()) == ':' || t == ';' || t == '{')) { + tk = lex(); + search = CScope_GetLocalTagType(cscope_current, classname); + if (search) { + tagtype_search: + if (!IS_TYPE_CLASS(search)) { + if ((IS_TYPE_TEMPLATE(search) || IS_TYPE_STRUCT(search)) && tk != '{' && tk != ':') { + declinfo->thetype = search; + return; + } + if (!IS_TYPE_TEMPLATE(search) || !(tclass = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(search)))) { + CError_Error(132, classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + break; + } + } else { + tclass = TYPE_CLASS(search); + } + if (tclass->mode != mode) { + if ((mode == CLASS_FLAGS_2 && tclass->mode == CLASS_MODE_0) || (mode == CLASS_MODE_0 && tclass->mode == CLASS_MODE_2)) { + if (copts.warn_structclass) + CError_Warning(343); + } else { + CError_Error(132, classname); + } + } + tclass->eflags |= class_declspec; + break; + } else { + tclass = CDecl_DefineClass(cscope_current, classname, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + break; + } + } else { + tkidentifier = classname; + } + default: + if (!CScope_ParseElaborateName(&pr)) { + CError_Error(121); + declinfo->thetype = (Type *) &stsignedint; + return; + } + + tk = lex(); + if ((search = pr.x8)) { + goto tagtype_search; + } + +#line 6786 + CError_ASSERT(pr.name_4); + + tclass = CDecl_DefineClass(CScope_FindNonClassNonFunctionNS(cscope_current), pr.name_4, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + } + } + + declinfo->thetype = (Type *) tclass; + if (tk == ':' || tk == '{') { + if (declinfo->x4C) + CError_Error(201); + + if (tclass->flags & CLASS_FLAGS_2) { + if ((tclass->flags & CLASS_FLAGS_100) && !TEMPL_CLASS(tclass)->instances && !(TEMPL_CLASS(tclass)->flags & TEMPLCLASS_FLAGS_2)) { + tclass = TYPE_CLASS(CDecl_SpecializeTemplateClass(TEMPL_CLASS(tclass))); + } else { + CError_Error(132, tclass->classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + } + } + + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + if (nspace == tclass->nspace) { + CError_Error(132, tclass->classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + break; + } + } + + is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0; + if (tclass->flags & CLASS_FLAGS_800) { + TEMPL_CLASS_INST(tclass)->x46 = 1; + if (!declinfo->x28) + TEMPL_CLASS_INST(tclass)->x47 = 1; + } + +#line 6853 + CError_ASSERT(copts.align_mode >= 0 && copts.align_mode <= 14); + + tclass->eflags |= (UInt8) ((copts.align_mode + 1) << 4); + if (tk == ':') + CDecl_ParseBaseClassList(tclass, mode, is_templ); + + CScope_SetClassDefScope(tclass, &scopesave); + if (tk == '{') { + tk = lex(); + if ((add_to_browse = cparamblkptr->browseOptions.recordClasses && declinfo->fileoffsetinfo.file->recordbrowseinfo)) { + offsetsave = member_fileoffset; + CBrowse_BeginClass(declinfo, &bs); + } + CDecl_ParseClassMembers(&decle, tclass, mode); + offset = CPrep_BrowserFileOffset(); + if (flag1) + tk = lex(); + if (add_to_browse) { + member_fileoffset = offsetsave; + if (flag1 && tk == ';') + CPrep_BrowserFileOffset(); + CBrowse_EndClass(offset, &bs); + } + } else { + CError_Error(135); + } + + if (is_templ) + CTemplClass_CompleteClass(TEMPL_CLASS(tclass), &decle); + else + CDecl_CompleteClass(&decle, tclass); + CScope_RestoreScope(&scopesave); + } +} diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c new file mode 100644 index 0000000..e73c4bb --- /dev/null +++ b/compiler_and_linker/unsorted/CExpr.c @@ -0,0 +1,123 @@ +#include "compiler/CExpr.h" +#include "compiler/CError.h" + +Boolean (*name_obj_check)(void *, Object *); // TODO figure out the right type +Boolean disallowgreaterthan; + +void CExpr_RewriteConst() {} +void optimizecomm() {} +static void checkadditive() {} +static void CExpr_CompareConvert() {} +static void CExpr_ConstResult() {} +static void makemultnode() {} +static void makedivnode() {} +static void canadd2() {} +void canadd() {} +static void addconst() {} +static void integralpointerpromote() {} +static void padd() {} +static void psub() {} +static void makeaddnode() {} +static void makesubnode() {} +void checkreference() {} +static ENode *pointer_generation2(ENode *expr) {} +ENode *pointer_generation(ENode *expr) {} +void CExpr_PointerGeneration() {} +static void CExpr_ConstPointerCheck() {} +void oldassignmentpromotion() {} +void argumentpromotion() {} +void classargument() {} +ENodeList *CExpr_ScanExpressionList(Boolean flag) {} +static void skipcommaexpr() {} +void CExpr_DoExplicitConversion() {} +static void CExpr_TemplArgDepCast() {} +static void CExpr_ParseExplicitConversion() {} +static void CExpr_MemberVarAccess() {} +static void CExpr_IsTemplateFunc() {} +static void CExpr_ExplicitTemplateArgCheck() {} +void CExpr_MakeNameLookupResultExpr() {} +static void CExpr_NewPTMType() {} +static void CExpr_ParseNameResultExpr() {} +static void CExpr_ParseRotate() {} +static void CExpr_ParseNextArg() {} +static void CExpr_ParseVecStep() {} +static void CExpr_BuiltInComputeAlign() {} +static void CExpr_AtomTypeID() {} +static void CExpr_BuiltInComputeType() {} +static void CExpr_BuiltInClassifyType() {} +static void CExpr_BuiltInComputeVArgType() {} +static void CExpr_ParseTypeExpression() {} +static void CExpr_ParseBuiltin() {} +static void CExpr_ParseBuiltin_isintconst() {} +static void primary_expression() {} +static void CExpr_SimpleExplicitConversion() {} +static void CExpr_NewPTMFCall() {} +static void call_ptmf() {} +static void CExpr_DummyDestr() {} +static void postfix_expression() {} +static void CExpr_ParseSizeof() {} +void scansizeof() {} +static void CExpr_ParseAlignof() {} +void scanalignof() {} +static void logicalexpression() {} +void getnodeaddress() {} +static void CExpr_MakeStaticMemberList() {} +static void CExpr_MakePTDM() {} +void getpointertomemberfunc() {} +static void getpointertomember() {} +void CExpr_New_ELOGNOT_Node() {} +void CExpr_New_EMONMIN_Node() {} +void CExpr_New_EBINNOT_Node() {} +void unary_expression() {} +void do_castnullcheck() {} +void CExpr_SafeClassPointerCast() {} +void PointerToMemberCast() {} +void CExpr_MemberPointerConversion() {} +static void CExpr_MemberPointerCast() {} +void do_typecast() {} +static void isvectorconst() {} +void cast_expression() {} +static void pm_expression() {} +void CExpr_New_EMUL_Node() {} +void CExpr_New_EDIV_Node() {} +void CExpr_New_EMODULO_Node() {} +void CExpr_New_EADD_Node() {} +void CExpr_New_ESUB_Node() {} +void CExpr_New_ESHL_Node() {} +void CExpr_New_ESHR_Node() {} +static void pointercompare() {} +static void unsigncheck() {} +void CExpr_New_ELESS_Node() {} +void CExpr_New_ELESSEQU_Node() {} +void CExpr_New_EGREATER_Node() {} +void CExpr_New_EGREATEREQU_Node() {} +void memberpointercompare() {} +void CExpr_New_EEQU_Node() {} +void CExpr_New_ENOTEQU_Node() {} +void CExpr_New_EAND_Node() {} +void CExpr_New_EXOR_Node() {} +void CExpr_New_EOR_Node() {} +void CExpr_New_ELAND_Node() {} +void CExpr_New_ELOR_Node() {} +void CExpr_NewDyadicNode() {} +static void CExpr_GetDyadicInfo() {} +static void CExpr_ParseDyadicExpression() {} +static void CExpr_IsBlockMoveType() {} +void CExpr_New_ECOND_Node() {} +static void conditional_expression() {} +static void CExpr_MakeOpAssNode() {} +static void makeassignmentnode() {} +static void makepassignmentnode() {} +static void makemulassignmentnode() {} +static void CExpr_TransformOpAssign() {} +ENode *assignment_expression(void) {} +ENode *conv_assignment_expression(void) {} +static void CExpr_HasSideEffect() {} +void CExpr_CheckUnusedExpression() {} +void s_expression() {} +ENode *expression(void) {} +void CExpr_IntegralConstExprType() {} +ENode *CExpr_IntegralConstOrDepExpr(void) {} +void CExpr_IntegralConstExpr() {} +void CExpr_CheckUnwantedAssignment() {} +void CExpr_ParseAsmExpr() {} diff --git a/compiler_and_linker/unsorted/CExpr2.c b/compiler_and_linker/unsorted/CExpr2.c new file mode 100644 index 0000000..6679bce --- /dev/null +++ b/compiler_and_linker/unsorted/CExpr2.c @@ -0,0 +1,1934 @@ +#include "compiler/CExpr.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CInt64.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" + +#ifdef __MWERKS__ +#undef va_start +#undef va_arg +#define va_start(ap, parm) ap = __va_start(parm) +#define __va_start(parm) (va_list) (&parm + 1) +//#define va_arg(ap, type) ((((type *) (ap = (va_list) (( ((long) ap + sizeof(type) - 1) & ~(sizeof(type)) ) + sizeof(type) ) ))[-1])) +#define va_arg(ap, type) (*(((type *) (ap = (char *)((((unsigned long)ap + __builtin_align(type) - 1) & ~(__builtin_align(type) - 1) ) + sizeof(type)))) - 1)) +#endif + +// TODO MOVE ME +extern ENode *CSOM_EnvCheck(ENode *, ENodeList *); +extern Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr); +extern ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr); +extern Boolean CObjC_IsCompatibleType(Type *a, Type *b); + +ENode *assign_node; +Boolean temp_reference_init; +static SInt32 assign_value; // type? +static ENode *firstarrayexpr; +static Match5 user_std_match; +static Boolean cexpr_hascall; +static Boolean cexpr_esearch_bool[MAXEXPR]; +static Boolean cexpr_rsearch_bool[MAXEXPR]; +static CExprSearchCB cexpr_esearch_callback; +static CExprReplaceCB cexpr_rsearch_callback; +static Type *cexpr_left_conversion_type; +static Type *cexpr_right_conversion_type; + +// data objects, need to figure out the types +static void *diadic_arg1; +static void *diadic_arg2; +static void *mon_arg; + +static void CExpr_RecSearchExprTree(ENode *expr) { + ENodeList *list; + +restart: + if (cexpr_esearch_bool[expr->type]) + cexpr_esearch_callback(expr); + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + goto restart; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + CExpr_RecSearchExprTree(expr->data.diadic.left); + expr = expr->data.diadic.right; + goto restart; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EOBJLIST: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + return; + case EFUNCCALL: + case EFUNCCALLP: + for (list = expr->data.funccall.args; list; list = list->next) + CExpr_RecSearchExprTree(list->node); + expr = expr->data.funccall.funcref; + goto restart; + case ENULLCHECK: + CExpr_RecSearchExprTree(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + goto restart; + case EMFPOINTER: + CExpr_RecSearchExprTree(expr->data.mfpointer.accessnode); + expr = expr->data.mfpointer.mfpointer; + goto restart; + case ECOND: + CExpr_RecSearchExprTree(expr->data.cond.cond); + CExpr_RecSearchExprTree(expr->data.cond.expr1); + expr = expr->data.cond.expr2; + goto restart; + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + CExpr_RecSearchExprTree(expr->data.newexception.initexpr); + expr = expr->data.newexception.tryexpr; + goto restart; + case EMYSTERY67: + if (expr->data.itc.initexpr) + CExpr_RecSearchExprTree(expr->data.itc.initexpr); + if (expr->data.itc.tryexpr) + CExpr_RecSearchExprTree(expr->data.itc.tryexpr); + if (expr->data.itc.catchexpr) + CExpr_RecSearchExprTree(expr->data.itc.catchexpr); + if (expr->data.itc.result) + CExpr_RecSearchExprTree(expr->data.itc.result); + return; + default: +#line 128 + CError_FATAL(); + } +} + +void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...) { + va_list ap; + short i; + + cexpr_esearch_callback = callback; + + va_start(ap, count); + for (i = 0; i < MAXEXPR; i++) + cexpr_esearch_bool[i] = 0; + i = 0; + while ((short) i < count) { + cexpr_esearch_bool[va_arg(ap, int)] = 1; + ++i; + } + va_end(ap); + + CExpr_RecSearchExprTree(expr); +} + +static ENode *CExpr_RecSearchExprTreeReplace(ENode *expr) { + ENodeList *list; + ENode *replaced; + + if (cexpr_rsearch_bool[expr->type]) { + replaced = cexpr_rsearch_callback(expr); + if (!replaced) + return expr; + expr = replaced; + } + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExpr_RecSearchExprTreeReplace(expr->data.monadic); + return expr; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + expr->data.diadic.left = CExpr_RecSearchExprTreeReplace(expr->data.diadic.left); + expr->data.diadic.right = CExpr_RecSearchExprTreeReplace(expr->data.diadic.right); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + case EFUNCCALL: + case EFUNCCALLP: + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CExpr_RecSearchExprTreeReplace(list->node); + expr->data.funccall.funcref = CExpr_RecSearchExprTreeReplace(expr->data.funccall.funcref); + return expr; + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.condexpr); + return expr; + case EMFPOINTER: + expr->data.mfpointer.accessnode = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.mfpointer); + return expr; + case ECOND: + expr->data.cond.cond = CExpr_RecSearchExprTreeReplace(expr->data.cond.cond); + expr->data.cond.expr1 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr1); + expr->data.cond.expr2 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr2); + return expr; + default: +#line 220 + CError_FATAL(); + return NULL; + } +} + +ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...) { + va_list ap; + short i; + + cexpr_rsearch_callback = callback; + + va_start(ap, count); + for (i = 0; i < MAXEXPR; i++) + cexpr_rsearch_bool[i] = 0; + i = 0; + while ((short) i < count) { + cexpr_rsearch_bool[va_arg(ap, int)] = 1; + ++i; + } + va_end(ap); + + return CExpr_RecSearchExprTreeReplace(expr); +} + +static void CExpr_HasFuncCallCallBack(ENode *expr) { + cexpr_hascall = 1; +} + +Boolean CExpr_HasFuncCall(ENode *expr) { + cexpr_hascall = 0; + CExpr_SearchExprTree(expr, CExpr_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); + return cexpr_hascall; +} + +void CExpr_AliasTransform(ENode *expr) { + ENode *n; + + Object *obj = expr->data.objref; + if (obj->u.alias.offset) { + n = makediadicnode( + create_objectrefnode(obj->u.alias.object), + intconstnode(TYPE(&stunsignedlong), obj->u.alias.offset), + EADD); + *expr = *n; + } else { + expr->data.objref = obj->u.alias.object; + } +} + +ENode *CExpr_UnaryFloatExpression(ENode *expr) { + return expr; +} + +ENode *CExpr_BinaryFloatExpression(ENode *expr) { + return expr; +} + +ENode *CExpr_NewENode(ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + memclrw(expr, sizeof(ENode)); + expr->type = ty; + return expr; +} + +ENode *CExpr_NewTemplDepENode(TemplDepSubType t) { + ENode *expr = CExpr_NewENode(ETEMPLDEP); + expr->rtype = &sttemplexpr; + expr->data.templdep.subtype = t; + return expr; +} + +ENode *nullnode(void) { + ENode *expr = CExpr_NewENode(EINTCONST); + expr->rtype = (Type *) &stsignedlong; + return expr; +} + +ENode *intconstnode(Type *type, SInt32 value) { + ENode *expr = CExpr_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, value); + return expr; +} + +ENode *stringconstnode(char *str) { + ENode *expr; + SInt32 size; + + size = strlen(str) + 1; + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewArrayType((Type *) &stchar, size); + expr->data.string.size = size; + expr->data.string.data = str; + expr->data.string.ispascal = 0; + if (copts.const_strings) + expr->flags = Q_CONST; + + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + return expr; +} + +ENode *forceintegral(ENode *expr) { + if (!IS_TYPE_ENUM(expr->rtype)) { + CError_Error(144); + return nullnode(); + } else { + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + return expr; + } +} + +ENode *makemonadicnode(ENode *inner, ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ty; + if ((expr->cost = inner->cost) == 0) + expr->cost = 1; + expr->flags = inner->flags & ENODE_FLAG_QUALS; + expr->rtype = inner->rtype; + expr->data.monadic = inner; + return expr; +} + +ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ty; + expr->rtype = left->rtype; + expr->data.diadic.left = left; + expr->data.diadic.right = right; + + if (left->cost != right->cost) { + expr->cost = right->cost; + if (left->cost > expr->cost) + expr->cost = left->cost; + } else { + expr->cost = right->cost + 1; + if (expr->cost > 200) + expr->cost = 200; + } + + expr->flags = (left->flags | right->flags) & ENODE_FLAG_QUALS; + return expr; +} + +ENode *makecommaexpression(ENode *left, ENode *right) { + ENode *expr; + + if (ENODE_IS(right, EINDIRECT) && !ENODE_IS(right->data.monadic, EBITFIELD)) { + Boolean savecpp = copts.cplusplus; + copts.cplusplus = 1; + expr = makediadicnode(left, getnodeaddress(right, 0), ECOMMA); + copts.cplusplus = savecpp; + expr->rtype = expr->data.diadic.right->rtype; + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = makediadicnode(left, right, ECOMMA); + } + + expr->rtype = right->rtype; + expr->flags = right->flags; + return expr; +} + +short iszero(ENode *expr) { + switch (expr->type) { + case EINTCONST: + return CInt64_IsZero(&expr->data.intval); + case EFLOATCONST: + return CMach_FloatIsZero(expr->data.floatval); + default: + return 0; + } +} + +short isnotzero(ENode *expr) { + Object *obj; + + switch (expr->type) { + case EINTCONST: + return !CInt64_IsZero(&expr->data.intval); + case EFLOATCONST: + return !CMach_FloatIsZero(expr->data.floatval); + case ESTRINGCONST: + case ETEMP: + return 1; + case EOBJREF: + obj = expr->data.objref; + break; + case EADD: + case ESUB: + if (ENODE_IS(expr->data.diadic.left, EOBJREF) && ENODE_IS(expr->data.diadic.right, EINTCONST)) { + obj = expr->data.diadic.left->data.objref; + break; + } + if (ENODE_IS(expr->data.diadic.left, EINTCONST) && ENODE_IS(expr->data.diadic.right, EOBJREF)) { + obj = expr->data.diadic.right->data.objref; + break; + } + return 0; + default: + return 0; + } + + switch (obj->datatype) { + case DLOCAL: + return 1; + default: + return 0; + } +} + +Boolean CExpr_IsOne(ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) + return CInt64_Equal(expr->data.intval, cint64_one); + else if (ENODE_IS(expr, EFLOATCONST)) + return CMach_FloatIsOne(expr->data.floatval); + else + return 0; +} + +Boolean CExpr_AllBitsSet(ENode *expr) { + SInt32 v; + + if (ENODE_IS(expr, EINTCONST)) { + switch (expr->rtype->size) { + case 1: + v = CInt64_GetULong(&expr->data.intval) & 0xFF; + return v == 0xFF; + case 2: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFF; + return v == 0xFFFF; + case 3: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFF; + return v == 0xFFFFFF; + case 4: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFFFF; + return v == 0xFFFFFFFF; + default: + return CInt64_Equal(expr->data.intval, cint64_negone); + } + } + + return 0; +} + +ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ETEMP; + expr->cost = 0; + expr->flags = 0; + expr->rtype = CDecl_NewPointerType(type); + expr->data.temp.type = type; + expr->data.temp.uniqueid = assign_id ? CParser_GetUniqueID() : 0; + expr->data.temp.needs_dtor = 0; + return expr; +} + +static ENode *CExpr_DerefETEMPCopy(ENode *expr) { + ENode *copy; + +#line 636 + CError_ASSERT(expr->rtype->type == TYPEPOINTER); + + copy = lalloc(sizeof(ENode)); + *copy = *expr; + copy = makemonadicnode(copy, EINDIRECT); + copy->rtype = TYPE_POINTER(copy->rtype)->target; +} + +ENode *CExpr_GetETEMPCopy(ENode *expr) { + ENode *newnode; + ENode *assnode; + ENode *finalnode; + + newnode = CExpr_NewETEMPNode(expr->rtype, 1); + newnode->flags = expr->flags; + + assnode = makediadicnode(CExpr_DerefETEMPCopy(newnode), expr, EASS); + assnode->data.diadic.right = lalloc(sizeof(ENode)); + *assnode->data.diadic.right = *expr; + *expr = *assnode; + + finalnode = makemonadicnode(newnode, EINDIRECT); + finalnode->rtype = expr->rtype; + return finalnode; +} + +ENode *integralpromote(ENode *expr) { + if (!IS_TYPE_INT(expr->rtype)) + expr = forceintegral(expr); + + if (TYPE_INTEGRAL(expr->rtype)->integral >= IT_INT) + return expr; + + if (!ENODE_IS(expr, EINTCONST)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = (Type *) &stsignedint; + + return expr; +} + +CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val) { + if (a == (Type *) &stbool) + return CMach_CalcIntDiadic(b, val, TK_LOGICAL_NE, cint64_zero); + else + return CMach_CalcIntDiadic(a, val, '+', cint64_zero); +} + +ENode *promote(ENode *expr, Type *type) { + if (ENODE_IS(expr, EINTCONST)) { + if (IS_TYPE_FLOAT(type)) { + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); + } else { + expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); + } + expr->rtype = type; + return expr; + } + if (ENODE_IS(expr, EFLOATCONST)) { + if (IS_TYPE_FLOAT(type)) { + expr->data.floatval = CMach_CalcFloatConvert(type, expr->data.floatval); + expr->rtype = type; + return expr; + } else if (IS_TYPE_INT(type)) { + expr->data.intval = CMach_CalcIntConvertFromFloat(type, expr->data.floatval); + expr->type = EINTCONST; + expr->rtype = type; + return expr; + } + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + return expr; +} + +void CExpr_ArithmeticConversion(ENode **left, ENode **right) { + switch ((*left)->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + break; + case TYPEENUM: + (*left)->rtype = TYPE_ENUM((*left)->rtype)->enumtype; + break; + default: + CError_Error(144); + (*left) = nullnode(); + } + + switch ((*right)->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + break; + case TYPEENUM: + (*right)->rtype = TYPE_ENUM((*right)->rtype)->enumtype; + break; + default: + CError_Error(144); + (*right) = nullnode(); + } + + if (IS_TYPE_FLOAT((*left)->rtype) || IS_TYPE_FLOAT((*right)->rtype)) { + if ((*left)->rtype != (*right)->rtype) { + if (TYPE_INTEGRAL((*left)->rtype)->integral > TYPE_INTEGRAL((*right)->rtype)->integral) + *right = promote(*right, (*left)->rtype); + else + *left = promote(*left, (*right)->rtype); + } + return; + } + + *left = integralpromote(*left); + *right = integralpromote(*right); + if ((*left)->rtype != (*right)->rtype) { + if (TYPE_INTEGRAL((*left)->rtype)->integral < TYPE_INTEGRAL((*right)->rtype)->integral) { + ENode **tmp = left; + left = right; + right = tmp; + } + + if ((*left)->rtype->size == (*right)->rtype->size && !is_unsigned((*left)->rtype) && is_unsigned((*right)->rtype)) { + if ((*left)->rtype == (Type *) &stsignedlong) { + *left = promote(*left, (Type *) &stunsignedlong); + } else { +#line 838 + CError_ASSERT((*left)->rtype == (Type *) &stsignedlonglong); + *left = promote(*left, (Type *) &stunsignedlonglong); + } + } + + *right = promote(*right, (*left)->rtype); + } +} + +static ENode *CExpr_GetEA(ENode *expr) { + ENode *copy; + + for (;;) { + switch (expr->type) { + case EINDIRECT: + expr = expr->data.monadic; + for (;;) { + switch (expr->type) { + case EOBJREF: + copy = lalloc(sizeof(ENode)); + *copy = *expr; + return copy; + case ECOMMA: + expr = expr->data.diadic.right; + continue; + default: + return CExpr_GetETEMPCopy(expr); + } + } + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = expr->data.monadic; + continue; + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + expr = expr->data.monadic; + continue; + case ECOMMA: + expr = expr->data.diadic.right; + continue; + default: + return NULL; + } + } +} + +ENode *CExpr_TempModifyExpr(ENode *expr) { + // register issues + Type *type; + ENode *tempnode; + ENode *eanode; + ENode *assnode2; + ENode *left; + ENode *right; + ENode *work; + + type = expr->rtype; + tempnode = CExpr_NewETEMPNode(type, 1); + eanode = CExpr_GetEA(expr); + if (!eanode) { + CError_Error(142); + return expr; + } + + left = makemonadicnode(tempnode, EINDIRECT); + left->rtype = type; + work = makediadicnode(left, expr, EASS); + + left = makemonadicnode(eanode, EINDIRECT); + left->rtype = type; + right = nullnode(); + right->rtype = (Type *) &stbool; + CInt64_SetLong(&right->data.intval, 1); + assnode2 = makediadicnode(left, right, EASS); + + work = makediadicnode(work, assnode2, ECOMMA); + right = makemonadicnode(tempnode, EINDIRECT); + right->rtype = type; + work = makediadicnode(work, right, ECOMMA); + + return work; +} + +Boolean CExpr_IsLValue(ENode *expr) { + while (!ENODE_IS(expr, EINDIRECT)) { + switch (expr->type) { + case EPREINC: + case EPREDEC: + return copts.cplusplus; + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if (!copts.cplusplus) + return 0; + expr = expr->data.diadic.left; + continue; + case ECOMMA: + if (!copts.cplusplus) + return 0; + expr = expr->data.diadic.right; + continue; + case ECOND: + if ( + copts.cplusplus && + is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && + (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) + ) { + return CExpr_IsLValue(expr->data.cond.expr1) && CExpr_IsLValue(expr->data.cond.expr2); + } + return 0; + default: + return 0; + } + } + + expr = expr->data.monadic; + switch (expr->type) { + case ETEMP: + return 0; + case EFUNCCALL: + if (expr->data.funccall.functype->functype->type != TYPEPOINTER || (expr->data.funccall.functype->flags & FUNC_FLAGS_1000)) + return 0; + default: + return 1; + } +} + +ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2) { + ENode *eanode; + ENode *tmpnode; + +loop: + switch (expr->type) { + case ETYPCON: + if (copts.pointercast_lvalue || !copts.ANSI_strict) { + if (expr->rtype->type == TYPEPOINTER && expr->data.monadic->rtype->type == TYPEPOINTER) { + switch (expr->data.monadic->type) { + case EINDIRECT: + case ETYPCON: + expr->data.monadic->rtype = expr->rtype; + expr->data.monadic->flags = expr->flags; + expr = expr->data.monadic; + goto loop; + } + } + } + break; + case EINDIRECT: + if (flag2) { + if (!CExpr_IsLValue(expr)) + CError_Warning(142); + + if ( + ENODE_IS(expr->data.monadic, EOBJREF) && + expr->data.monadic->data.objref->name == this_name_node && + cscope_currentfunc && + cscope_currentclass && + expr->data.monadic->data.objref == CClass_ThisSelfObject()) + CError_Error(189); + } + if (flag1) { + if (CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS)) + CError_Error(179); + } + return expr; + case EPREINC: + case EPREDEC: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + if (copts.cplusplus) { + if ((eanode = CExpr_GetEA(expr))) { + tmpnode = makediadicnode(expr, eanode, ECOMMA); + tmpnode->rtype = tmpnode->data.diadic.right->rtype; + tmpnode = makemonadicnode(tmpnode, EINDIRECT); + tmpnode->rtype = expr->rtype; + return tmpnode; + } + CError_Error(190); + return expr; + } + break; + case ECOND: + if ( + copts.cplusplus && + is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && + (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) + ) { + expr->data.cond.expr1 = CExpr_LValue(expr->data.cond.expr1, flag1, flag2); + expr->data.cond.expr2 = CExpr_LValue(expr->data.cond.expr2, flag1, flag2); + if (ENODE_IS(expr->data.cond.expr1, EINDIRECT) && ENODE_IS(expr->data.cond.expr2, EINDIRECT)) { + if (!ENODE_IS(expr->data.cond.expr1->data.monadic, EBITFIELD) && !ENODE_IS(expr->data.cond.expr2->data.monadic, EBITFIELD)) { + expr->data.cond.expr1 = getnodeaddress(expr->data.cond.expr1, 0); + expr->data.cond.expr2 = getnodeaddress(expr->data.cond.expr2, 0); + expr->rtype = expr->data.cond.expr1->rtype; + tmpnode = makemonadicnode(expr, EINDIRECT); + tmpnode->rtype = TYPE_POINTER(tmpnode->rtype)->target; + return tmpnode; + } + } + } + break; + } + + if (flag2) + CError_Error(142); + return expr; +} + +ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag) { + ENode *expr; + + if (obj->sclass == OBJECT_SCLASS_104) { + CError_Error(141); + return intconstnode((Type *) &void_ptr, 0); + } + + expr = lalloc(sizeof(ENode)); + memclrw(expr, sizeof(ENode)); + expr->type = EOBJREF; + expr->data.objref = obj; + expr->rtype = CDecl_NewPointerType(obj->type); + + if (!IS_TYPE_FUNC(obj->type)) + expr->flags = obj->qual & ENODE_FLAG_QUALS; + if (flag) + obj->flags |= OBJECT_FLAGS_UNUSED; + + return expr; +} + +ENode *create_objectrefnode(Object *obj) { + if (name_obj_check && !name_obj_check(NULL, obj)) + return intconstnode((Type *) &void_ptr, 0); + return CExpr_MakeObjRefNode(obj, 1); +} + +ENode *create_objectnode2(Object *obj) { + ENode *expr; + + if (name_obj_check && !name_obj_check(NULL, obj)) + return nullnode(); + + expr = makemonadicnode(CExpr_MakeObjRefNode(obj, 1), EINDIRECT); + expr->rtype = TYPE_POINTER(expr->rtype)->target; + return expr; +} + +ENode *create_objectnode(Object *obj) { + return checkreference(create_objectnode2(obj)); +} + +static ENode *CExpr_ExpandArg(ENode *expr, Type *type) { + if (ENODE_IS(expr, ETYPCON) && IS_TYPE_FLOAT(type)) { + expr->rtype = type; + return expr; + } else { + return promote(expr, type); + } +} + +ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr) { + ENodeList *args; + ENode *funccall; + ENode *funcref; + + if (!ENODE_IS(expr, EINDIRECT) || expr->rtype != type || !ENODE_IS((funccall = expr->data.monadic), EFUNCCALL) || !(args = funccall->data.funccall.args)) + return NULL; + + if (!ENODE_IS((funcref = funccall->data.funccall.funcref), EOBJREF) || !CClass_IsConstructor(funcref->data.objref)) { + if (expr->data.monadic->data.funccall.functype->functype != type) + return NULL; + if (CABI_GetStructResultArgumentIndex() == 1) { + args = args->next; +#line 1277 + CError_ASSERT(args); + } + } + + if (resultexpr) + *resultexpr = args->node; + return expr->data.monadic; +} + +ENode *CExpr_AdjustFunctionCall(ENode *expr) { + ENodeList *list; + + switch (expr->data.funccall.functype->functype->type) { + case TYPECLASS: + CDecl_CompleteType(expr->data.funccall.functype->functype); + case TYPESTRUCT: + if (!expr->data.funccall.functype->functype->size) + CError_Error(136, expr->data.funccall.functype->functype, 0); + } + + if (CMach_GetFunctionResultClass(expr->data.funccall.functype)) { + list = lalloc(sizeof(ENodeList)); + if (IS_TYPE_CLASS(expr->data.funccall.functype->functype)) { + CDecl_CompleteType(expr->data.funccall.functype->functype); + if (CClass_Destructor(TYPE_CLASS(expr->data.funccall.functype->functype))) + list->node = create_temp_node2(expr->rtype); + else + list->node = create_temp_node(expr->rtype); + } else { + list->node = create_temp_node(expr->rtype); + } + list->next = expr->data.funccall.args; + expr->data.funccall.args = list; + + if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) + expr = CSOM_EnvCheck(expr, list); + + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + return expr; + } + + if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) + expr = CSOM_EnvCheck(expr, NULL); + return expr; +} + +ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4) { + ENode *expr; + TypeFunc *tfunc; + ENodeList *list; + + tfunc = TYPE_FUNC(func->type); +#line 1411 + CError_ASSERT(IS_TYPE_FUNC(tfunc)); + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = tfunc->functype; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.functype = tfunc; + + if (arg1) { + list = lalloc(sizeof(ENodeList)); + expr->data.funccall.args = list; + list->node = arg1; + if (arg2) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg2; + if (arg3) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg3; + if (arg4) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg4; + } + } + } + list->next = NULL; + } else { + expr->data.funccall.args = NULL; + } + + return CExpr_AdjustFunctionCall(expr); +} + +ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6) { + ENode *expr; + TypeFunc *tfunc; + ENodeList *list; + + tfunc = TYPE_FUNC(func->type); +#line 1460 + CError_ASSERT(IS_TYPE_FUNC(tfunc)); + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = tfunc->functype; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.functype = tfunc; + + list = lalloc(sizeof(ENodeList)); + expr->data.funccall.args = list; + list->node = arg1; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg2; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg3; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg4; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg5; + if (arg6) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg6; + } + list->next = NULL; + + return CExpr_AdjustFunctionCall(expr); +} + +static void CExpr_CalcStdAssign(short checkresult, Match5 *match, Type *t1, UInt32 q1, Type *t2, UInt32 q2, Boolean flag) { + memclrw(match, sizeof(Match5)); + switch (checkresult) { + case CheckResult1: + match->x0++; + break; + case CheckResult2: + match->x2++; + break; + case CheckResult3: + match->x4++; + match->x6 += assign_value; + break; + default: +#line 1504 + CError_FATAL(); + } + + if (flag || (IS_TYPE_POINTER_ONLY(t2) && (IS_TYPE_POINTER_ONLY(t1) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) != 0)) { + if ((q2 & Q_CONST) == (q1 & Q_CONST)) + match->x8++; + if ((q2 & Q_VOLATILE) == (q1 & Q_VOLATILE)) + match->x8++; + } +} + +void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) { + Boolean r8; + + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) { + t2 = TYPE_POINTER(t2)->target; + r8 = 1; + } else { + r8 = 0; + } + + while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) { + if (r8) { + if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST)) + match->xC--; + if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE)) + match->xC--; + } + t2 = TYPE_POINTER(t2)->target; + t1 = TYPE_POINTER(t1)->target; + r8 = 1; + } + + if ((q1 & Q_CONST) != (q2 & Q_CONST)) + match->xC--; + if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE)) + match->xC--; +} + +Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) { + switch (assign_check(expr, type, qual, 0, 0, 1)) { + case CheckResult0: + return 0; + case CheckResult1: + match->x4++; + break; + case CheckResult2: + match->x6++; + break; + case CheckResult3: + match->x8++; + match->xA += assign_value; + break; + case CheckResult4: + match->xE++; + match->match5.x0 += user_std_match.x0; + match->match5.x2 += user_std_match.x2; + match->match5.x4 += user_std_match.x4; + match->match5.x6 += user_std_match.x6; + match->match5.x8 += user_std_match.x8; + break; + default: +#line 1585 + CError_FATAL(); + } + + if (IS_TYPE_POINTER_ONLY(type)) + CExpr_MatchCV(expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual, match); + + return 1; +} + +static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) { + if (a->x0 > b->x0) return 1; + if (a->x0 == b->x0) { + if (a->x2 > b->x2) return 1; + if (a->x2 == b->x2) { + if (a->x4 > b->x4) return 1; + if (a->x4 == b->x4) { + if (a->x6 > b->x6) return 1; + if (a->x6 == b->x6) { + if (!flag) + return 0; + if (a->x8 > b->x8) return 1; + if (a->x8 == b->x8) return 0; + } + } + } + } + return -1; +} + +static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) { + // returns CheckResult +} + +ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) { + ENode *expr; + ClassList *base; + Boolean do_nullcheck; + TypeClass *tclass; + SInt32 offset; + ENode *tmp; + + expr = origexpr; + tclass = TYPE_CLASS(cls->type); + do_nullcheck = 0; +#line 1691 + CError_ASSERT(cls); + + if (!IS_TYPE_POINTER_ONLY(origexpr->rtype)) { + CError_Error(CErrorStr141); + return origexpr; + } + + cls = cls->next; + while (cls) { + for (base = tclass->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(cls->type)) + break; + } + + if (!base) { + CError_Error(CErrorStr221); + while (cls->next) + cls = cls->next; + + tmp = nullnode(); + tmp->rtype = CDecl_NewPointerType(cls->type); + return tmp; + } + + if (base->is_virtual) { + if (!base->base->sominfo) { + do_nullcheck = 1; + if ((offset = base->offset) && !canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); + expr = makemonadicnode(expr, EINDIRECT); + } + } else { + if ((offset = base->offset)) { + do_nullcheck = 1; + if (!canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + } + } + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = makemonadicnode(expr, ETYPCON); + } + + expr->rtype = CDecl_NewPointerType(TYPE(base->base)); + tclass = TYPE_CLASS(cls->type); + cls = cls->next; + } + + if (nullcheckflag && do_nullcheck) + expr = do_castnullcheck(expr, origexpr); + return expr; +} + +ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag) { + TypeClass *tclass; + ENode *tmp; + + if (!expr) { + if (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func || !(expr = CClass_CreateThisSelfExpr())) { + CError_Error(CErrorStr221); + return NULL; + } + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(cscope_currentclass); + } + +#line 1786 + CError_ASSERT(a); +#line 1787 + CError_ASSERT(IS_TYPE_CLASS(expr->rtype)); + + tclass = TYPE_CLASS(expr->rtype); + a = CScope_GetClassAccessPath(a, tclass); + if (!a || a->type != TYPE(tclass)) { + CError_Error(CErrorStr221); + return NULL; + } + + if (flag) + CClass_CheckPathAccess(a, obj, access); + + if (!TYPE_CLASS(a->type)->sominfo) { + if (b) + a = CClass_AppendPath(a, b); + + if (!ENODE_IS(expr, EINDIRECT)) + expr = CExpr_LValue(expr, 0, 0); + + if (ENODE_IS(expr, EINDIRECT)) { + expr->data.monadic->flags = expr->flags; + tmp = expr->data.monadic; + switch (tmp->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + tmp = makemonadicnode(tmp, ETYPCON); + } + expr = makemonadicnode(CExpr_ClassPointerCast(a, tmp, 0), EINDIRECT); + expr->rtype = TYPE(tclass); + } + } + + return expr; +} + +static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) { +} + +ENode *CExpr_ConvertToBool(ENode *expr, Boolean flag) { + if (IS_TYPE_MEMBERPOINTER(expr->rtype)) + expr = CExpr_ConvertToCondition(expr); + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + if (IS_TYPE_ENUM(expr->rtype)) + expr = forceintegral(expr); + switch (expr->type) { + case EINTCONST: + CInt64_SetLong(&expr->data.intval, !CInt64_IsZero(&expr->data.intval)); + break; + case EFLOATCONST: + CInt64_SetLong(&expr->data.intval, !CMach_FloatIsZero(expr->data.floatval)); + expr->type = EINTCONST; + break; + default: + expr = makemonadicnode(expr, ELOGNOT); + expr->rtype = TYPE(&stbool); + expr = makemonadicnode(expr, ELOGNOT); + } + break; + default: + CError_Error( + flag ? CErrorStr247 : CErrorStr209, + expr->rtype, + expr->flags & ENODE_FLAG_QUALS, + &stbool, + 0); + expr = nullnode(); + } + + expr->rtype = TYPE(&stbool); + return expr; +} + +static short std_assign_check(ENode *expr, Type *type, Boolean flag1, Boolean flag2) { + short result; + + if (copts.cplusplus) { + illegalimplicitconversion = 0; + + if ((result = iscpp_typeequal(expr->rtype, type))) { + assign_node = expr; + if (result == -1) { + assign_value = 1; + return CheckResult3; + } else { + return CheckResult1; + } + } + + if (flag1 && illegalimplicitconversion) { + CError_Error(CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + return CheckResult0; + } + } else { + if (is_typeequal(expr->rtype, type)) { + assign_node = expr; + return CheckResult1; + } + } + + if (type == TYPE(&stbool)) { + switch (expr->rtype->type) { + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + assign_value = 0; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + if (flag1) + assign_node = CExpr_ConvertToBool(expr, 0); + return CheckResult3; + default: + return CheckResult0; + } + } + + if (IS_TYPE_ENUM(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + result = CheckResult3; + if (IS_TYPE_INT(type)) { + if (TYPE_ENUM(expr->rtype)->enumtype == type) { + result = CheckResult2; + } else if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { + switch (TYPE_INTEGRAL(type)->integral) { + case IT_INT: + if (expr->rtype->size < stsignedint.size || TYPE_ENUM(expr->rtype)->enumtype == TYPE(&stsignedshort)) + result = CheckResult2; + break; + case IT_UINT: + if (expr->rtype->size >= stsignedint.size && TYPE_ENUM(expr->rtype)->enumtype != TYPE(&stsignedshort)) + result = CheckResult2; + break; + } + } + } + if (flag1) { + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + assign_node = promote(expr, type); + } + return result; + } + + if (IS_TYPE_INT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + result = CheckResult3; + if (TYPE_INTEGRAL(expr->rtype)->integral <= IT_INT) { + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) { + switch (TYPE_INTEGRAL(type)->integral) { + case IT_INT: + if (expr->rtype->size < stsignedint.size || type != TYPE(&stunsignedshort)) + result = CheckResult2; + break; + case IT_UINT: + if (expr->rtype->size == stsignedint.size && type == TYPE(&stunsignedshort)) + result = CheckResult2; + break; + } + } + } + + if (flag1 && type != expr->rtype) + assign_node = promote(expr, type); + else + assign_node = expr; + return result; + } + + if (IS_TYPE_FLOAT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + if (type == TYPE(&stdouble) && (expr->rtype == TYPE(&stfloat) || expr->rtype == TYPE(&stshortdouble))) + result = CheckResult2; + else + result = CheckResult3; + + if (flag1 && (!IS_TYPE_FLOAT(type) || type->size != expr->rtype->size)) + assign_node = promote(expr, type); + else + assign_node = expr; + return result; + } + + if (IS_TYPE_POINTER_ONLY(type)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval) && (IS_TYPE_INT(expr->rtype) || (!copts.cplusplus && IS_TYPE_ENUM(expr->rtype)))) { + if (flag1) + expr->rtype = TYPE(&stunsignedlong); + assign_node = expr; + return CheckResult3; + } + if (ENODE_IS(expr, EOBJLIST)) { + return std_assign_check_overload(expr->data.objlist.list, expr->data.objlist.templargs, type, flag1); + } + if (IS_TYPE_POINTER_ONLY(expr->rtype)) { + if (ENODE_IS(expr, EOBJREF) && IS_TYPE_FUNC(expr->data.objref->type) && (TYPE_FUNC(expr->data.objref->type)->flags & FUNC_FLAGS_100000)) { + NameSpaceObjectList list; + list.next = NULL; + list.object = OBJ_BASE(expr->data.objref); + return std_assign_check_overload(&list, NULL, type, flag1); + } + if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type)) { + assign_value = 1; + return CheckResult3; + } + if (IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + short depth; + Boolean isambig; + BClassList *path; + path = CClass_GetBasePath( + TYPE_CLASS(TYPE_POINTER(expr->rtype)->target), + TYPE_CLASS(TYPE_POINTER(type)->target), + &depth, &isambig + ); + if (path) { + assign_value = 1000 - depth; + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + if (flag2) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + assign_node = CExpr_ClassPointerCast(path, expr, 1); + } + return CheckResult3; + } else { + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + else + CError_Error( + CErrorStr244, + expr->rtype, + expr->flags & ENODE_FLAG_QUALS, + type, + 0); + } + return CheckResult0; + } + } + } + } + + if (IS_TYPE_MEMBERPOINTER(type) && !IS_TYPE_CLASS(expr->rtype)) { + return CExpr2_MemberPointerConversion(type, expr, flag1); + } + + if (IS_TYPE_CLASS(expr->rtype) && IS_TYPE_CLASS(type)) { + short depth; + Boolean isambig; + BClassList *path; + path = CClass_GetBasePath( + TYPE_CLASS(expr->rtype), + TYPE_CLASS(type), + &depth, &isambig + ); + if (path) { + assign_value = 1000 - depth; + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + assign_node = getnodeaddress(expr, 0); + assign_node = CExpr_ClassPointerCast(path, assign_node, 0); + assign_node = makemonadicnode(assign_node, EINDIRECT); + assign_node->rtype = type; + } + return CheckResult3; + } + } + + if (IS_TYPE_ENUM(type)) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + if (!copts.cplusplus) { + if (flag1) { + if (copts.pedantic) + CError_Warning(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + assign_node = do_typecast(expr, type, 0); + assign_node->flags = expr->flags; + } + return CheckResult2; + } else { + if (flag1) + CError_Error(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + } + } + } + + return CodeGen_AssignCheck(expr, type, flag1, flag2); +} + +static short is_compatible_conversion(Type *a, Type *b) { + if (IS_TYPE_REFERENCE(a)) + a = TYPE_POINTER(a)->target; + if (IS_TYPE_REFERENCE(b)) + b = TYPE_POINTER(b)->target; + return iscpp_typeequal(b, a); +} + +static void CExpr_ConIteratorInit(ConIterator *iter) { + ClassList *base; + ConIterator *subiter; + ConIteratorList *list; + + for (base = iter->tclass->bases; base; base = base->next) { + if (base->base->flags & CLASS_FLAGS_40) { + subiter = galloc(sizeof(ConIterator)); + memclrw(subiter, sizeof(ConIterator)); + subiter->parent = iter; + subiter->tclass = base->base; + CExpr_ConIteratorInit(subiter); + + list = galloc(sizeof(ConIteratorList)); + memclrw(list, sizeof(ConIteratorList)); + list->iter = subiter; + list->next = iter->children; + iter->children = list; + } + } +} + +void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass) { + memclrw(iter, sizeof(ConversionIterator)); + if (tclass->flags & CLASS_FLAGS_40) { + iter->coniter = &iter->myconiter; + iter->myconiter.tclass = tclass; + CExpr_ConIteratorInit(&iter->myconiter); + CScope_InitObjectIterator(&iter->objiter, tclass->nspace); + } +} + +static Boolean CExpr_ConversionIteratorIsHidden(ConIterator *iter, TypeFunc *tfunc) { + CScopeObjectIterator objiter; + ObjBase *obj; + TypeFunc *objtfunc; + + while (iter) { + CScope_InitObjectIterator(&objiter, iter->tclass->nspace); + while (1) { + if (!(obj = CScope_NextObjectIteratorObject(&objiter))) + break; + + objtfunc = TYPE_FUNC(OBJECT(obj)->type); + if ( + IS_TYPE_FUNC(objtfunc) && + (objtfunc->flags & FUNC_FLAGS_40) && + is_compatible_conversion(tfunc->functype, objtfunc->functype) && + (tfunc->args->qual & Q_CONST) == (objtfunc->args->qual & Q_CONST) && + (tfunc->qual & Q_CONST) == (objtfunc->qual & Q_CONST) + ) + return 1; + } + iter = iter->parent; + } + + return 0; +} + +Object *CExpr_ConversionIteratorNext(ConversionIterator *iter) { + ConIterator *ci; + Object *obj; + + ci = iter->coniter; + if (!ci) + return NULL; + +restart: + if ((obj = OBJECT(CScope_NextObjectIteratorObject(&iter->objiter)))) { + if ( + IS_TYPE_FUNC(obj->type) && + (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_40) && + !CExpr_ConversionIteratorIsHidden(ci->parent, TYPE_FUNC(obj->type)) + ) { + return obj; + } + goto restart; + } + + do { + if (ci->children) { + iter->coniter = ci->children->iter; + ci->children = ci->children->next; + ci = iter->coniter; + CScope_InitObjectIterator(&iter->objiter, ci->tclass->nspace); + goto restart; + } + } while ((ci = ci->parent)); + + return NULL; +} + +void user_assign_check() {} + +ENode *CExpr_ConvertToCondition(ENode *expr) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + return expr; + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + return expr; + case TYPEMEMBERPOINTER: + return memberpointercompare(ENOTEQU, expr, nullnode()); + case TYPECLASS: + return CExpr_Convert(expr, TYPE(&stbool), 0, 0, 1); + default: + CError_Error(376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); + return nullnode(); + } +} + +void CExpr_ConvertToIntegral() {} +void CExpr_CheckArithmConversion() {} +void get_address_of_temp_copy() {} + +short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { +} + +void CExpr_MatchCompare() {} +static void MatchOverloadFunc() {} +void CExpr_GetFuncMatchArgs() {} + +static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) { + NameSpaceObjectList *first; + NameSpaceObjectList *work; + + first = work = lalloc(sizeof(NameSpaceObjectList)); + while (1) { + work->object = list->object; + list = list->next; + if (!list) { + work->next = NULL; + break; + } else { + work->next = lalloc(sizeof(NameSpaceObjectList)); + work = work->next; + } + } + return first; +} + +static void CExpr_MatchArgList() {} + +ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) { + ENode *tmp; + + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->dexpr)) { +#line 3264 + CError_ASSERT(ENODE_IS(funcexpr, EOBJREF)); + tmp = CTemplTool_DeduceDefaultArg( + funcexpr->data.objref, + CInline_CopyExpression(arg->dexpr, CopyMode0) + ); + return argumentpromotion(tmp, arg->type, arg->qual, 1); + } + + return CInline_CopyExpression(arg->dexpr, CopyMode0); +} + +static ENode *CExpr_GenericCall(ENode *funcexpr, ENodeList *argexprs, TypeFunc *tfunc, FuncArg *args) { + ENodeList *list; + ENode *callexpr; + + while (args) { + if (args->dexpr) { + if (argexprs) { + list = argexprs; + while (list->next) + list = list->next; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + } else { + list = argexprs = lalloc(sizeof(ENodeList)); + } + list->next = NULL; + list->node = CExpr_GetDefaultArgument(funcexpr, args); + } + args = args->next; + } + + callexpr = lalloc(sizeof(ENode)); + callexpr->type = EFUNCCALL; + callexpr->cost = 4; + callexpr->rtype = tfunc->functype; + callexpr->flags = tfunc->qual & ENODE_FLAG_QUALS; + callexpr->data.funccall.funcref = funcexpr; + callexpr->data.funccall.funcref->rtype = CDecl_NewPointerType(TYPE(tfunc)); + callexpr->data.funccall.args = argexprs; + callexpr->data.funccall.functype = tfunc; + funcexpr->data.objref->flags |= OBJECT_FLAGS_UNUSED; + return CExpr_AdjustFunctionCall(callexpr); +} + +static Boolean CExpr_IsObjrefPlusX(ENode *expr) { + Type *type; + + if (ENODE_IS(expr, EOBJREF)) { + type = expr->data.objref->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + return IS_TYPE_CLASS(type); + } + + if (ENODE_IS2(expr, EADD, ESUB)) { + if (CExpr_IsObjrefPlusX(expr->data.diadic.left)) + return 1; + if (CExpr_IsObjrefPlusX(expr->data.diadic.right)) + return 1; + } + + return 0; +} + +static Boolean CExpr_IsStaticType(ENode *expr) { + return ENODE_IS(expr, EINDIRECT) && CExpr_IsObjrefPlusX(expr->data.monadic); +} + +ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) { + if (!copts.old_argmatch) + expr = pointer_generation(expr); + + switch (expr->rtype->type) { + case TYPEVOID: + case TYPEFUNC: + CError_Error(CErrorStr353); + expr = nullnode(); + break; + case TYPEINT: + case TYPEENUM: + expr = integralpromote(expr); + break; + case TYPEFLOAT: + if (TYPE_INTEGRAL(expr->rtype)->integral < IT_DOUBLE) + expr = promote(expr, TYPE(&stdouble)); + break; + case TYPECLASS: + expr = classargument(expr); + break; + } + + if (!flag && copts.warn_largeargs) { + if ((IS_TYPE_INT(expr->rtype) && TYPE_INTEGRAL(expr->rtype)->integral >= IT_LONGLONG) || IS_TYPE_FLOAT(expr->rtype)) + CError_Warning(CErrorStr316); + } + + return expr; +} + +void CExpr_GenericFuncCall() {} +void CExpr_GenericPtmfCall() {} +static void CExpr_ConvertEMember() {} +void CExpr_MakeFunctionCall() {} +static void accept_conversion_type() {} +static void CExpr_OperatorConversion() {} +static void wild_conversion_check() {} +static void monadic_conversion_check() {} +static void is_legal_type_combination() {} +static void match_class_type_conversion() {} +static void match_type_class_conversion() {} +static void match_class_class_conversion() {} +void CExpr_CheckOperatorConversion() {} +void CExpr_CheckOperator() {} + +ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) { + ENode *expr; + Object *ctor; + +#line 4595 + CError_ASSERT(IS_TYPE_POINTER_ONLY(addr_expr->rtype)); + + addr_expr = makemonadicnode(addr_expr, EINDIRECT); + addr_expr->rtype = TYPE(tclass); + + if (!flag3 && args && !args->next && args->node->rtype == TYPE(tclass) && !CClass_CopyConstructor(tclass)) { +#line 4605 + CError_ASSERT(IS_TYPE_CLASS(addr_expr->rtype)); + expr = makediadicnode(addr_expr, args->node, EASS); + if (!flag1) + expr = getnodeaddress(expr, 0); + return expr; + } + + if ((ctor = CClass_Constructor(tclass))) { + if (tclass->flags & CLASS_FLAGS_20) { + ENodeList *list = lalloc(sizeof(ENodeList)); + list->next = args; + args = list; + list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0); + } + // TODO: 12CE80 call to genericfunccall + } else { + if (args) { + if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) { + return makediadicnode( + addr_expr, + CExpr_AssignmentPromotion(args->node, TYPE(tclass), 0, 1), + EASS); + } + CError_Error(174); + } + return addr_expr; + } +} + +static void CExpr_DeleteFuncCall() {} +static void CExpr_CopyPlacementNewArg() {} +static void CExpr_PlacementDeleteCall() {} +static void scan_type_name() {} +static void cv_qualifier_list() {} +static void scan_new_declarator() {} +static void scan_new_type_name() {} +static void CExpr_NewAlloc() {} +static void CExpr_NewExceptionSafeAlloc() {} +static void CExpr_NewExceptionSafeInit() {} +static void CExpr_NewArray() {} +static void CExpr_NewSimpleClass() {} +static void CExpr_NewClass() {} +void scannew() {} +static void CExpr_DeleteArray() {} +void scandelete() {} diff --git a/compiler_and_linker/unsorted/CFunc.c b/compiler_and_linker/unsorted/CFunc.c new file mode 100644 index 0000000..76d880a --- /dev/null +++ b/compiler_and_linker/unsorted/CFunc.c @@ -0,0 +1,105 @@ +#include "compiler/CFunc.h" +#include "compiler/types.h" + +FuncArg elipsis; +FuncArg oldstyle; +ObjectList *arguments; +ObjectList *locals; +short localcount; +SInt32 curstmtvalue; +SInt32 sourceoffset; +HashNameNode *sourcefilepath; +SInt32 functionbodyoffset; +HashNameNode *functionbodypath; +InitExpr *init_expressions; +CLabel *Labels; +CtorChain *ctor_chain; +Statement *curstmt; +static short temp_destructor_object_regmem; +static short temp_destructor_objects; +static short temp_expression_has_conditionals; +static DeclBlock *firstblock; +static DeclBlock *currentblock; +static short blockcount; +static Object *sinit_first_object; +static CLabel *sinit_label; +static Boolean ainit_only_one; +static ENode *ainit_expr; +static FuncArg *check_arglist; +static Boolean cfunc_is_extern_c; +static short cfunc_staticvarcount; +static void *destroyobjects; +static Boolean cfunc_hasdtortemp; + +static void CFunc_LoopIncrement(void) {} +static void CFunc_LoopDecrement(void) {} +DeclBlock *CFunc_NewDeclBlock(void) {} +void CFunc_RestoreBlock(DeclBlock *block) {} +void CFunc_SetupLocalVarInfo(Object *obj) {} +static void adjustargumenttype(DeclInfo *declinfo) {} +static FuncArg *CFunc_IsInArgList(FuncArg *list, HashNameNode *name) {} +static Object *CFunc_IsInObjList(ObjectList *list, HashNameNode *name) {} +static void CFunc_AppendArg(FuncArg **list, FuncArg *arg) {} +static void identifier_list(DeclInfo *declinfo) {} +static Boolean defarg_name_obj_check(HashNameNode *name, Object *obj) {} +void CFunc_DefaultArg(Type *type, short qual, FuncArg *args) {} +static FuncArg *parameter_list(DeclInfo *declinfo) {} +Boolean CFunc_ParseFakeArgList(Boolean flag) {} +FuncArg *parameter_type_list(DeclInfo *declinfo) {} +CLabel *findlabel(void) {} +CLabel *newlabel(void) {} +Statement *CFunc_AppendStatement(StatementType sttype) {} +Statement *CFunc_InsertStatement(StatementType sttype, Statement *after) {} +Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before) {} +void CheckCLabels(void) {} +Object *create_temp_object(Type *type) {} +ENode *create_temp_node(Type *type) {} +ENode *create_temp_node2(Type *type) {} +static void CFunc_DestroyReverse() {} // not sure about type +static void CFunc_TempTransDestroy() {} // not sure about type +void CFunc_WarnUnused(void) {} +void CFunc_CodeCleanup(Statement *stmt) {} +static Boolean DestructorNeeded(ExceptionAction *a, ExceptionAction *b) {} +static Statement *DestructLocals(Statement *stmt, ExceptionAction *exc1, ExceptionAction *exc2) {} +static Boolean NeedsDestruction(Statement *stmt1, Statement *stmt2) {} +static ExceptionAction *FindLastNonCommonStackObj(Statement *stmt1, Statement *stmt2) {} +static void DestructorReturnTransform(Statement *stmt1, Statement *stmt2) {} +static Statement *DestructorIfTransform(Statement *stmt) {} +static Boolean IsSubStack(ExceptionAction *exc1, ExceptionAction *exc2) {} +static void CFunc_CheckInitSkip(Statement *stmt, ExceptionAction *exc) {} +void CFunc_DestructorCleanup(Statement *stmt) {} +static void scancase(DeclThing *thing) {} +static void CFunc_NameLocalStaticDataObject(Object *obj, char *str) {} +static void sinit_insert_expr(ENode *expr) {} +static void ainit_insert_expr(ENode *expr) {} +static ENode *ainit_register_object(TypeClass *tclass, Object *local, SInt32 offset, void *unk) {} +static void CFunc_LocalDataDeclarator(DeclInfo *declinfo, TStreamElement *element, Boolean flag1, Boolean flag2) {} +static ENode *CFunc_ParseLocalDeclarationList(Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) {} +static void makeifstatement(ENode *expr, CLabel *label1, CLabel *label2, Boolean flag1, Boolean flag2) {} +static void CFunc_HasDtorTempCallBack(ENode *expr) {} +static void ifstatement(Boolean flag1, ENode *expr, CLabel *label, Boolean flag2) {} +Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode (*callback)(ENode *, ENode *)) {} +static Boolean checklabel(void) {} +static ENode *returnstatementadjust(ENode *expr, Type *type, UInt32 qual) {} +static void CFunc_AutoResultCheck(ENode *expr) {} +static void statement(DeclThing *thing) {} +void CFunc_CompoundStatement(DeclThing *thing) {} +static void CFunc_InsertArgumentCopyConversion(Object *obj, Type *type1, Type *type2, Boolean flag) {} +static void CFunc_AdjustOldStyleArgs(void) {} +void CFunc_SetupNewFuncArgs(Object *obj, FuncArg *args) {} +static ObjectList *CFunc_CopyObjectList(ObjectList *list) {} +static void SetupFunctionArguments(Object *obj, DeclInfo *declinfo) {} +NameSpace *CFunc_FuncGenSetup(Statement *stmt) {} +void CFunc_GetGlobalCompilerState(CFuncSave *state) {} +void CFunc_SetGlobalCompilerState(CFuncSave *state) {} +void CFunc_Gen(Statement *stmt, Object *obj, UInt8 unk) {} +static void CFunc_CheckCtorInitializer(TypeClass *tclass, CtorChain *chain) {} +void CFunc_CheckClassCtors(TypeClass *tclass) {} +static void CFunc_ParseCtorInitializer(void) {} +static void CFunc_FunctionRedefinedCheck(Object *obj) {} +static Object *CFunc_DeclareFuncName(char *str, HashNameNode *name) {} +void CFunc_ParseFuncDef(Object *obj, DeclInfo *declinfo, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace) {} +void InitExpr_Register(ENode *expr, Object *object) {} +void CFunc_GenerateDummyFunction(Object *a) {} +void CFunc_GenerateSingleExprFunc(Object *a, ENode *expr) {} +void CFunc_GenerateDummyCtorFunc(Object *a, Object *b) {} diff --git a/compiler_and_linker/unsorted/CInit.c b/compiler_and_linker/unsorted/CInit.c new file mode 100644 index 0000000..a305c38 --- /dev/null +++ b/compiler_and_linker/unsorted/CInit.c @@ -0,0 +1,3107 @@ +#include "compiler/CInit.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +// TODO - move me!! +extern void PreComp_StaticData(Object *obj, void *data, OLinkList *list, SInt32 size); +extern void ObjGen_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size); +extern void ObjGen_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size); +extern void CExcept_RegisterDestructorObject(Object *obj, SInt32 offset, Object *dtor, Boolean flag); +extern void CExcept_RegisterLocalArray(Statement *stmt, Object *obj, Object *dtor, SInt32 count, SInt32 size); + +TempNodeCB cinit_tempnodefunc; +InitInfo *cinit_initinfo; +static PooledString *cinit_stringlist; +static PooledString *cinit_pooledstringlist; +static PooledString *cinit_pooledwstringlist; +static ObjectList *cinit_tentative; +static TypeClass *cinit_loop_class; +static ENodeList *cinit_fdtnode; +static Boolean cinit_fdtambig; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CInit_1C { + struct CInit_1C *next; + Type *type; + ENode *expr; + SInt32 offset; +} CInit_1C; + +typedef struct CInit_Stuff { + struct CInit_Stuff *x0; + struct CInit_Stuff *x4; + char *buffer; + SInt32 xC; + SInt32 size; + SInt32 bufferSize; + SInt32 x18; + CInit_1C *x1C; + OLinkList *list; + Boolean flag; +} CInit_Stuff; + +typedef enum { + Stage0, + Stage1, + Stage2, + Stage3, + Stage4 +} Stage; + +typedef struct CInit_Stuff2 { + ENode *expr; + ENode myexpr; + Stage stage; + Boolean x23; + SInt32 x24; + Type *type; +} CInit_Stuff2; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean flag); +static void CInit_Type(Type *type, UInt32 qual, Boolean flag); + +void CInit_Init(void) { + cinit_tempnodefunc = NULL; + cinit_initinfo = NULL; + cinit_stringlist = NULL; + cinit_pooledstringlist = NULL; + cinit_pooledwstringlist = NULL; + cinit_tentative = NULL; +} + +static void CInit_SetupInitInfo(InitInfo *info, Object *obj) { + memclrw(info, sizeof(InitInfo)); + info->obj = obj; + info->next = cinit_initinfo; + cinit_initinfo = info; +} + +static void CInit_CleanupInitInfo(InitInfo *info) { + cinit_initinfo = info->next; +} + +static void CInit_SetupInitInfoBuffer(Type *type) { + SInt32 size = type->size; + cinit_initinfo->size = size; + + if (!size) + size = 512; + else if (size & 1) + size++; + + cinit_initinfo->buffer = lalloc(size); + cinit_initinfo->bufferSize = size; + memclrw(cinit_initinfo->buffer, size); +} + +static void CInit_SetData(void *data, SInt32 offset, SInt32 size) { + SInt32 end; + char *buffer; + + end = offset + size; + if (end > cinit_initinfo->size) + cinit_initinfo->size = end; + + if (end > cinit_initinfo->bufferSize) { + if (cinit_initinfo->obj->type->size == 0) { + if (end < 8000) + end += 0x400; + else + end += 0x4000; + } + if (end & 1) + end++; + + buffer = lalloc(end); + memclrw(buffer, end); + memcpy(buffer, cinit_initinfo->buffer, cinit_initinfo->bufferSize); + cinit_initinfo->buffer = buffer; + cinit_initinfo->bufferSize = end; + } + + if (data) + memcpy(cinit_initinfo->buffer + offset, data, size); +} + +typedef struct CInit_Initializer { + struct CInit_Initializer *next; + struct CInit_Initializer *sublist; + ENode *expr; + TStreamElement element; +} CInit_Initializer; + +static CInit_Initializer *CInit_ParseInitializerList(void) { + CInit_Initializer *r30; + CInit_Initializer *r29; + CInit_Initializer *tmp; + + if ((tk = lex()) == '}') + return NULL; + + r30 = NULL; + do { + if (r30) { + tmp = lalloc(sizeof(CInit_Initializer)); + r29->next = tmp; + r29 = tmp; + } + if (!r30) { + r30 = r29 = lalloc(sizeof(CInit_Initializer)); + } + r29->next = NULL; + + if (tk == '{') { + r29->element = *CPrep_CurStreamElement(); + r29->sublist = CInit_ParseInitializerList(); + r29->expr = NULL; + tk = lex(); + } else { + r29->sublist = NULL; + r29->expr = conv_assignment_expression(); + r29->element = *CPrep_CurStreamElement(); + } + + if (tk == '}') + return r30; + + if (tk != ',') { + CError_Error(116); + return r30; + } + } while ((tk = lex()) != '}'); + + return r30; +} + +static CInit_Initializer *CInit_ParseInitializerClause(void) { + CInit_Initializer *init; + + init = lalloc(sizeof(CInit_Initializer)); + init->next = NULL; + if (tk != '{') { + init->sublist = NULL; + init->expr = conv_assignment_expression(); + init->element = *CPrep_CurStreamElement(); + } else { + init->element = *CPrep_CurStreamElement(); + init->expr = NULL; + init->sublist = CInit_ParseInitializerList(); + tk = lex(); + } + + return init; +} + +static ENode *CInit_ParseInitializer(ENode *expr) { + CInt64 save_int; + Float save_float; + SInt32 save_size; + short t; + + switch (tk) { + case TK_INTCONST: + case TK_FLOATCONST: + save_int = tkintconst; + save_float = tkfloatconst; + save_size = tksize; + t = lookahead(); + tkintconst = save_int; + tkfloatconst = save_float; + tksize = save_size; + + switch (t) { + case ',': + case ';': + case '}': + memclrw(expr, sizeof(ENode)); + switch (tk) { + case TK_INTCONST: + expr->type = EINTCONST; + expr->rtype = atomtype(); + expr->data.intval = tkintconst; + break; + case TK_FLOATCONST: + expr->type = EFLOATCONST; + expr->rtype = atomtype(); + expr->data.floatval = tkfloatconst; + break; + } + tk = lex(); + CPrep_TokenStreamFlush(); + return expr; + } + } + + expr = assignment_expression(); + CPrep_TokenStreamFlush(); + return expr; +} + +static Stage CInit_ParseNextInit(CInit_Stuff2 *s) { + DeclInfo di; + short t; + + s->expr = NULL; + if (tk == ';') { + s->stage = Stage4; + return Stage4; + } + switch (s->stage) { + case Stage0: + if (s->x23) { + if (tk == '(') { + tk = lex(); + CParser_GetDeclSpecs(&di, 1); + s->type = di.thetype; + if (tk == ')') + tk = lex(); + else + CError_Error(115); + + if (tk == '(') + tk = lex(); + else + CError_Error(114); + s->x24++; + t = lookahead(); + if (t == TK_UU_VECTOR || (t == TK_IDENTIFIER && !strcmp("vector", tkidentifier->name))) + CInit_ParseNextInit(s); + s->stage = Stage1; + return Stage1; + } + } else { + if (tk == '{') { + tk = lex(); + s->x24 = 0; + s->stage = Stage1; + return Stage1; + } + } + s->expr = CInit_ParseInitializer(&s->myexpr); + s->stage = Stage2; + return Stage2; + case Stage1: + break; + case Stage2: + case Stage3: + if (tk == ',') { + tk = lex(); + break; + } + if (s->x24) { + if (tk != ')') + CError_Error(174); + if (s->x24 > 1) { + s->x24--; + tk = lex(); + CInit_ParseNextInit(s); + } + } else { + if (tk != '}') + CError_Error(174); + } + s->stage = Stage3; + return Stage3; + default: +#line 389 + CError_FATAL(); + } + + switch (tk) { + case '{': + tk = lex(); + s->stage = Stage1; + return Stage1; + case '}': + s->stage = Stage3; + return Stage3; + case '(': + if (s->x23) { + tk = lex(); + s->stage = Stage1; + return Stage1; + } + case ')': + if (s->x23 && s->x24) { + if (s->x24 > 1) { + s->x24--; + tk = lex(); + CInit_ParseNextInit(s); + } + s->stage = Stage3; + return Stage3; + } + default: + s->expr = CInit_ParseInitializer(&s->myexpr); + s->stage = Stage2; + return Stage2; + } +} + +static void CInit_CloseInitList(void) { + if (tk == ',' && copts.cplusplus) + tk = lex(); + + if (tk != '}') + CError_ErrorSkip(130); + else + tk = lex(); +} + +static Boolean CInit_IsAllZero(char *buf, SInt32 size) { + SInt32 i; + + if (copts.explicit_zero_data) + return 0; + + for (i = 0; i < size; i++) + if (buf[i]) return 0; + + return 1; +} + +static Boolean CInit_ClassNeedsConstruction(TypeClass *tclass) { + return CClass_Constructor(tclass) || CClass_Destructor(tclass); +} + +static Boolean CInit_IsSimpleStructArrayInit(Type *type) { + switch (type->type) { + case TYPESTRUCT: + return 1; + case TYPEARRAY: + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IS_TYPE_CLASS(type)) + return 1; + case TYPECLASS: + return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); + default: + return 0; + } +} + +static Boolean CInit_IsSimpleInit(Type *type) { + switch (type->type) { + case TYPEPOINTER: + return (TYPE_POINTER(type)->qual & Q_REFERENCE) == 0; + case TYPEARRAY: + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IS_TYPE_CLASS(type)) + return 1; + case TYPECLASS: + return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); + default: + return 1; + } +} + +static Object *CInit_GetInitObject(Object *obj) { + if (obj->datatype == DALIAS) { +#line 521 + CError_ASSERT(!obj->u.alias.offset); + obj = obj->u.alias.object; + } + return obj; +} + +static Object *CInit_CreateStaticDataObject(Type *type, UInt32 qual, HashNameNode *name) { + Object *obj; + DeclInfo di; + + memclrw(&di, sizeof(DeclInfo)); + di.thetype = type; + di.name = name ? name : CParser_GetUniqueName(); + di.qual = qual; + di.storageclass = TK_STATIC; + di.x4E = 1; + + obj = CParser_NewGlobalDataObject(&di); + obj->nspace = cscope_root; + return obj; +} + +static Type *CInit_GetRegMemType() { + return CDecl_NewStructType(void_ptr.size * 3, CMach_GetTypeAlign((Type *) &void_ptr)); +} + +static Object *CInit_CreateStaticData(Type *type) { + Object *obj = CInit_CreateStaticDataObject(type, 0, NULL); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + return obj; +} + +static void CInit_InitNonConst(CInit_Stuff *s, Type *type, ENode *expr) { + CInit_1C *entry; + CInit_1C *scan; + MWVector128 *vec; + + if (s->x4->flag || IS_TYPE_VECTOR(type)) { + if (IS_TYPE_VECTOR(type) && ENODE_IS(expr, EVECTOR128CONST)) { + vec = (MWVector128 *) (s->buffer + s->size); + *vec = expr->data.vector128val; + CMach_InitVectorMem(type, *vec, vec, 1); + } + + entry = lalloc(sizeof(CInit_1C)); + memclrw(entry, sizeof(CInit_1C)); + entry->next = NULL; + entry->type = type; + entry->expr = expr; + entry->offset = s->xC + s->size; + if ((scan = s->x4->x1C)) { + while (scan->next) + scan = scan->next; + scan->next = entry; + } else { + s->x4->x1C = entry; + } + } else { + CError_Error(124); + } +} + +static CInit_Stuff *CInit_GrowBuffer(CInit_Stuff *s, SInt32 size) { + CInit_Stuff *newbuf; + + newbuf = lalloc(sizeof(CInit_Stuff)); + memclrw(newbuf, sizeof(CInit_Stuff)); + newbuf->x4 = s->x4; + newbuf->buffer = lalloc(size); + newbuf->xC = s->xC + s->size; + newbuf->bufferSize = size; + s->x0 = newbuf; + memset(newbuf->buffer, 0, newbuf->bufferSize); + return newbuf; +} + +Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag) { + Object *objcheck1; + Object *objcheck2; + CInt64 valcheck1; + CInt64 valcheck2; + + *objptr = NULL; + valptr->lo = 0; + valptr->hi = 0; + + while (1) { + switch (expr->type) { + case EINTCONST: + *valptr = expr->data.intval; + return 1; + case EOBJREF: + objcheck1 = CInit_GetInitObject(expr->data.objref); + if (objcheck1->datatype == DLOCAL && !flag) + return 0; + *objptr = objcheck1; + return 1; + case ESTRINGCONST: + CInit_RewriteString(expr, 0); + continue; + case ETYPCON: + do { + if (expr->rtype->size != expr->data.monadic->rtype->size) + return 0; + expr = expr->data.monadic; + if (!IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_INT(expr->rtype)) + return 0; + } while (ENODE_IS(expr, ETYPCON)); + continue; + case EADD: + if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) + return 0; + if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) + return 0; + + if (objcheck1) { + if (objcheck2) + return 0; + *objptr = objcheck1; + } else { + *objptr = objcheck1; + } + + *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '+', valcheck2); + return 1; + case ESUB: + if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) + return 0; + if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) + return 0; + + if (objcheck2) + return 0; + + *objptr = objcheck1; + *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '-', valcheck2); + return 1; + default: + return 0; + } + } +} + +static void CInit_InitTypePointer(CInit_Stuff *s, ENode *expr, TypePointer *tptr, UInt32 qual) { + Object *obj; + CInt64 val; + OLinkList *list; + + expr = CExpr_AssignmentPromotion(expr, TYPE(tptr), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_POINTER_ONLY(expr->rtype) || ENODE_IS(expr, EINTCONST)) { + if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { + if (obj) { + list = lalloc(sizeof(OLinkList)); + list->next = s->x4->list; + list->obj = obj; + list->somevalue = CInt64_GetULong(&val); + list->offset = s->xC + s->size; + s->x4->list = list; + } else { + CMach_InitIntMem(TYPE(&stunsignedlong), val, s->buffer + s->size); + } + } else { + CInit_InitNonConst(s, TYPE(tptr), expr); + } + } else { + CError_Error(174); + } +} + +static void CInit_InitTypeInt(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(tint), expr->data.intval, s->buffer + s->size); + } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) { + CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual); + } else { + CInit_InitNonConst(s, TYPE(tint), expr); + } + } else { + CError_Error(174); + } +} + +static void CInit_InitTypeFloat(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_FLOAT(expr->rtype)) { + if (ENODE_IS(expr, EFLOATCONST)) { + CMach_InitFloatMem(TYPE(tint), expr->data.floatval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tint), expr); + } + } else { + CError_Error(174); + } +} + +static void CInit_InitTypeEnum(CInit_Stuff *s, ENode *expr, TypeEnum *tenum, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tenum), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_ENUM(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(tenum->enumtype, expr->data.intval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tenum), expr); + } + } else { + CError_Error(174); + } +} + +static void CInit_InitTypeMemberPointer(CInit_Stuff *s, ENode *expr, TypeMemberPointer *tmptr, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tmptr), qual & (Q_CONST | Q_VOLATILE), 1); + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tmptr), expr); + } +} + +static void CInit_SetBitfield(TypeBitfield *tbitfield, UInt8 *buffer, CInt64 val) { + int i; + int pos; + int step; + + if (copts.little_endian) { + pos = tbitfield->unkA; + step = 1; + } else { + pos = tbitfield->unkB + tbitfield->unkA - 1; + step = -1; + } + for (i = 0; i < tbitfield->unkB; i++) { + if (CInt64_GetULong(&val) & 1) { + if (copts.little_endian) { + buffer[pos >> 3] |= 1 << (pos & 7); + } else { + buffer[pos >> 3] |= 0x80 >> (pos & 7); + } + } + val = CInt64_ShrU(val, cint64_one); + pos += step; + } +} + +static void CInit_InitTypeBitfield(CInit_Stuff *s, ENode *expr, TypeBitfield *tbitfield, UInt32 qual) { + Type *inner; + + inner = tbitfield->bitfieldtype; + if (IS_TYPE_ENUM(inner)) + inner = TYPE_ENUM(inner)->enumtype; + expr = CExpr_AssignmentPromotion(expr, inner, qual & (Q_CONST | Q_VOLATILE), 1); + + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CInit_SetBitfield(tbitfield, (UInt8 *) s->buffer + s->size, expr->data.intval); + } else { + CInit_InitNonConst(s, TYPE(tbitfield), expr); + } + } else { + CError_Error(174); + } +} + +static void CInit_InitTypeArray(CInit_Stuff *s, CInit_Stuff2 *s2, TypePointer *tptr, UInt32 qual, Boolean errorflag) { + SInt32 targetsize; + SInt32 start; + SInt32 i; + Boolean flag; + Boolean is_zero_size; + SInt32 size; + SInt32 tmp; + Boolean is_char_ptr; + Boolean is_wchar_ptr; + + is_zero_size = tptr->size == 0; + targetsize = tptr->target->size; + if (!targetsize) { + CError_Error(145); + return; + } + + is_char_ptr = IS_TYPE_INT(tptr->target) && (targetsize == 1); + is_wchar_ptr = IS_TYPE_INT(tptr->target) && (targetsize == stwchar.size); + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + if (is_zero_size) + CError_Error(174); + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(174); + return; + } + + if (s2->stage == Stage2) + s2->expr = pointer_generation(s2->expr); + + if (s2->stage == Stage2 && ENODE_IS(s2->expr, ESTRINGCONST) && (is_char_ptr || is_wchar_ptr)) { + if (IS_TYPE_POINTER_ONLY(s2->expr->rtype) && tptr->target->size != TYPE_POINTER(s2->expr->rtype)->target->size) + CError_Warning(174); + size = tmp = s2->expr->data.string.size; + if (is_zero_size) { + tptr->size = s2->expr->data.string.size; + if (s->bufferSize < tmp) + s = CInit_GrowBuffer(s, tmp); + memcpy(s->buffer, s2->expr->data.string.data, size); + s->size = size; + } else { + if (s2->expr->data.string.size > tptr->size) { + if (copts.cplusplus || (s2->expr->data.string.size - 1) > tptr->size) + CError_Error(147); + s2->expr->data.string.size = tptr->size; + size = tptr->size; + } + memcpy(s->buffer + s->size, s2->expr->data.string.data, size); + } + } else { + if (!flag && errorflag) { + CError_Error(174); + return; + } + + start = s->size; + i = 0; + while (1) { + if (is_zero_size) { + size = (i + 1) * targetsize; + s->size = start + size - targetsize - s->xC; + if (s->size + targetsize > s->bufferSize) + s = CInit_GrowBuffer(s, targetsize * 16); + CInit_InitType(s, s2, tptr->target, qual, 0); + tptr->size = size; + s->size = start + size - s->xC; + } else { + if (tptr->size <= i * targetsize) { + i--; + CError_Error(147); + } + s->size = start + i * targetsize; + CInit_InitType(s, s2, tptr->target, qual, 0); + if (!flag && tptr->size <= (i + 1) * targetsize) + break; + } + + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + break; + case Stage3: + if (flag) + tk = lex(); + return; + default: + CError_Error(130); + return; + } + + i++; + } + } + + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + return; + case Stage2: + CError_Error(147); + return; + default: + CError_Error(130); + } + } +} + +static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, TypeStruct *tstruct, UInt32 qual, Boolean errorflag) { + StructMember *member; + SInt32 start; + Boolean flag; + SInt32 count; + TypePointer arraytype; + MWVector128 *vecp; + int i; + + count = 0; + if (s2->type) + tstruct = TYPE_STRUCT(s2->type); + + if (!(member = tstruct->members)) { + CError_Error(145); + return; + } + + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(174); + return; + } + + if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tstruct))) { + s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tstruct), qual, 1); + if (IS_TYPE_STRUCT(s2->expr->rtype)) + CInit_InitNonConst(s, TYPE(tstruct), s2->expr); + return; + } + + start = s->size; + while (1) { + s->size = start + member->offset; + if (!member->type->size) { + if (!errorflag || !IS_TYPE_ARRAY(member->type)) { + CError_Error(147); + if (!IS_TYPE_ARRAY(member->type)) + return; + } + + arraytype = *TYPE_POINTER(member->type); + CInit_InitTypeArray(s, s2, &arraytype, member->qual, 1); + s->x18 = arraytype.size; + } else { + CInit_InitType(s, s2, member->type, member->qual, 0); + } + + count++; + if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) { +#line 1218 + CError_ASSERT(!ENODE_IS(s2->expr, EVECTOR128CONST)); + } + + do { + member = member->next; + } while (member && (member->qual & Q_OVERLOAD)); + + if (!member || tstruct->stype == STRUCT_TYPE_UNION) { + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + if (IS_TYPESTRUCT_VECTOR(tstruct)) { + vecp = (MWVector128 *) (s->buffer + start); + CMach_InitVectorMem(TYPE(tstruct), *vecp, vecp, 0); + } + tk = lex(); + return; + case Stage2: + CError_Error(147); + return; + default: + CError_Error(130); + return; + } + } + return; + } else { + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + continue; + case Stage3: + if (flag) + tk = lex(); + if (IS_TYPESTRUCT_VECTOR(tstruct)) { + switch (TYPE_STRUCT(tstruct)->stype) { + case STRUCT_TYPE_4: + case STRUCT_TYPE_5: + case STRUCT_TYPE_6: + if (count != 16) { + if (count == 1) { + UInt8 val, *p; + p = (UInt8 *) s->buffer; + val = p[0]; + for (i = 1; i < 16; i++) + p[i] = val; + } else { + CError_Error(174); + } + } + break; + case STRUCT_TYPE_7: + case STRUCT_TYPE_8: + case STRUCT_TYPE_9: + case STRUCT_TYPE_E: + if (count != 8) { + if (count == 1) { + SInt16 val, *p; + p = (SInt16 *) s->buffer; + val = p[0]; + for (i = 1; i < 8; i++) + p[i] = val; + } else { + CError_Error(174); + } + } + break; + case STRUCT_TYPE_A: + case STRUCT_TYPE_B: + case STRUCT_TYPE_C: + case STRUCT_TYPE_D: + if (count != 4) { + if (count == 1) { + UInt32 val, *p; + p = (UInt32 *) s->buffer; + val = p[0]; + for (i = 1; i < 4; i++) + p[i] = val; + } else { + CError_Error(174); + } + } + break; + } + } + return; + default: + CError_Error(174); + return; + } + } + } +} + +static ObjMemberVar *CInit_FindNextMember(ObjMemberVar *ivar) { + ObjMemberVar *scan = ivar; + while (1) { + scan = scan->next; + if (!scan) + return NULL; + if (!scan->anonunion) + return scan; + if (scan->offset > ivar->offset) + return scan; + if (IS_TYPE_BITFIELD(scan->type) && IS_TYPE_BITFIELD(ivar->type) && TYPE_BITFIELD(scan->type)->unkA != TYPE_BITFIELD(ivar->type)->unkA) + return scan; + } +} + +static void CInit_InitTypeClass(CInit_Stuff *s, CInit_Stuff2 *s2, TypeClass *tclass, UInt32 qual, Boolean errorflag) { + ObjMemberVar *ivar; + SInt32 start; + Boolean flag; + SInt32 last_offset; + TypePointer arraytype; + + if (tclass->bases || tclass->vtable) { + CError_Error(174); + return; + } + + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(174); + return; + } + + if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tclass) || CExpr_CanImplicitlyConvert(s2->expr, TYPE(tclass), 0))) { + s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tclass), qual, 1); + if (IS_TYPE_CLASS(s2->expr->rtype)) + CInit_InitNonConst(s, TYPE(tclass), s2->expr); + return; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->access != ACCESSPUBLIC) { + CError_Error(174); + break; + } + } + + if (!(ivar = tclass->ivars)) { + CError_Error(147); + return; + } + start = s->size; + while (1) { + s->size = start + ivar->offset; + if (!ivar->type->size) { + if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) { + CError_Error(147); + if (!IS_TYPE_ARRAY(ivar->type)) + return; + } + + arraytype = *TYPE_POINTER(ivar->type); + CInit_InitTypeArray(s, s2, &arraytype, ivar->qual, 1); + s->x18 = arraytype.size; + } else { + CInit_InitType(s, s2, ivar->type, ivar->qual, 0); + } + + last_offset = ivar->offset; + if (!(ivar = CInit_FindNextMember(ivar)) || (tclass->mode == CLASS_MODE_1 && ivar->offset == last_offset)) { + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + return; + case Stage2: + CError_Error(147); + return; + default: + CError_Error(130); + return; + } + } + return; + } else { + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + continue; + case Stage3: + if (flag) + tk = lex(); + break; + default: + CError_Error(174); + } + return; + } + } +} + +static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean errorflag) { + Boolean flag; + + switch (type->type) { + case TYPEVOID: + CError_Error(174); + break; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEBITFIELD: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + switch (s2->stage) { + case Stage1: + flag = 1; + CInit_ParseNextInit(s2); + break; + case Stage2: + flag = 0; + break; + } + if (s2->stage != Stage2) { + CError_Error(174); + return; + } + + switch (type->type) { + case TYPEINT: + CInit_InitTypeInt(s, s2->expr, TYPE_INTEGRAL(type), qual); + break; + case TYPEFLOAT: + CInit_InitTypeFloat(s, s2->expr, TYPE_INTEGRAL(type), qual); + break; + case TYPEENUM: + CInit_InitTypeEnum(s, s2->expr, TYPE_ENUM(type), qual); + break; + case TYPEPOINTER: + CInit_InitTypePointer(s, s2->expr, TYPE_POINTER(type), qual); + break; + case TYPEMEMBERPOINTER: + CInit_InitTypeMemberPointer(s, s2->expr, TYPE_MEMBER_POINTER(type), qual); + break; + case TYPEBITFIELD: + CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual); + break; + default: +#line 1542 + CError_FATAL(); + } + + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + break; + case Stage2: + CError_Error(147); + break; + default: + CError_Error(130); + } + } + break; + case TYPESTRUCT: + CInit_InitTypeStruct(s, s2, TYPE_STRUCT(type), qual, errorflag); + break; + case TYPEARRAY: + CInit_InitTypeArray(s, s2, TYPE_POINTER(type), qual, errorflag); + break; + case TYPECLASS: + CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag); + break; + default: +#line 1573 + CError_FATAL(); + } +} + +static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag) { + CInit_Stuff2 s2; + SInt32 size; + CInit_Stuff *tmp; + char *buffer; + + locklheap(); + memclrw(s, sizeof(CInit_Stuff)); + s->x4 = s; + if (type->size == 0) { + if (IS_TYPE_ARRAY(type)) + s->bufferSize = 16 * TYPE_POINTER(type)->target->size; + else + CError_Error(145); + } else { + s->bufferSize = type->size; + } + + s->buffer = lalloc(s->bufferSize); + memset(s->buffer, 0, s->bufferSize); + s->flag = flag; + + s2.stage = Stage0; + s2.x23 = 0; + if (IS_TYPE_VECTOR(type)) { + s2.x23 = 1; + s->flag = 1; + } + if (IS_TYPE_ARRAY(type) && IS_TYPE_VECTOR(TYPE_POINTER(type)->target)) { + s->flag = 1; + } + + s2.type = NULL; + s2.x24 = 0; + CInit_ParseNextInit(&s2); + CInit_InitType(s, &s2, type, qual, 1); + + if ((size = type->size + s->x18)) { + if (s->x0) { + buffer = lalloc(size); + for (tmp = s; tmp; tmp = tmp->x0) { +#line 1647 + CError_ASSERT((tmp->xC + tmp->size) <= size); + memcpy(buffer + tmp->xC, tmp->buffer, tmp->size); + } + s->buffer = buffer; + } + } else { + CError_Error(174); + } + + s->size = size; + s->x0 = NULL; + unlocklheap(); +} + +static ENode *CInit_InitConcat(ENode *a1, ENode *a2, SInt32 offset, Type *type, ENode *a5) { + ENode *r30; + ENode *r28; + ENode *tmp; + + r28 = lalloc(sizeof(ENode)); + *r28 = *a2; + if (offset) + r28 = makediadicnode(r28, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + if (IS_TYPE_BITFIELD(type)) { + tmp = makemonadicnode(r28, EBITFIELD); + tmp->rtype = type; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = TYPE_BITFIELD(type)->bitfieldtype; + } else { + tmp = makemonadicnode(r28, EINDIRECT); + tmp->rtype = type; + } + + r30 = makediadicnode(tmp, a5, EASS); + if (!a1) { + return r30; + } else { + tmp = makediadicnode(a1, r30, ECOMMA); + tmp->rtype = r30->rtype; + return tmp; + } +} + +static ENode *CInit_RegisterDtorObject(Type *type, Object *dtor, ENode *objexpr) { + ENode *expr; + + if (copts.no_static_dtors) + return objexpr; + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->flags = 0; + expr->rtype = CDecl_NewPointerType(type); + expr->data.funccall.funcref = create_objectrefnode(Xgreg_func); + expr->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); + expr->data.funccall.args = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->node = objexpr; + expr->data.funccall.args->next = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, 1)); + expr->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())); + expr->data.funccall.args->next->next->next = NULL; + + return expr; +} + +static Boolean CInit_ConstructGlobalObject(Object *obj, TypeClass *tclass, ENode *valueexpr, SInt32 offset, Boolean flag) { + Object *ctor; + Object *dtor; + ENodeList *list; + ENode *expr; + Boolean ctorflag; + + ctor = CClass_Constructor(tclass); + dtor = CClass_Destructor(tclass); + if (!ctor && !dtor) + return 0; + + if (flag && !ctor && tk == '=' && lookahead() == '{') + return 0; + + if (flag && tk == '(') { + tk = lex(); + list = CExpr_ScanExpressionList(1); + if (tk == ')') + tk = lex(); + else + CError_Error(115); + } else if (valueexpr) { + list = lalloc(sizeof(ENodeList)); + list->node = valueexpr; + list->next = NULL; + } else { + list = NULL; + } + + expr = create_objectrefnode(obj); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + if (ctor) { + ctorflag = 1; + if (tk == '=') { + ctorflag = 0; + if (list) + CError_Error(174); + + list = lalloc(sizeof(ENodeList)); + list->next = NULL; + tk = lex(); + list->node = conv_assignment_expression(); + } + + expr = CExpr_ConstructObject(tclass, expr, list, 0, 1, 0, 1, ctorflag); + if (expr->rtype->type != TYPEPOINTER) { + CError_Error(174); + return 1; + } + } else { + if (list) + CError_Error(174); + } + + if (dtor) + expr = CInit_RegisterDtorObject(TYPE(tclass), dtor, expr); + + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, obj); + + return 1; +} + +static Boolean CInit_ConstructAutoObject(TypeClass *tclass, ENode *expr, SInt32 offset, Boolean flag) { + ENodeList *r30; + ENode *r29; + Object *ctor; + Object *dtor; + Boolean r24; + + ctor = CClass_Constructor(tclass); + dtor = CClass_Destructor(tclass); + if (!ctor && !dtor) + return 0; + + if (dtor) + CClass_CheckStaticAccess(NULL, tclass, dtor->access); + + if (flag && !ctor && tk == '=' && lookahead() == '{') + return 0; + + if (flag && tk == '(') { + tk = lex(); + r30 = CExpr_ScanExpressionList(1); + if (tk == ')') + tk = lex(); + else + CError_Error(115); + } else if (expr) { + r30 = lalloc(sizeof(ENodeList)); + r30->node = expr; + r30->next = NULL; + } else { + r30 = NULL; + } + + if (ctor) { + r24 = 1; + if (tk == '=') { + if (r30) + CError_Error(174); + r30 = lalloc(sizeof(ENodeList)); + r30->next = NULL; + tk = lex(); + r30->node = conv_assignment_expression(); + r24 = 0; + } + + if (!dtor) { + r29 = create_objectrefnode(cinit_initinfo->obj1C); + if (offset) + r29 = makediadicnode(r29, intconstnode(TYPE(&stunsignedlong), offset), EADD); + } else { + r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); + } + + r29 = CExpr_ConstructObject(tclass, r29, r30, 0, 1, 0, 1, r24); + if (!IS_TYPE_POINTER_ONLY(r29->rtype)) { + CError_Error(174); + return 1; + } + r29 = makemonadicnode(r29, EINDIRECT); + r29->rtype = TYPE_POINTER(r29->rtype)->target; + cinit_initinfo->insert_expr_cb(r29); + } else { + if (r30) + CError_Error(174); + if (dtor) + r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); + cinit_initinfo->insert_expr_cb(r29); + } + + return 1; +} + +static void CInit_ExprPointer(TypePointer *tptr, ENode *expr) { + Object *obj; + CInt64 val; + OLinkList *list; + + if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { + if (obj) { + list = lalloc(sizeof(OLinkList)); + list->next = cinit_initinfo->list; + list->obj = obj; + list->somevalue = CInt64_GetULong(&val); + list->offset = cinit_initinfo->expr_offset; + cinit_initinfo->list = list; + } else { + CMach_InitIntMem(TYPE(&stunsignedlong), val, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tptr), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + + cinit_initinfo->expr_offset += 4; +} + +static void CInit_ExprInt(TypeIntegral *tint, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(tint), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSI_strict)) { + CInit_ExprPointer(TYPE_POINTER(expr->data.monadic->rtype), expr->data.monadic); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tint), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + + cinit_initinfo->expr_offset += tint->size; +} + +static void CInit_ExprFloat(TypeIntegral *tint, ENode *expr) { + if (ENODE_IS(expr, EFLOATCONST)) { + CMach_InitFloatMem(TYPE(tint), expr->data.floatval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tint), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + + cinit_initinfo->expr_offset += tint->size; +} + +static void CInit_ExprEnum(TypeEnum *tenum, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(tenum->enumtype, expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tenum), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + + cinit_initinfo->expr_offset += tenum->size; +} + +static void CInit_ExprMemberPointer(TypeMemberPointer *tmptr, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tmptr), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + + cinit_initinfo->expr_offset += tmptr->size; +} + +static void CInit_TypeExpr(Type *type, ENode *expr) { + switch (type->type) { + case TYPEINT: + CInit_ExprInt(TYPE_INTEGRAL(type), expr); + break; + case TYPEFLOAT: + CInit_ExprFloat(TYPE_INTEGRAL(type), expr); + break; + case TYPEENUM: + CInit_ExprEnum(TYPE_ENUM(type), expr); + break; + case TYPEPOINTER: + CInit_ExprPointer(TYPE_POINTER(type), expr); + break; + case TYPEMEMBERPOINTER: + CInit_ExprMemberPointer(TYPE_MEMBER_POINTER(type), expr); + break; + case TYPESTRUCT: + case TYPECLASS: + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(type, expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(124); + } + break; + case TYPEARRAY: + CError_Error(174); + break; + default: +#line 2082 + CError_FATAL(); + } +} + +static void CInit_Bitfield(TypeBitfield *tbitfield) { + Boolean r30; + ENode *expr; + ENode myexpr; + + r30 = tk == '{'; + if (r30) + tk = lex(); + + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion( + expr, + IS_TYPE_ENUM(tbitfield->bitfieldtype) ? TYPE_ENUM(tbitfield->bitfieldtype)->enumtype : tbitfield->bitfieldtype, + 0, + 1); + if (ENODE_IS(expr, EINTCONST)) + CInit_SetBitfield(tbitfield, (UInt8 *) cinit_initinfo->buffer + cinit_initinfo->expr_offset, expr->data.intval); + else + CError_Error(124); + + if (r30) + CInit_CloseInitList(); +} + +static void CInit_Array(TypePointer *tptr, UInt32 qual, Boolean flag) { + SInt32 start; + SInt32 i; + SInt32 targetsize1; + SInt32 targetsize2; + Boolean in_block; + Boolean is_char_ptr; + Boolean needs_construction; + Boolean is_wchar_ptr; + + targetsize1 = tptr->target->size; + targetsize2 = tptr->target->size; + if (!tptr->target->size) { + if (!IS_TYPE_ARRAY(tptr->target)) { + CError_Error(145); + return; + } + targetsize1 = tptr->target->size; + targetsize2 = tptr->target->size; + if (!tptr->target->size) { + CError_Error(145); + return; + } + } + + is_char_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == 1); + is_wchar_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == stwchar.size); + + in_block = 1; + if (flag && !(tk == TK_STRING && is_char_ptr) && !(tk == TK_STRING_WIDE && is_wchar_ptr)) { + if (tk != '{') { + CError_ErrorSkip(135); + return; + } + tk = lex(); + } else { + if (tk == '{') + tk = lex(); + else + in_block = 0; + } + + if ((tk == TK_STRING && is_char_ptr) || (tk == TK_STRING_WIDE && is_wchar_ptr)) { + if (tptr->size) { + if (tksize > tptr->size) { + if (copts.cplusplus || (tksize - (is_wchar_ptr ? stwchar.size : 1)) > tptr->size) + CError_Error(147); + tksize = tptr->size; + } + memcpy(cinit_initinfo->buffer + cinit_initinfo->expr_offset, tkstring, tksize); + } else { + tptr->size = tksize; + CInit_SetData(tkstring, cinit_initinfo->expr_offset, tptr->size); + } + cinit_initinfo->expr_offset += tptr->size; + tk = lex(); + if (in_block) + CInit_CloseInitList(); + return; + } + + if (IS_TYPE_CLASS(tptr->target) && CInit_ClassNeedsConstruction(TYPE_CLASS(tptr->target))) + needs_construction = 1; + else + needs_construction = 0; + + start = cinit_initinfo->expr_offset; + i = 0; + while (1) { + if (tk == '}') { + innerloop: + if (tptr->size) { + if (needs_construction) { + while (tptr->size > (i * targetsize1)) { + cinit_initinfo->expr_offset = start + i * targetsize2; + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, NULL, 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(174); + } + i++; + } + } + } else { + tptr->size = i * targetsize1; + } + cinit_initinfo->expr_offset = start + tptr->size; + if (in_block) + tk = lex(); + return; + } + + if (!tptr->size) { + cinit_initinfo->expr_offset = start + i * targetsize2; + CInit_SetData(NULL, cinit_initinfo->expr_offset, targetsize2); + if (needs_construction) { + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(174); + } + } else { + CInit_Type(tptr->target, qual, 0); + } + } else { + if (tptr->size <= i * targetsize1) { + i--; + CError_Error(147); + } + + cinit_initinfo->expr_offset = start + i * targetsize2; + if (needs_construction) { + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(174); + } + } else { + CInit_Type(tptr->target, qual, 0); + } + + if (!in_block) { + if (tptr->size <= (i + 1) * targetsize1) + return; + } + } + + if (tk != '}') { + if (tk != ',') { + CError_ErrorSkip(121); + in_block = 0; + i++; + goto innerloop; + } + tk = lex(); + } + i++; + } +} + +static void CInit_Struct(TypeStruct *tstruct, Boolean flag) { + StructMember *member; + SInt32 start; + Boolean in_block; + + if (!(member = tstruct->members)) { + CError_Error(145); + return; + } + + if (tstruct->stype == STRUCT_TYPE_UNION) { + if (tk == '{') { + tk = lex(); + CInit_Type(member->type, member->qual, 0); + if (tk == '}') + tk = lex(); + } else { + CInit_Type(member->type, member->qual, 0); + } + return; + } + + if (IS_TYPE_VECTOR(tstruct) && tk != '{') { + CInit_TypeExpr(TYPE(tstruct), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tstruct), 0, 1)); + return; + } + + if (tk != '{') { + if (flag) + CError_ErrorSkip(135); + in_block = 0; + } else { + in_block = 1; + tk = lex(); + } + + start = cinit_initinfo->expr_offset; + while (1) { + if (tk == '}') + break; + + cinit_initinfo->expr_offset = start + member->offset; + if (!member->type->size && IS_TYPE_ARRAY(member->type)) { + CError_Error(147); + break; + } + + CInit_Type(member->type, member->qual, 0); + if (tk == '}') + break; + + if (tk != ',') { + CError_Error(121); + break; + } + + do { + member = member->next; + } while (member && (member->qual & Q_OVERLOAD)); + + if (!member) { + if (!in_block) + break; + if ((tk = lex()) != '}') { + CError_Error(147); + break; + } + } else { + tk = lex(); + } + } + + cinit_initinfo->expr_offset = start + tstruct->size; + if (tk == '}' && in_block) + tk = lex(); +} + +static void CInit_Class(TypeClass *tclass, Boolean flag) { + ObjMemberVar *ivar; + SInt32 start; + Boolean in_block; + + if (tk == '{') { + in_block = 1; + tk = lex(); + } else { + in_block = 0; + } + + if (tclass->bases || tclass->vtable) { + CError_Error(174); + return; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->access != ACCESSPUBLIC) + break; + } + + if (!ivar && !CClass_Constructor(tclass) && (!CClass_Destructor(tclass) || in_block)) { + if ((ivar = tclass->ivars)) { + start = cinit_initinfo->expr_offset; + while (1) { + if (tk == '}') + break; + + if (!ivar->type->size && IS_TYPE_ARRAY(ivar->type)) { + CError_Error(147); + break; + } + + cinit_initinfo->expr_offset = start + ivar->offset; + CInit_Type(ivar->type, ivar->qual, 0); + + if (tk == '}') + break; + + if (tk != ',') { + CError_Error(121); + break; + } + + do { + ivar = ivar->next; + } while (ivar && ivar->anonunion); + + if (!ivar) { + if (!in_block) + break; + if ((tk = lex()) != '}') { + CError_Error(147); + break; + } + } else { + tk = lex(); + } + } + } else { + if (in_block && tk != '}') + CError_Error(147); + } + } else { + if (in_block) + CError_Error(174); + CInit_TypeExpr(TYPE(tclass), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tclass), 0, 1)); + } + + cinit_initinfo->expr_offset = start + tclass->size; + if (tk == '}' && in_block) + tk = lex(); +} + +static void CInit_Type(Type *type, UInt32 qual, Boolean flag) { + ENode *expr; + ENode myexpr; + + switch (type->type) { + case TYPEVOID: + CError_Error(174); + break; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + if (tk == '{') { + tk = lex(); + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + CInit_CloseInitList(); + } else { + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + } + CInit_TypeExpr(type, expr); + break; + case TYPEBITFIELD: + CInit_Bitfield(TYPE_BITFIELD(type)); + break; + case TYPEARRAY: + CInit_Array(TYPE_POINTER(type), qual, flag); + break; + case TYPESTRUCT: + CInit_Struct(TYPE_STRUCT(type), flag); + break; + case TYPECLASS: + CInit_Class(TYPE_CLASS(type), flag); + break; + default: +#line 2482 + CError_FATAL(); + } +} + +static void CInit_GlobalStaticInit(Type *type, ENode *valueexpr, Boolean flag) { + ENode *expr; + ENode *tmp; + + cinit_initinfo->x15 = 1; + if (flag) { + CInit_ConstructGlobalObject(cinit_initinfo->obj, TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); + } else { + expr = create_objectrefnode(cinit_initinfo->obj); + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + CError_Error(174); + return; + } + TYPE_POINTER(expr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + tmp = makemonadicnode(expr, EINDIRECT); + tmp->rtype = type; + expr = makediadicnode(tmp, valueexpr, EASS); + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, cinit_initinfo->obj); + } +} + +static void CInit_AutoInit(Type *type, ENode *valueexpr, Boolean flag) { + ENode *expr; + ENode *tmp; + Type *copy; + SInt32 size; + + if (flag) { + CInit_ConstructAutoObject(TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); + } else { + if (IS_TYPE_ARRAY(type) && (type->size & 1)) { + copy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(copy) = *TYPE_POINTER(type); + type = copy; + copy->size = type->size + 1; + } + expr = create_objectrefnode(cinit_initinfo->obj1C); + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + CError_Error(174); + return; + } + TYPE_POINTER(expr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + tmp = makemonadicnode(expr, EINDIRECT); + tmp->rtype = type; + expr = makediadicnode(tmp, valueexpr, EASS); + if (!copts.cplusplus) + CError_Error(124); + cinit_initinfo->insert_expr_cb(expr); + } +} + +static SInt32 CInit_AdjustObjectDataSize(Object *obj) { + if (obj->type->size <= 1) + return obj->type->size; + if (obj->type->size & 1) + return obj->type->size + 1; + else + return obj->type->size; +} + +static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB expr_cb, Boolean flag) { + Object *r31; + ENode *expr; + ENode *tmpexpr; + Type *inner; + Type *copy; + SInt32 size; + Boolean lastflag; + SInt16 cv; + + cinit_initinfo->expr_cb = expr_cb; + expr = NULL; + + if (tk == '(') { + if (IS_TYPE_ARRAY(type)) + CError_Error(174); + tk = lex(); + expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1); + if (tk != ')') + CError_ErrorSkip(115); + else + tk = lex(); + goto jump_ahead; + } + + tk = lex(); + switch (type->type) { + case TYPECLASS: + if (tk == '{' && CClass_Constructor(TYPE_CLASS(type))) + CError_Error(174); + case TYPESTRUCT: + if (tk != '{') + goto generic_type; + case TYPEARRAY: + if (!obj) { + if (IS_TYPE_ARRAY(type)) { + inner = type; + while (IS_TYPE_ARRAY(inner)) + inner = TYPE_POINTER(inner)->target; + + if (IS_TYPE_CLASS(inner) && CInit_ClassNeedsConstruction(TYPE_CLASS(inner))) { + CInit_SetupInitInfoBuffer(type); + cinit_initinfo->obj = cinit_initinfo->obj1C; + CInit_Type(type, cinit_initinfo->obj->qual, 1); + return 0; + } + if (type->size & 1) { + copy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(copy) = *TYPE_POINTER(type); + type = copy; + type->size++; + } + } + + obj = CInit_CreateStaticDataObject(type, qual, NULL); + cinit_initinfo->obj = obj; + expr = create_objectnode(obj); + cinit_initinfo->obj1C = obj; + } + CInit_SetupInitInfoBuffer(type); + CInit_Type(type, obj->qual, 1); +#line 2639 + CError_ASSERT(obj->type->size == (size = cinit_initinfo->size)); + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, size)) { + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return expr; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + generic_type: + if (obj) { + cv = obj->qual; + cv &= Q_CONST | Q_VOLATILE; + } else { + cv = cinit_initinfo->obj1C->qual; + cv &= Q_CONST | Q_VOLATILE; + } + if (tk == '{') { + tk = lex(); + expr = assignment_expression(); + CInit_CloseInitList(); + } else { + expr = assignment_expression(); + } + expr = CExpr_AssignmentPromotion(expr, type, cv, 1); + jump_ahead: + if (obj == NULL) + r31 = cinit_initinfo->obj1C; + else + r31 = obj; + + if (is_const_object(r31)) { + switch (r31->type->type) { + case TYPEINT: + case TYPEENUM: + if (ENODE_IS(expr, EINTCONST)) { + r31->u.data.u.intconst = expr->data.intval; + goto common_8068C; + } + break; + case TYPEFLOAT: + if (ENODE_IS(expr, EFLOATCONST)) { + Float fl; + r31->u.data.u.floatconst = galloc(sizeof(Float)); + fl = CMach_CalcFloatConvert(r31->type, expr->data.floatval); + *r31->u.data.u.floatconst = fl; + goto common_8068C; + } + break; + case TYPEPOINTER: + tmpexpr = expr; + while (ENODE_IS(tmpexpr, ETYPCON)) + tmpexpr = tmpexpr->data.monadic; + if (!ENODE_IS(tmpexpr, EINTCONST)) + break; + r31->u.data.u.intconst = tmpexpr->data.intval; + common_8068C: + r31->qual |= Q_10000; + if (!obj) { + r31->sclass = TK_STATIC; + r31->datatype = DDATA; + r31->u.data.linkname = CParser_AppendUniqueName(r31->name->name); + } else if (r31->sclass != TK_STATIC || (r31->flags & OBJECT_FLAGS_2)) { + CInit_ExportConst(r31); + } + return NULL; + } + } + + if (!obj || (flag && copts.cplusplus)) { + if (obj) { + IsCompleteType(obj->type); +#line 2747 + CError_ASSERT(obj->type->size == type->size); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return expr; + } + + CInit_SetupInitInfoBuffer(type); + CInit_TypeExpr(type, expr); +#line 2756 + CError_ASSERT(obj->type->size == cinit_initinfo->size); + + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + lastflag = !cinit_initinfo->x15 && is_const_object(r31); + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { + if (lastflag) + CInit_DeclareReadOnlyData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + else + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + if (lastflag) + CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); + else + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + break; + + default: +#line 2776 + CError_FATAL(); + } + + return NULL; +} + +void CInit_ExportConst(Object *obj) { + char buffer[64]; + + if (obj->flags & OBJECT_FLAGS_4) + return; + + switch (obj->type->type) { + case TYPEINT: + CMach_InitIntMem(obj->type, obj->u.data.u.intconst, buffer); + break; + case TYPEENUM: + CMach_InitIntMem(TYPE_ENUM(obj->type)->enumtype, obj->u.data.u.intconst, buffer); + break; + case TYPEPOINTER: + CMach_InitIntMem(TYPE(&stunsignedlong), obj->u.data.u.intconst, buffer); + break; + case TYPEFLOAT: + CMach_InitFloatMem(obj->type, *obj->u.data.u.floatconst, buffer); + break; + default: +#line 2807 + CError_FATAL(); + } + + if (is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, buffer, NULL, obj->type->size); + else + CInit_DeclareData(obj, buffer, NULL, obj->type->size); +} + +static ENode *CInit_ClassInitLoopCallBack(ENode *expr) { + return CExpr_ConstructObject(cinit_loop_class, expr, NULL, 0, 1, 0, 1, 1); +} + +Statement *CInit_ConstructClassArray(Statement *stmt, TypeClass *tclass, Object *ctor, Object *dtor, ENode *firstarg, SInt32 count) { + ENode *dtor_expr; + + if (stmt) + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + else + stmt = CFunc_AppendStatement(ST_EXPRESSION); + + if (dtor) + dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, 1)); + else + dtor_expr = nullnode(); + + stmt->expr = CExpr_FuncCallSix( + carr_func, + firstarg, + create_objectrefnode(ctor), + dtor_expr, + intconstnode(TYPE(&stunsignedlong), tclass->size), + intconstnode(TYPE(&stunsignedlong), count), + NULL + ); + + return stmt; +} + +static void CInit_InitializeClassArray(Object *obj, TypeClass *tclass, Boolean flag) { + Object *ctor; + Object *dtor; + SInt32 count; + SInt32 i; + ENode *expr; + SInt32 offset; + ENode *dtor_expr; + Statement *stmt; + TypeFunc *tfunc; + Object *funcobj; + + dtor = CClass_Destructor(tclass); + count = obj->type->size / tclass->size; + if (CClass_Constructor(tclass)) { + ctor = CClass_DefaultConstructor(tclass); + if (!ctor) { + ctor = CClass_DummyDefaultConstructor(tclass); + if (!ctor) { + CError_Error(203); + return; + } + } + } else { + ctor = NULL; + } + + if (count <= 1 || (!flag && count <= 8)) { + if (flag) { + for (i = 0; i < count; i++) { + CInit_ConstructGlobalObject(obj, tclass, NULL, i * tclass->size, 0); + } + } else { + for (i = 0; i < count; i++) { + offset = i * tclass->size; + expr = create_objectrefnode(obj); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + if (ctor) + expr = CExpr_ConstructObject(tclass, expr, NULL, 0, 1, 0, 1, 1); + cinit_initinfo->insert_expr_cb(expr); + if (dtor) + CExcept_RegisterDestructorObject(obj, offset, dtor, 1); + } + if (dtor) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = nullnode(); + } + } + } else { + if (ctor) { + if (!flag && !dtor) { + CInit_ConstructClassArray(NULL, tclass, ctor, dtor, create_objectrefnode(obj), count); + expr = nullnode(); + } else { + if (dtor) + dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, 1)); + else + dtor_expr = nullnode(); + expr = CExpr_FuncCallSix( + carr_func, + create_objectrefnode(obj), + create_objectrefnode(ctor), + dtor_expr, + intconstnode(TYPE(&stunsignedlong), tclass->size), + intconstnode(TYPE(&stunsignedlong), count), + NULL + ); + } + } else { + expr = nullnode(); + } + + if (flag) { + if (dtor && !copts.no_static_dtors) { + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + CDecl_SetFuncFlags(tfunc, 1); + + funcobj = CParser_NewCompilerDefFunctionObject(); + funcobj->name = CParser_AppendUniqueName("__arraydtor"); + funcobj->type = TYPE(tfunc); + funcobj->sclass = TK_STATIC; + funcobj->qual = Q_INLINE; + + CParser_RegisterSingleExprFunction(funcobj, funccallexpr( + darr_func, + create_objectrefnode(obj), + create_objectrefnode(CABI_GetDestructorObject(dtor, 1)), + intconstnode(TYPE(&stsignedlong), tclass->size), + intconstnode(TYPE(&stsignedlong), count) + )); + + expr = makediadicnode(expr, nullnode(), ECOMMA); + expr->rtype = TYPE(&void_ptr); + + expr = funccallexpr( + Xgreg_func, + expr, + create_objectrefnode(funcobj), + create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())), + NULL + ); + } + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, obj); + } else { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + if (dtor) { + CExcept_RegisterLocalArray(stmt, obj, dtor, count, tclass->size); + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = nullnode(); + } + } + } +} + +static ENode *CInit_AutoTempNode(Type *type, Boolean flag) { + ENode *node; + node = CExpr_NewETEMPNode(type, 0); + if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) + node->data.temp.needs_dtor = 1; + return node; +} + +static ENode *CInit_GlobalTempNode(Type *type, Boolean flag) { + Object *dtor; + ENode *node; + ENode *funcnode; + + node = create_objectrefnode(CInit_CreateStaticData(type)); + if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type))) && !copts.no_static_dtors) { + if (flag) + CError_Error(190); + + funcnode = galloc(sizeof(ENode)); + funcnode->type = EFUNCCALL; + funcnode->cost = 200; + funcnode->flags = 0; + funcnode->rtype = CDecl_NewPointerType(type); + funcnode->data.funccall.funcref = create_objectrefnode(Xgreg_func); + funcnode->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); + funcnode->data.funccall.args = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->node = node; + funcnode->data.funccall.args->next = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, 1)); + funcnode->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));; + funcnode->data.funccall.args->next->next->next = NULL; + node = funcnode; + } + return node; +} + +static void CInit_RefInit(Type *type, ENode *expr, Boolean flag) { + ENode *objexpr; + + objexpr = create_objectrefnode(cinit_initinfo->obj); + if (!IS_TYPE_POINTER_ONLY(objexpr->rtype)) { + CError_Error(174); + return; + } + TYPE_POINTER(objexpr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + objexpr = makediadicnode(objexpr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + objexpr = makemonadicnode(objexpr, EINDIRECT); + objexpr->rtype = type; + + expr = makediadicnode(objexpr, expr, EASS); + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, cinit_initinfo->obj); +} + +static Boolean CInit_IsDtorTemp(ENode *expr) { + return ENODE_IS(expr, ETEMP) && expr->data.temp.needs_dtor; +} + +static void CInit_FindDtorTemp(ENode *expr) { + ENodeList *list; + + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + + if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target)) { + switch (expr->type) { + case ETYPCON: + CInit_FindDtorTemp(expr->data.monadic); + break; + case EADD: + case ESUB: + CInit_FindDtorTemp(expr->data.diadic.left); + CInit_FindDtorTemp(expr->data.diadic.right); + break; + case EFUNCCALL: + case EFUNCCALLP: + if ((list = expr->data.funccall.args)) { + if (CInit_IsDtorTemp(list->node) || ((list = list->next) && CInit_IsDtorTemp(list->node))) { + if (!cinit_fdtnode) + cinit_fdtnode = list; + else + cinit_fdtambig = 1; + } + } + break; + } + } +} + +static void CInit_RefTempTransform(Type *type, ENode *expr) { + Object *obj; + +#line 3164 + CError_ASSERT(IS_TYPE_POINTER_ONLY(type)); + + if (IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + cinit_fdtnode = NULL; + cinit_fdtambig = 0; + CInit_FindDtorTemp(expr); + if (cinit_fdtnode) { +#line 3172 + CError_ASSERT(!cinit_fdtambig); + obj = create_temp_object(cinit_fdtnode->node->data.temp.type); + cinit_initinfo->register_object_cb(cinit_fdtnode->node->data.temp.type, obj, 0, 0); + cinit_fdtnode->node = create_objectrefnode(obj); + } + } +} + +static Boolean CInit_InitReference(Object *obj, Boolean flag) { + ENode *expr; + + if (tk == '=') { + cinit_tempnodefunc = flag ? CInit_AutoTempNode : CInit_GlobalTempNode; + tk = lex(); + expr = CExpr_AssignmentPromotion(assignment_expression(), obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); + cinit_tempnodefunc = NULL; + + if (flag) { + CInit_RefTempTransform(obj->type, expr); + expr = makediadicnode(create_objectnode2(obj), expr, EASS); + cinit_initinfo->insert_expr_cb(expr); + } else { + cinit_initinfo->expr_cb = CInit_RefInit; + CInit_SetupInitInfoBuffer(obj->type); + CInit_ExprPointer(TYPE_POINTER(obj->type), expr); +#line 3213 + CError_ASSERT(obj->type->size == cinit_initinfo->size); + + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + } + + return 1; + } + + return 0; +} + +ENode *CInit_AutoObject(Object *obj, Type *type, UInt32 qual) { + CInit_Stuff s; + CInit_1C *entry; + ENode *expr; + ENode *indirect_expr; + ENode *obj_expr; + ENode *const_expr; + Type *newtype; + Object *newobj; + + CInit_InitData(&s, type, qual, copts.cplusplus || copts.gcc_extensions || copts.c9x || !obj); + if (!obj && !cscope_currentfunc) { + obj = CParser_NewCompilerDefDataObject(); + obj->name = CParser_GetUniqueName(); + obj->type = type; + obj->qual = qual; + obj->sclass = TK_STATIC; + CScope_AddGlobalObject(obj); + } + + if (IS_TYPE_VECTOR(type) && !s.x1C) { + if (obj) + obj_expr = create_objectrefnode(obj); + else + obj_expr = CExpr_NewETEMPNode(type, 1); + + const_expr = CExpr_NewENode(EVECTOR128CONST); + const_expr->rtype = type; + const_expr->data.vector128val = *((MWVector128 *) s.buffer); + + indirect_expr = makemonadicnode(obj_expr, EINDIRECT); + indirect_expr->rtype = type; + + expr = makediadicnode(indirect_expr, const_expr, EASS); + if (!obj) { + ENode *tmp = lalloc(sizeof(ENode)); + *tmp = *obj_expr; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = type; + tmp->flags = qual & ENODE_FLAG_QUALS; + expr = makecommaexpression(expr, tmp); + } + return expr; + } + + if (s.x18) { + type = CDecl_NewStructType(type->size + s.x18, CMach_GetTypeAlign(type)); + if (obj) + obj->type = type; + } + + if (obj) + obj_expr = create_objectrefnode(obj); + else + obj_expr = CExpr_NewETEMPNode(type, 1); + + newtype = type; + if (IS_TYPE_ARRAY(type)) + newtype = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type)); + newobj = CInit_CreateStaticDataObject(newtype, 0, NULL); + if (s.list || !CInit_IsAllZero(s.buffer, s.size)) + CInit_DeclareReadOnlyData(newobj, s.buffer, s.list, s.size); + else + CInit_DeclareReadOnlyData(newobj, NULL, NULL, s.size); + + indirect_expr = makemonadicnode(obj_expr, EINDIRECT); + indirect_expr->rtype = newtype; + expr = makediadicnode(indirect_expr, create_objectnode(newobj), EASS); + + for (entry = s.x1C; entry; entry = entry->next) { + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + } + + if (!obj) { + ENode *tmp = lalloc(sizeof(ENode)); + *tmp = *obj_expr; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = type; + tmp->flags = qual & ENODE_FLAG_QUALS; + expr = makecommaexpression(expr, tmp); + } else if (IS_TYPE_ARRAY(type)) { + expr = makecommaexpression(expr, create_objectnode(obj)); + } + + return expr; +} + +static void CInit_GlobalObject(Object *obj) { + CInit_Stuff s; + CInit_1C *entry; + ENode *obj_expr; + ENode *expr; + + CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); + obj_expr = create_objectrefnode(obj); + + IsCompleteType(obj->type); + + if (!s.x1C && is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); + else + CInit_DeclareData(obj, s.buffer, s.list, s.size); + + if (s.x1C) { + entry = s.x1C; + expr = NULL; + while (entry) { + if (!ENODE_IS(entry->expr, EVECTOR128CONST)) + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + entry = entry->next; + } + + if (expr) + InitExpr_Register(expr, obj); + } +} + +void CInit_InitializeAutoData(Object *obj, InsertExprCB insert_cb, RegisterObjectCB register_cb) { + ENode *expr; + Type *type; + InitInfo initinfo; + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=' || (tk == '(' && copts.cplusplus)) { + if (tk == '(') { + tk = lex(); + expr = conv_assignment_expression(); + if (tk != ')') + CError_Error(115); + tk = lex(); + } else if (tk == '=' && ((tk = lex()) == '{' || IS_TYPE_ARRAY(obj->type))) { + insert_cb(CInit_AutoObject(obj, obj->type, obj->qual)); + return; + } else { + expr = conv_assignment_expression(); + } + expr = CExpr_AssignmentPromotion(expr, obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); + insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else if (copts.cplusplus && is_const_object(obj)) { + CError_Error(224); + } + + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + initinfo.obj1C = obj; + initinfo.insert_expr_cb = insert_cb; + initinfo.register_object_cb = register_cb; + + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructAutoObject(TYPE_CLASS(obj->type), NULL, 0, 1)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 1)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 0); + CInit_CleanupInitInfo(&initinfo); + return; + } + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + + if (IS_TYPE_CLASS(obj->type)) + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + + if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) + CError_Error(224); + } else { + if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { + if ((expr = CInit_GenericData(NULL, obj->type, obj->qual, CInit_AutoInit, 0))) + insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else { + CError_Error(145); + } + } + + if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type))) + register_cb(obj->type, obj, 0, NULL); + + CInit_CleanupInitInfo(&initinfo); +} + +void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb) { + ENode *expr; + Type *type; + InitInfo initinfo; + CInit_Stuff s; + CInit_1C *entry; + ENode *obj_expr; + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=' || (tk == '(' && copts.cplusplus)) { + if (tk == '=') + tk = lex(); + CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); + + IsCompleteType(obj->type); + + if (!s.x1C && is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); + else + CInit_DeclareData(obj, s.buffer, s.list, s.size); + + if (s.x1C) { + obj_expr = create_objectrefnode(obj); + entry = s.x1C; + expr = NULL; + while (entry) { + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + entry = entry->next; + } + cb(expr); + } + } else { + if (copts.cplusplus && is_const_object(obj)) + CError_Error(224); + + if (is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); + else + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + initinfo.x16 = 1; + initinfo.init_expr_register_cb = cb; + + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { + IsCompleteType(obj->type); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (IsCompleteType(obj->type)) + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); + CInit_CleanupInitInfo(&initinfo); + return; + } + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + + if (IS_TYPE_CLASS(obj->type)) + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + + if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) + CError_Error(224); + } else { + if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { + if ((expr = CInit_GenericData(obj, obj->type, obj->qual, CInit_GlobalStaticInit, 1))) + cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else { + CError_Error(145); + } + } + + CInit_CleanupInitInfo(&initinfo); +} + +void CInit_InitializeData(Object *obj) { + Object *dtor; + ObjectList *list; + CInt64 val; + InitInfo initinfo; + Boolean needs_construction; + Type *type; + + if (tk == ':') { + tk = lex(); + obj->datatype = DABSOLUTE; + val = CExpr_IntegralConstExpr(); + obj->u.address = CInt64_GetULong(&val); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (obj->sclass != TK_EXTERN) { + if (!copts.cplusplus) { + if (IsCompleteType(obj->type)) { + for (list = cinit_tentative; list; list = list->next) { + if (list->object == obj) + break; + } + if (!list) { + list = galloc(sizeof(ObjectList)); + list->object = obj; + list->next = cinit_tentative; + cinit_tentative = list; + obj->qual |= Q_1000000; + } + } + } else { + if (obj->flags & OBJECT_FLAGS_4) + CError_Error(329, obj); + obj->flags |= OBJECT_FLAGS_4; + + needs_construction = 0; + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_SetupInitInfo(&initinfo, obj); + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); + CInit_CleanupInitInfo(&initinfo); + needs_construction = 1; + } else { + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + } else { + if (IS_TYPE_CLASS(obj->type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(obj->type))) { + CInit_SetupInitInfo(&initinfo, obj); + CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 0); + CInit_CleanupInitInfo(&initinfo); + needs_construction = 1; + } else { + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + } + } + } + + if (!needs_construction && copts.cplusplus) { + if (IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) + CError_Error(224); + } + if (IsCompleteType(obj->type)) + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + } + return; + } + + if (obj->flags & OBJECT_FLAGS_4) + CError_Error(329, obj); + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=') + tk = lex(); + else + CError_Error(121); + CInit_GlobalObject(obj); + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { + IsCompleteType(obj->type); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (obj->type->size == 0 && !IS_TYPE_ARRAY(obj->type)) { + CError_Error(145); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (copts.cplusplus) + CInit_GenericData(obj, obj->type, obj->qual, &CInit_GlobalStaticInit, 0); + else + CInit_GenericData(obj, obj->type, obj->qual, NULL, 0); + + if (IS_TYPE_CLASS(obj->type) && (dtor = CClass_Destructor(TYPE_CLASS(obj->type)))) + InitExpr_Register(CInit_RegisterDtorObject(obj->type, dtor, create_objectrefnode(obj)), obj); + + CInit_CleanupInitInfo(&initinfo); +} + +Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide) { + PooledString *str; + Object *obj; + PooledString *scan; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_stringlist; scan; scan = scan->next) { + if (scan->size == size && scan->ispascal == ispascal && scan->iswide == iswide && !memcmp(scan->data, data, size)) + return scan->obj; + } + } + + obj = CParser_NewCompilerDefDataObject(); + obj->name = CParser_GetUniqueName(); + if (iswide) { + obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); + } else { + obj->type = CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size); + } + obj->sclass = TK_STATIC; + CScope_AddGlobalObject(obj); + + if (!iswide && !ispascal && size == (strlen(data) + 1)) + obj->section = SECT_TEXT_CSTRING; + else + obj->section = SECT_CONST; + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(obj, data, NULL, obj->type->size); + else + CInit_DeclareData(obj, data, NULL, obj->type->size); + + str = galloc(sizeof(PooledString)); + str->next = cinit_stringlist; + cinit_stringlist = str; + str->obj = obj; + str->offset = 0; + str->size = size; + str->ispascal = ispascal; + str->iswide = iswide; + str->data = galloc(size); + memcpy(str->data, data, size); + + return obj; +} + +PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal) { + PooledString *str; + Object *obj; + PooledString *scan; + SInt32 offset; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_pooledstringlist; scan; scan = scan->next) { + if (scan->size == size && scan->ispascal == ispascal && !memcmp(scan->data, data, size)) + return scan; + } + } + + if (cinit_pooledstringlist) { + obj = cinit_pooledstringlist->obj; + offset = cinit_pooledstringlist->offset + cinit_pooledstringlist->size; + } else { + obj = CInit_CreateStaticDataObject( + CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size), + 0, GetHashNameNodeExport("@stringBase0")); + obj->section = SECT_CONST; + offset = 0; + } + + str = galloc(sizeof(PooledString)); + str->next = cinit_pooledstringlist; + cinit_pooledstringlist = str; + str->obj = obj; + str->offset = offset; + str->size = size; + str->ispascal = ispascal; + str->data = galloc(size); + memcpy(str->data, data, size); + return str; +} + +PooledString *CInit_DeclarePooledWString(char *data, SInt32 size) { + PooledString *str; + Object *obj; + PooledString *scan; + SInt32 offset; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_pooledwstringlist; scan; scan = scan->next) { + if (scan->size == size && !memcmp(scan->data, data, size)) + return scan; + } + } + + if (cinit_pooledwstringlist) { + obj = cinit_pooledwstringlist->obj; + offset = cinit_pooledwstringlist->offset + cinit_pooledwstringlist->size; + } else { + obj = CInit_CreateStaticDataObject( + CDecl_NewArrayType(CParser_GetWCharType(), size), + 0, GetHashNameNodeExport("@wstringBase0")); + obj->section = SECT_CONST; + offset = 0; + } + + str = galloc(sizeof(PooledString)); + str->next = cinit_pooledwstringlist; + cinit_pooledwstringlist = str; + str->obj = obj; + str->offset = offset; + str->size = size; + str->ispascal = 0; + str->data = galloc(size); + memcpy(str->data, data, size); + return str; +} + +void CInit_RewriteString(ENode *expr, Boolean flag) { + PooledString *str; + Boolean is_wide; + + if (cparamblkptr->isPrecompiling == 1) + CError_Error(180); + +#line 4220 + CError_ASSERT(expr->rtype->type == TYPEPOINTER); + + is_wide = TYPE_POINTER(expr->rtype)->target->size != 1; + if (copts.pool_strings) { + if (is_wide) + str = CInit_DeclarePooledWString(expr->data.string.data, expr->data.string.size); + else + str = CInit_DeclarePooledString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal); + + if (str->offset) { + expr->type = EADD; + expr->data.diadic.right = intconstnode(TYPE(&stunsignedlong), str->offset); + expr->data.diadic.left = create_objectrefnode(str->obj); + expr->cost = 1; + } else { + expr->type = EOBJREF; + expr->data.objref = str->obj; + } + } else { + expr->type = EOBJREF; + expr->data.objref = CInit_DeclareString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal, is_wide); + } +} + +void CInit_DeclarePooledStrings(void) { + SInt32 size; + char *buffer; + PooledString *str; + + size = 0; + for (str = cinit_pooledstringlist; str; str = str->next) + size += str->size; + + if (size) { + cinit_pooledstringlist->obj->type = CDecl_NewArrayType(TYPE(&stchar), size); + buffer = galloc(size); + for (str = cinit_pooledstringlist; str; str = str->next) + memcpy(buffer + str->offset, str->data, str->size); + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(cinit_pooledstringlist->obj, buffer, NULL, size); + else + CInit_DeclareData(cinit_pooledstringlist->obj, buffer, NULL, size); + } + + size = 0; + for (str = cinit_pooledwstringlist; str; str = str->next) + size += str->size; + + if (size) { + cinit_pooledwstringlist->obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); + buffer = galloc(size); + for (str = cinit_pooledwstringlist; str; str = str->next) + memcpy(buffer + str->offset, str->data, str->size); + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(cinit_pooledwstringlist->obj, buffer, NULL, size); + else + CInit_DeclareData(cinit_pooledwstringlist->obj, buffer, NULL, size); + } +} + +static void declaredata(Object *obj, void *data, OLinkList *list, SInt32 size, Boolean is_readonly) { + OLinkList *scan; + UInt32 qual; + + qual = obj->qual; + + if (cparamblkptr->isPrecompiling == 1) { + PreComp_StaticData(obj, data, list, size); + } else { + obj->flags |= OBJECT_FLAGS_4; + if (!fatalerrors) { + for (scan = list; scan; scan = scan->next) + CInline_ObjectAddrRef(scan->obj); + if (copts.isGeneratingDebugInfo) + CPrep_SetSourceFile(&cparser_fileoffset); + if (is_readonly) + ObjGen_DeclareReadOnlyData(obj, data, list, size); + else + ObjGen_DeclareData(obj, data, list, size); + obj->qual = qual; + } + } +} + +void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size) { + declaredata(obj, data, list, size, 0); +} + +void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size) { + declaredata(obj, data, list, size, 1); +} + +void CInit_DefineTentativeData(void) { + ObjectList *list; + + for (list = cinit_tentative; list; list = list->next) { + if (!(list->object->flags & OBJECT_FLAGS_4)) + CInit_DeclareData(list->object, NULL, NULL, list->object->type->size); + } + + cinit_tentative = NULL; +} diff --git a/compiler_and_linker/unsorted/CInline.c b/compiler_and_linker/unsorted/CInline.c new file mode 100644 index 0000000..bd2e46c --- /dev/null +++ b/compiler_and_linker/unsorted/CInline.c @@ -0,0 +1,116 @@ +#include "compiler/CInline.h" +#include "compiler/CFunc.h" + +static CInlineCopyMode enode_copymode; +static Boolean enode_globalcopy; +static void *enode_idtrans; // type? +static void *local_dobjects; // type? +static void *local_aobjects; // type? +static CI_Var *loc_args; +static CI_Var *loc_vars; +static Boolean inline_expanded; +static Boolean any_inline_expanded; +static short cinline_level; +static void *cinline_label_trans; // type? +static Statement *cinline_first_stmt; +static void *cinline_stmtlevelexpr[16]; // type? +static short cinline_stmtlevelexprs; +static Boolean cinline_unconditionalpart; +static Boolean cinline_serialize_stmt; +static void *cinline_exportlist; // type? +static CI_Action *cinline_actionlist; +CI_Action *cinline_tactionlist; +static ObjectList *cinline_freflist; +static Boolean cinline_gendeps; +static Statement *cinline_serial_stmt; +static Statement *cinline_cur_serial_stmt; +static void *cinline_uid_temps; // type? +static Boolean cinline_has_sideeffect; +static SInt32 inline_max_size; +static Boolean recursive_inline; +static Object *expanding_function; +static Boolean cinline_funccallfound; + +void CInline_Init(void) {} +static ENode *CInline_MakeNotNot(ENode *expr) {} +static ENode *CInline_FoldConst(ENode *expr) {} +SInt32 CInline_GetLocalID(Object *obj) {} +static Boolean CInline_IsTrivialExpression(ENode *expr) {} +Boolean CInline_ExpressionHasSideEffect(ENode *expr) {} +static ENode *CInline_CopyExpressionSave(ENode *expr) {} +static SInt32 CInline_TranslateID(SInt32 id) {} +static SInt32 CInline_GetLabelStatementNumber(HashNameNode *name) {} +static ENodeList *CInline_CopyNodeList(ENodeList *list) {} +static EMemberInfo *CInline_CopyEMemberInfo(EMemberInfo *mi) {} +static ENode *CInline_CopyNodes(ENode *node) {} +static void CInline_CheckUsage(ENode *expr, Boolean flag) {} +ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode) {} +static UInt8 CInline_GetObjectSFlags(Object *obj) {} +static void CInline_SetObjectSFlags(Object *obj, UInt8 sflags) {} +static Object *CInline_NewLocalObject(Type *type, short qual, UInt8 sflags) {} +static ENode *CInline_FuncArgConvert(ENode *expr) {} +static ENode *CInline_RefArgTransform(ENode *expr, Boolean flag) {} +static ENode *CInline_SetupArgsExpression(Object *obj, CI_FuncData *data, ENodeList *list) {} +static void CInline_ReturnCheckCB(/* there should be args here */) {} +static ENode *CInline_ReturnCheck(ENode *expr) {} +static ENode *CInline_ReturnMemResult(void) {} +static ENode *CInline_InlineFunctionExpression(ENode *expr) {} +static Boolean CInline_CanExpand(ENode *expr) {} +static SInt32 CInline_EstimateSizeOfExpr(ENode *expr, SInt32 a, SInt32 b) {} +static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 a, SInt32 b) {} +static SInt32 EstimateExpandedSizeOfExpr(ENode *expr, SInt32 b) {} +static SInt32 EstimateExpandedSizeOfFunction(Statement *stmt) {} +static Boolean CInline_InlineFunctionCheck(ENode *expr) {} +static ENode *CInline_ExpandExpression(ENode *expr) {} +static Statement *CInline_NewStatement(StatementType sttype) {} +static ENode *CInline_LoadToTemp(ENode *expr, Object **obj) {} +static ENode *CInline_SerializeEFORCELOAD(ENode *expr) {} +static ENode *CInline_SerializeECOMMA(ENode *expr) {} +static ENode *CInline_SerializeELOR(ENode *expr) {} +static ENode *CInline_SerializeELAND(ENode *expr) {} +static ENode *CInline_SerializeEPRECOMP(ENode *expr) {} +static ENode *CInline_SerializeENULLCHECK(ENode *expr) {} +static ENode *CInline_SerializeECOND(ENode *expr) {} +static ENode *CInline_SerializeExpr(ENode *expr) {} +void CInline_SerializeStatement(Statement *stmt) {} +static void CInline_UnpackSwitch(Statement *stmt, CI_Statement *packed, CLabel **labels) {} +Object *CInline_GetLocalObj(SInt32 id, Boolean flag) {} +static ExceptionAction *CInline_UnpackActions(CI_Statement *packed, Boolean flag) {} +static Statement *CInline_ExpandStatements(Object *obj, Statement *stmt, CI_FuncData *data, ENode *expr, CLabel *label, Object *obj2, Boolean flag) {} +static Statement *CInline_InlineFunctionStatement(Statement *stmt, Boolean *success) {} +static Statement *CInline_ExtractInlineFunction(Statement *stmt) {} +static Statement *CInline_ExpandStatement(Statement *stmt) {} +static void CInline_ForceReverseSearch(ENode *) {} +static ENode *CInline_ForceReverseEvaluation(ENode *expr) {} +static void CInline_ExportCheck(ENode *expr) {} +static void CInline_Expand(Statement *stmt) {} +SInt32 CInline_GetStatementNumber(Statement *first, Statement *stmt) {} +static CI_Switch *CInline_PackSwitch(Statement *s1, Statement *s2) {} +static Boolean CInline_CanInline(Object *obj, Statement *stmt) {} +static ExceptionAction *CInline_PackActions(Statement *s1, Statement *s2) {} +void CInline_PackIFunctionData(CI_FuncData *packed, Statement *stmt, Object *obj) {} +void CInline_UnpackIFunctionData(Object *obj, CI_FuncData *packed, Statement *stmt) {} +static void CInline_GenIFunctionCode(Object *obj, CI_FuncData *func, UInt8 unk) {} +void CInline_AddDefaultFunctionAction(Object *obj) {} +void CInline_AddInlineFunctionAction(Object *obj, TypeClass *tclass, FileOffsetInfo *fileoffset, TStream *stream, Boolean flag) {} +void CInline_AddMemberFunctionAction(Object *obj, Type *a, Type *b, TemplateMember *tmemb) {} +void CInline_AddTemplateFunctionAction(Object *obj, TemplateFunction *func, TemplFuncInstance *inst) {} +static void CInline_AddFRefList_Object(Object *obj) {} +static void CInline_AddFRefList_ExAction(ExceptionAction *exc) {} +static void CInline_AddFRefList_ExprCB(ENode *expr) {} +static void CInline_AddFRefList_Expr(ENode *expr) {} +static void CInline_AddFRefList_Statement(Statement *stmt) {} +static void CInline_AddFRefList_InlineFunc(CI_FuncData *data) {} +static void CInline_GenerateTemplateInline(Object *obj) {} +void CInline_ObjectAddrRef(Object *obj) {} +static Boolean CInline_CheckDependencies(ObjectList *list) {} +static Boolean CInline_IsSmallFunction(Object *obj, Statement *stmt) {} +static Boolean CInline_NoFPLocals(void) {} +void CInline_GenFunc(Statement *stmt, Object *obj, UInt8 unk) {} +static void CInline_GenerateDefaultFunc(Object *obj) {} +static TemplClassInst *CInline_FindNestedTemplInst(TemplClassInst *inst) {} +static void CInline_GenerateInlineFunc(CI_Action *action) {} +Boolean CInline_CanFreeLHeap(void) {} +Boolean CInline_GenerateDeferredFuncs(void) {} +static InitExpr *CInline_InitTemplateData(InitExpr *init) {} +void CInline_Finish(void) {} diff --git a/compiler_and_linker/unsorted/CMachine.c b/compiler_and_linker/unsorted/CMachine.c index f34ec88..fd4aafc 100644 --- a/compiler_and_linker/unsorted/CMachine.c +++ b/compiler_and_linker/unsorted/CMachine.c @@ -186,6 +186,7 @@ SInt32 CMach_ArgumentAlignment(Type *type) { return align; } +// TODO: investigate if this returns SInt16 actually SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual) { SInt32 align; SInt32 qualalign; @@ -573,7 +574,7 @@ void CMach_InitIntMem(Type *type, CInt64 val, void *mem) { } } -void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem) { +void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) { unsigned char uc[16]; unsigned short us[8]; unsigned int ul[4]; @@ -856,7 +857,7 @@ static SInt16 CMach_GetQualifiedStructAlign(TypeStruct *tstruct, Boolean flag) { switch (copts.align_mode) { case AlignMode3_1Byte: - case AlignMode8: + case AlignMode8_Packed: return 1; case AlignMode0_Mac68k: return 2; @@ -941,7 +942,7 @@ static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) { switch (copts.align_mode) { case AlignMode3_1Byte: - case AlignMode8: + case AlignMode8_Packed: return 1; case AlignMode0_Mac68k: return 2; @@ -1047,7 +1048,7 @@ static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) { switch (copts.align_mode) { case AlignMode3_1Byte: - case AlignMode8: + case AlignMode8_Packed: return 1; case AlignMode4_2Byte: case AlignMode5_4Byte: @@ -1166,7 +1167,7 @@ static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 var, Boolean flag) { align = 16; switch (copts.align_mode) { - case AlignMode8: + case AlignMode8_Packed: align = 1; break; case AlignMode0_Mac68k: @@ -1266,7 +1267,7 @@ SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) { switch (copts.align_mode) { case AlignMode3_1Byte: - case AlignMode8: + case AlignMode8_Packed: required_alignment = 0; break; } diff --git a/compiler_and_linker/unsorted/CMangler.c b/compiler_and_linker/unsorted/CMangler.c new file mode 100644 index 0000000..569871e --- /dev/null +++ b/compiler_and_linker/unsorted/CMangler.c @@ -0,0 +1,719 @@ +#include "compiler.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" +#include "cos.h" + +HashNameNode *constructor_name_node; +HashNameNode *destructor_name_node; +HashNameNode *asop_name_node; + +// forward decls +static void CMangler_MangleClassName(TypeClass *tclass); +static void CMangler_MangleTypeAppend(Type *type, UInt32 qual); +static void CMangler_MangleArgs(FuncArg *args); + +void CMangler_Setup(void) { + constructor_name_node = GetHashNameNodeExport("__ct"); + destructor_name_node = GetHashNameNodeExport("__dt"); + asop_name_node = GetHashNameNodeExport("__as"); +} + +HashNameNode *CMangler_BasicDtorName(void) { + return GetHashNameNodeExport("__dtb"); +} + +HashNameNode *CMangler_VBaseDtorName(void) { + return GetHashNameNodeExport("__dtv"); +} + +HashNameNode *CMangler_ArrayDtorName(void) { + return GetHashNameNodeExport("__dta"); +} + +HashNameNode *CMangler_SDeleteDtorName(void) { + return GetHashNameNodeExport("__dts"); +} + +HashNameNode *CMangler_DeleteDtorName(void) { + return GetHashNameNodeExport("__dt"); +} + +char *CMangler_GetOperator(HashNameNode *opname) { + char *name; + + if (opname == asop_name_node) + return "operator="; + + name = opname->name; + if (!strcmp(name, "__nw")) return "operator new"; + if (!strcmp(name, "__dl")) return "operator delete"; + if (!strcmp(name, "__nwa")) return "operator new[]"; + if (!strcmp(name, "__dla")) return "operator delete[]"; + if (!strcmp(name, "__pl")) return "operator+"; + if (!strcmp(name, "__mi")) return "operator-"; + if (!strcmp(name, "__ml")) return "operator*"; + if (!strcmp(name, "__dv")) return "operator/"; + if (!strcmp(name, "__md")) return "operator%"; + if (!strcmp(name, "__er")) return "operator^"; + if (!strcmp(name, "__ad")) return "operator&"; + if (!strcmp(name, "__or")) return "operator|"; + if (!strcmp(name, "__co")) return "operator~"; + if (!strcmp(name, "__nt")) return "operator!"; + if (!strcmp(name, "__lt")) return "operator<"; + if (!strcmp(name, "__gt")) return "operator>"; + if (!strcmp(name, "__apl")) return "operator+="; + if (!strcmp(name, "__ami")) return "operator-="; + if (!strcmp(name, "__amu")) return "operator*="; + if (!strcmp(name, "__adv")) return "operator/="; + if (!strcmp(name, "__amd")) return "operator%="; + if (!strcmp(name, "__aer")) return "operator^="; + if (!strcmp(name, "__aad")) return "operator&="; + if (!strcmp(name, "__aor")) return "operator|="; + if (!strcmp(name, "__ls")) return "operator<<"; + if (!strcmp(name, "__rs")) return "operator>>"; + if (!strcmp(name, "__als")) return "operator<<="; + if (!strcmp(name, "__ars")) return "operator>>="; + if (!strcmp(name, "__eq")) return "operator=="; + if (!strcmp(name, "__ne")) return "operator!="; + if (!strcmp(name, "__le")) return "operator<="; + if (!strcmp(name, "__ge")) return "operator>="; + if (!strcmp(name, "__aa")) return "operator&&"; + if (!strcmp(name, "__oo")) return "operator||"; + if (!strcmp(name, "__pp")) return "operator++"; + if (!strcmp(name, "__mm")) return "operator--"; + if (!strcmp(name, "__cm")) return "operator,"; + if (!strcmp(name, "__rm")) return "operator->*"; + if (!strcmp(name, "__rf")) return "operator*"; + if (!strcmp(name, "__cl")) return "operator()"; + if (!strcmp(name, "__vc")) return "operator[]"; + return NULL; +} + +HashNameNode *CMangler_OperatorName(short token) { + switch (token) { + case TK_NEW: return GetHashNameNodeExport("__nw"); + case TK_DELETE: return GetHashNameNodeExport("__dl"); + case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa"); + case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla"); + case '+': return GetHashNameNodeExport("__pl"); + case '-': return GetHashNameNodeExport("__mi"); + case '*': return GetHashNameNodeExport("__ml"); + case '/': return GetHashNameNodeExport("__dv"); + case '%': return GetHashNameNodeExport("__md"); + case '^': return GetHashNameNodeExport("__er"); + case '&': return GetHashNameNodeExport("__ad"); + case '|': return GetHashNameNodeExport("__or"); + case '~': return GetHashNameNodeExport("__co"); + case '!': return GetHashNameNodeExport("__nt"); + case '=': return asop_name_node; + case '<': return GetHashNameNodeExport("__lt"); + case '>': return GetHashNameNodeExport("__gt"); + case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl"); + case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami"); + case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu"); + case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv"); + case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd"); + case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer"); + case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad"); + case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor"); + case TK_SHL: return GetHashNameNodeExport("__ls"); + case TK_SHR: return GetHashNameNodeExport("__rs"); + case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als"); + case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars"); + case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq"); + case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne"); + case TK_LESS_EQUAL: return GetHashNameNodeExport("__le"); + case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge"); + case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa"); + case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo"); + case TK_INCREMENT: return GetHashNameNodeExport("__pp"); + case TK_DECREMENT: return GetHashNameNodeExport("__mm"); + case ',': return GetHashNameNodeExport("__cm"); + case TK_ARROW_STAR: return GetHashNameNodeExport("__rm"); + case TK_ARROW: return GetHashNameNodeExport("__rf"); + case '(': return GetHashNameNodeExport("__cl"); + case '[': return GetHashNameNodeExport("__vc"); + default: return NULL; + } +} + +HashNameNode *CMangler_VTableName(TypeClass *tclass) { + HashNameNode *name; + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__vt__"); + CMangler_MangleClassName(tclass); + AppendGListByte(&name_mangle_list, 0); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) { + HashNameNode *name; + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__RTTI__"); + CMangler_MangleTypeAppend(type, qual); + AppendGListByte(&name_mangle_list, 0); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_ThunkName(Object *obj, int a, int b, int c) { + HashNameNode *linkname; + HashNameNode *name; + char buf[64]; + + linkname = CMangler_GetLinkName(obj); + name_mangle_list.size = 0; + if (b == 0) { + if (c < 0) + sprintf(buf, "_@%ld@", -a); + else + sprintf(buf, "_@%ld@%ld@", -a, c); + } else { + sprintf(buf, "_@%ld@%ld@%ld@", -a, c, b); + } + AppendGListName(&name_mangle_list, buf); + AppendGListID(&name_mangle_list, linkname->name + 1); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static void CMangler_CheckTemplateArguments(TemplArg *arg) { + ENode *expr; + + while (arg) { + if (arg->pid.type == TPT_NONTYPE) { + expr = arg->data.paramdecl.expr; +#line 360 + CError_ASSERT(expr); + if (expr->rtype->type != TYPETEMPLDEPEXPR) { + switch (expr->type) { + case EINTCONST: + break; + case EOBJREF: + CMangler_GetLinkName(expr->data.objref); + break; + default: +#line 383 + CError_FATAL(); + } + } + } + arg = arg->next; + } +} + +static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { + ENode *expr; + char buf[32]; + + AppendGListByte(&name_mangle_list, '<'); + + while (arg) { + if (arg->pid.type == TPT_NONTYPE) { + expr = arg->data.paramdecl.expr; +#line 409 + CError_ASSERT(expr); + if (expr->rtype->type != TYPETEMPLDEPEXPR) { + switch (expr->type) { + case EINTCONST: + CInt64_PrintDec(buf, expr->data.intval); + AppendGListName(&name_mangle_list, buf); + break; + case EOBJREF: + AppendGListByte(&name_mangle_list, '&'); + AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name); + break; + default: +#line 452 + CError_FATAL(); + } + } else { + AppendGListByte(&name_mangle_list, 'T'); + } + } else if (arg->pid.type == TPT_TYPE) { + CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual); + } else { +#line 467 + CError_ASSERT(arg->pid.type == TPT_TEMPLATE); + CMangler_MangleTypeAppend(arg->data.ttargtype, 0); + } + + if (arg->next) + AppendGListByte(&name_mangle_list, ','); + arg = arg->next; + } + + AppendGListByte(&name_mangle_list, '>'); +} + +HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) { + HashNameNode *name; + + CMangler_CheckTemplateArguments(args); + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, basename->name); + CMangler_AppendTemplateArgumentList(args); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static void CMangler_MangleTypeName(char *str) { + char buf[16]; + + sprintf(buf, "%d", strlen(str)); + AppendGListName(&name_mangle_list, buf); + AppendGListName(&name_mangle_list, str); +} + +static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) { + char *stack[10]; + int stackp; + + stack[0] = str; + stackp = 1; + while (nspace) { + if (nspace->name) { + stack[stackp++] = nspace->name->name; + if (stackp >= 9) + break; + } + nspace = nspace->parent; + } + + if (stackp > 1) { + AppendGListByte(&name_mangle_list, 'Q'); + AppendGListByte(&name_mangle_list, '0' + stackp); + } + + while (--stackp >= 0) + CMangler_MangleTypeName(stack[stackp]); +} + +static void CMangler_MangleClassName(TypeClass *tclass) { + if (!tclass->classname) + CMangler_MangleNameSpaceName(tclass->nspace->parent, "class"); + else + CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name); +} + +static void CMangler_MangleQualifier(UInt32 qual) { + if (qual & Q_CONST) + AppendGListByte(&name_mangle_list, 'C'); + if (qual & Q_VOLATILE) + AppendGListByte(&name_mangle_list, 'V'); +} + +static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { + char buf[16]; + + switch (type->type) { + case TYPEVOID: + CMangler_MangleQualifier(qual); + AppendGListByte(&name_mangle_list, 'v'); + break; + case TYPEINT: + case TYPEFLOAT: + CMangler_MangleQualifier(qual); + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + AppendGListByte(&name_mangle_list, 'b'); + return; + case IT_CHAR: + AppendGListByte(&name_mangle_list, 'c'); + return; + case IT_WCHAR_T: + AppendGListByte(&name_mangle_list, 'w'); + return; + case IT_UCHAR: + AppendGListName(&name_mangle_list, "Uc"); + return; + case IT_SCHAR: + AppendGListName(&name_mangle_list, "Sc"); + return; + case IT_SHORT: + AppendGListByte(&name_mangle_list, 's'); + return; + case IT_USHORT: + AppendGListName(&name_mangle_list, "Us"); + return; + case IT_INT: + AppendGListByte(&name_mangle_list, 'i'); + return; + case IT_UINT: + AppendGListName(&name_mangle_list, "Ui"); + return; + case IT_LONG: + AppendGListByte(&name_mangle_list, 'l'); + return; + case IT_ULONG: + AppendGListName(&name_mangle_list, "Ul"); + return; + case IT_LONGLONG: + AppendGListByte(&name_mangle_list, 'x'); + return; + case IT_ULONGLONG: + AppendGListName(&name_mangle_list, "Ux"); + return; + case IT_FLOAT: + AppendGListByte(&name_mangle_list, 'f'); + return; + case IT_SHORTDOUBLE: + AppendGListByte(&name_mangle_list, 'D'); + return; + case IT_DOUBLE: + AppendGListByte(&name_mangle_list, 'd'); + return; + case IT_LONGDOUBLE: + AppendGListByte(&name_mangle_list, 'r'); + return; + default: +#line 619 + CError_FATAL(); + } + case TYPEENUM: + CMangler_MangleQualifier(qual); + if (!TYPE_ENUM(type)->enumname) + CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum"); + else + CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name); + break; + case TYPEPOINTER: + CMangler_MangleQualifier(TYPE_POINTER(type)->qual); + if (TYPE_POINTER(type)->qual & Q_REFERENCE) + AppendGListByte(&name_mangle_list, 'R'); + else + AppendGListByte(&name_mangle_list, 'P'); + CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) { + AppendGListName(&name_mangle_list, "3<T>"); + } else { + CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual); + AppendGListByte(&name_mangle_list, 'M'); + CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2)); + CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual); + } + break; + case TYPEARRAY: + AppendGListByte(&name_mangle_list, 'A'); + if (TYPE_POINTER(type)->target->size) { + sprintf(buf, "%ld", type->size / TYPE_POINTER(type)->target->size); + AppendGListName(&name_mangle_list, buf); + } else { + AppendGListByte(&name_mangle_list, '0'); + } + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); + break; + case TYPEFUNC: + CMangler_MangleQualifier(qual); + AppendGListByte(&name_mangle_list, 'F'); + CMangler_MangleArgs(TYPE_FUNC(type)->args); + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual); + break; + case TYPESTRUCT: + CMangler_MangleQualifier(qual); + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_4: + AppendGListName(&name_mangle_list, "XUc"); + return; + case STRUCT_TYPE_5: + AppendGListName(&name_mangle_list, "Xc"); + return; + case STRUCT_TYPE_6: + AppendGListName(&name_mangle_list, "XC"); + return; + case STRUCT_TYPE_7: + AppendGListName(&name_mangle_list, "XUs"); + return; + case STRUCT_TYPE_8: + AppendGListName(&name_mangle_list, "Xs"); + return; + case STRUCT_TYPE_9: + AppendGListName(&name_mangle_list, "XS"); + return; + case STRUCT_TYPE_A: + AppendGListName(&name_mangle_list, "XUi"); + return; + case STRUCT_TYPE_B: + AppendGListName(&name_mangle_list, "Xi"); + return; + case STRUCT_TYPE_C: + AppendGListName(&name_mangle_list, "XI"); + return; + case STRUCT_TYPE_D: + AppendGListName(&name_mangle_list, "Xf"); + return; + case STRUCT_TYPE_E: + AppendGListName(&name_mangle_list, "Xp"); + return; + } + + if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) { + CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name); + return; + } + + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_STRUCT: + AppendGListName(&name_mangle_list, "struct"); + break; + case STRUCT_TYPE_UNION: + AppendGListName(&name_mangle_list, "union"); + break; + case STRUCT_TYPE_CLASS: + AppendGListName(&name_mangle_list, "class"); + break; + default: +#line 701 + CError_FATAL(); + } + break; + + case TYPECLASS: + CMangler_MangleQualifier(qual); + CMangler_MangleClassName(TYPE_CLASS(type)); + break; + + case TYPETEMPLATE: + AppendGListName(&name_mangle_list, "1T"); + break; + + default: +#line 716 + CError_FATAL(); + } +} + +void CMangler_MangleType(Type *type, UInt32 qual) { + name_mangle_list.size = 0; + CMangler_MangleTypeAppend(type, qual); +} + +static void CMangler_MangleArgs(FuncArg *args) { + TypePointer ptr; + + if (args) { + if (args->type) { + while (args) { + if (args != &elipsis && args != &oldstyle) { + if (args->type->type == TYPEPOINTER) { + ptr = *TYPE_POINTER(args->type); + ptr.qual &= ~(Q_CONST | Q_VOLATILE); + CMangler_MangleTypeAppend((Type *) &ptr, args->qual); + } else { + CMangler_MangleTypeAppend(args->type, 0); + } + } else { + AppendGListByte(&name_mangle_list, 'e'); + } + args = args->next; + } + } else { + AppendGListByte(&name_mangle_list, 'e'); + } + } else { + AppendGListByte(&name_mangle_list, 'v'); + } +} + +static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) { + TypeFunc *tfunc = TYPE_FUNC(obj->type); + FuncArg *arg = tfunc->args; + + AppendGListName(&name_mangle_list, obj->name->name); + if (obj->u.func.inst) { + if (tfunc->flags & FUNC_FLAGS_40) + CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); + CMangler_AppendTemplateArgumentList(obj->u.func.inst->args); + } + AppendGListName(&name_mangle_list, "__"); + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + + if (nspace) { + CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); + if (nspace->theclass) { + if (obj->name == destructor_name_node) { + AppendGListName(&name_mangle_list, "Fv"); + return; + } + if (arg) { + if (obj->name == constructor_name_node) { + arg = arg->next; + if (arg && (nspace->theclass->flags & CLASS_FLAGS_20)) + arg = arg->next; + } else { + if ((tfunc->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(tfunc)->x26) { + CMangler_MangleQualifier(arg->qual); + arg = arg->next; + } + } + } + } + } + + AppendGListByte(&name_mangle_list, 'F'); + CMangler_MangleArgs(arg); + if (obj->u.func.inst && copts.new_mangler) { + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); + } +} + +HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) { + HashNameNode *name; + + if (CTemplTool_IsTemplateArgumentDependentType(type)) + return GetHashNameNodeExport("__op"); + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__op"); + CMangler_MangleTypeAppend(type, qual); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_MangleNameToUpper(char *str) { + HashNameNode *name; + + name_mangle_list.size = 0; + while (*str) { + AppendGListByte(&name_mangle_list, toupper(*(str++))); + } + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_FunctionLinkName(Object *obj) { + HashNameNode *name; + NameSpace *nspace; + + if (obj->u.func.inst) + CMangler_CheckTemplateArguments(obj->u.func.inst->args); + + for (nspace = obj->nspace; nspace; nspace = nspace->parent) { + if (nspace->name) + break; + } + + name_mangle_list.size = 0; + if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) { + AppendGListData(&name_mangle_list, "_", 1); + AppendGListID(&name_mangle_list, obj->name->name); + } else if ((obj->qual & Q_80000) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) { + AppendGListData(&name_mangle_list, "_", 1); + CMangler_MangleFunction(obj, nspace); + AppendGListByte(&name_mangle_list, 0); + } else { + AppendGListData(&name_mangle_list, "_", 1); + AppendGListID(&name_mangle_list, obj->name->name); + } + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_GetCovariantFunctionName(Object *obj, Type *type) { + HashNameNode *linkname; + HashNameNode *name; + + linkname = CMangler_GetLinkName(obj); + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, linkname->name); + AppendGListName(&name_mangle_list, "@@"); + CMangler_MangleTypeAppend(type, 0); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_DataLinkName(Object *obj) { + NameSpace *nspace; + HashNameNode *name; + + nspace = obj->nspace; + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + + name_mangle_list.size = 0; + AppendGListData(&name_mangle_list, "_", 1); + AppendGListName(&name_mangle_list, obj->name->name); + + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + if (nspace && (obj->qual & Q_80000)) { + AppendGListName(&name_mangle_list, "__"); + CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); + } + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_GetLinkName(Object *obj) { + while (obj->datatype == DALIAS) + obj = obj->u.alias.object; + + switch (obj->datatype) { + case DFUNC: + case DVFUNC: + if (!obj->u.func.linkname) + obj->u.func.linkname = CMangler_FunctionLinkName(obj); + return obj->u.func.linkname; + case DDATA: + if (!obj->u.data.linkname) + obj->u.data.linkname = CMangler_DataLinkName(obj); + return obj->u.data.linkname; + case DINLINEFUNC: + return CMangler_FunctionLinkName(obj); + case DLOCAL: + case DABSOLUTE: + case DLABEL: + return obj->name; + case DNONLAZYPTR: + if (!obj->u.toc.linkname) + obj->u.toc.linkname = CMangler_DataLinkName(obj); + return obj->u.toc.linkname; + default: +#line 1110 + CError_FATAL(); + return NULL; + } +} diff --git a/compiler_and_linker/unsorted/CParser.c b/compiler_and_linker/unsorted/CParser.c new file mode 100644 index 0000000..8228159 --- /dev/null +++ b/compiler_and_linker/unsorted/CParser.c @@ -0,0 +1,3520 @@ +#include "compiler/CParser.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.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/templates.h" +#include "cos.h" + +// TODO MOVE ME +extern SInt32 symdecloffset; +extern void CSOM_Setup(Boolean is_precompiler); +extern void CSOM_Cleanup(void); +extern void CIRTrans_Setup(void); +extern void CObjC_Setup(void); +extern void CObjC_GenerateModule(void); +extern Type *CObjC_ParseTypeProtocol(Type *type); +extern void CObjC_ParseProtocol(void); +extern void CObjC_ParseClassDeclaration(void); +extern void CObjC_ParseInterface(void); +extern void CObjC_ParseImplementation(void); +extern void CTempl_Setup(void); +extern void CTempl_Parse(TypeClass *tclass, short access); +extern Boolean CTempl_Instantiate(void); +extern Boolean CInline_GenerateDeferredFuncs(void); +extern void CTempl_Cleanup(); +extern void CIRTrans_Cleanup(); +extern void CObjC_Cleanup(); +extern void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *declinfo); +extern void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *declinfo); +extern void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *declinfo); +extern Boolean CTemplTool_TemplDepTypeCompare(TypeTemplDep *a, TypeTemplDep *b); +extern Boolean CTemplTool_IsSameTemplateType(Type *a, Type *b); +extern TemplStack *ctempl_curinstance; +extern Type *CObjC_ParseID(void); +extern void CodeGen_UpdateOptimizerOptions(void); + +FileOffsetInfo cparser_fileoffset; +TStreamElement symdecltoken; +ParserTryBlock *trychain; +Boolean inassembler; +Boolean dont_set_references; +TypeStruct ptmstruct; +TypeStruct catchinfostruct; +Boolean in_assembler; +Boolean illegalimplicitconversion; +Boolean in_func_arglist; +NameSpaceName *newp_fobj; +NameSpaceName *newa_fobj; +NameSpaceName *delp_fobj; +NameSpaceName *dela_fobj; +Object *newh_func; +Object *delh_func; +Object *copy_func; +Object *clear_func; +Object *Rgtid_func; +Object *Rdync_func; +Object *rt_ptmf_cast; +Object *rt_ptmf_cmpr; +Object *rt_ptmf_test; +Object *rt_ptmf_call; +Object *rt_ptmf_scall; +Object *rt_ptmf_call4; +Object *rt_ptmf_scall4; +Object *rt_ptmf_null; +Object *rt_som_new; +Object *rt_som_newcheck; +Object *rt_som_check; +Object *rt_som_glue1; +Object *rt_som_glue2; +Object *rt_som_glue3; +Object *carr_func; +Object *cnar_func; +Object *darr_func; +Object *dnar_func; +Object *dnar3_func; +Object *Xgreg_func; +Object *Xthrw_func; +Object *Xicth_func; +Object *Xecth_func; +Object *Xunex_func; +COpts copts; +GList name_mangle_list; +HashNameNode *no_name_node; +HashNameNode *temp_argument_name; +HashNameNode *this_name_node; +HashNameNode *self_name_node; +HashNameNode *vptr_name_node; +CallbackAction *callbackactions; +Boolean fatalerrors; +Boolean anyerrors; +jmp_buf errorreturn; +static HashNameNode *uniquenamespacename; +static SInt32 uniqueid; + +struct ClassAction { + struct ClassAction *next; + TypeClass *tclass; +}; +static struct ClassAction *cparser_classactions; + +struct ParentCleanup { + struct ParentCleanup *next; + TypeClass *tclass; +}; +static struct ParentCleanup *cparser_parentcleanup; + +struct SFuncList { + struct SFuncList *next; + Object *func; + Object *obj; + ENode *expr; +}; +static struct SFuncList *cparser_sfunclist; + +char string[256]; +SInt32 compilererrornum; +SInt32 compilererrfile; +SInt32 compilererrline; + +Type sttemplexpr = {TYPETEMPLDEPEXPR, 0}; +Type stillegal = {TYPEILLEGAL, 1}; +Type stvoid = {TYPEVOID, 0}; +TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0}; +TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0}; + +// forward declarations +static void CParser_ParseDeclaration(DeclInfo *di); + +Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) { + Object *obj; + FuncArg *args; + FuncArg *arg; + TypeFunc *tfunc; + va_list va; + + args = NULL; + if (argcount) { + va_start(va, argcount); + while (--argcount >= 0) { + if (args) { + arg->next = CParser_NewFuncArg(); + arg = arg->next; + } else { + arg = CParser_NewFuncArg(); + args = arg; + } + arg->type = va_arg(va, Type *); + } + va_end(va); + } + + obj = CParser_NewFunctionObject(NULL); + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = rettype; + tfunc->args = args; + CDecl_SetFuncFlags(tfunc, 0); + + obj->name = name; + obj->type = TYPE(tfunc); + if (flag == 1) + obj->qual = Q_80000; + + return obj; +} + +Boolean CParser_IsPublicRuntimeObject(Object *obj) { + if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next) + return 1; + if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next) + return 1; + if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next) + return 1; + if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next) + return 1; + return CodeGen_IsPublicRuntimeObject(obj); +} + +Object *CParser_FindPublicRuntimeObject(HashNameNode *name) { + NameSpaceObjectList *list = CScope_FindName(cscope_root, name); + if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG)) + return OBJECT(list->object); + else + return NULL; +} + +Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) { + if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW)))) + return 0; + if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY)))) + return 0; + if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE)))) + return 0; + if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY)))) + return 0; + + newh_func->name = GetHashNameNodeExport("__new_hdl"); + delh_func->name = GetHashNameNodeExport("__del_hdl"); + copy_func->name = GetHashNameNodeExport("__copy"); + clear_func->name = GetHashNameNodeExport("__clear"); + Rgtid_func->name = GetHashNameNodeExport("__get_typeid"); + Rdync_func->name = GetHashNameNodeExport("__dynamic_cast"); + rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast"); + rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr"); + rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test"); + rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call"); + rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall"); + rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4"); + rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4"); + rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null"); + rt_som_new->name = GetHashNameNodeExport("__som_new"); + rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new"); + rt_som_check->name = GetHashNameNodeExport("__som_check_ev"); + rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4"); + rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5"); + rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_"); + carr_func->name = GetHashNameNodeExport("__construct_array"); + cnar_func->name = GetHashNameNodeExport("__construct_new_array"); + darr_func->name = GetHashNameNodeExport("__destroy_arr"); + dnar_func->name = GetHashNameNodeExport("__destroy_new_array"); + dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3"); + Xgreg_func->name = GetHashNameNodeExport("__register_global_object"); + Xthrw_func->name = GetHashNameNodeExport("__throw"); + Xicth_func->name = GetHashNameNodeExport("__init__catch"); + Xecth_func->name = GetHashNameNodeExport("__end__catch"); + Xunex_func->name = GetHashNameNodeExport("__unexpected"); + + CMangler_Setup(); + + no_name_node = GetHashNameNodeExport("@no_name@"); + temp_argument_name = GetHashNameNodeExport("@temp_ptr@"); + this_name_node = GetHashNameNodeExport("this"); + self_name_node = GetHashNameNodeExport("self"); + vptr_name_node = GetHashNameNodeExport("__vptr$"); + + CSOM_Setup(is_precompiler); + return CodeGen_ReInitRuntimeObjects(is_precompiler); +} + +static void CParser_SetupRuntimeObjects(void) { + ExceptSpecList *exspecs; + Type *sizet; + Object *func; + + exspecs = galloc(sizeof(ExceptSpecList)); + memclrw(exspecs, sizeof(ExceptSpecList)); + + sizet = CABI_GetSizeTType(); + + func = CParser_NewRTFunc( + TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1, + 1, sizet); + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1, + 1, sizet); + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1, + 1, &void_ptr); +#line 379 + CError_ASSERT(IS_TYPE_FUNC(func->type)); + TYPE_FUNC(func->type)->exspecs = exspecs; + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1, + 1, &void_ptr); +#line 387 + CError_ASSERT(IS_TYPE_FUNC(func->type)); + TYPE_FUNC(func->type)->exspecs = exspecs; + CScope_AddGlobalObject(func); + + newh_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 1, sizet); + delh_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + + Rgtid_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 2, &void_ptr, &stsignedlong); + Rdync_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort); + + copy_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &void_ptr, &void_ptr, sizet); + clear_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 2, &void_ptr, sizet); + + rt_ptmf_cast = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &stsignedlong, &void_ptr, &void_ptr); + rt_ptmf_cmpr = CParser_NewRTFunc( + TYPE(&stsignedlong), NULL, 2, + 2, &void_ptr, &void_ptr); + rt_ptmf_test = CParser_NewRTFunc( + TYPE(&stsignedlong), NULL, 2, + 1, &void_ptr); + + rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + + rt_ptmf_null = CParser_NewGlobalDataObject(NULL); + rt_ptmf_null->type = &stvoid; + + rt_som_new = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &void_ptr, &stsignedlong, &stsignedlong); + rt_som_newcheck = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + rt_som_check = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + + carr_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); + cnar_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); + darr_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 4, &void_ptr, &void_ptr, sizet, sizet); + dnar_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 2, &void_ptr, &void_ptr); + dnar3_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort); + + Xgreg_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 3, &void_ptr, &void_ptr, &void_ptr); + Xthrw_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 3, &void_ptr, &void_ptr, &void_ptr); + Xicth_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + Xecth_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + Xunex_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + + CodeGen_SetupRuntimeObjects(); +#line 534 + CError_ASSERT(CParser_ReInitRuntimeObjects(0)); +} + +void CParser_Setup(void) { + CScope_Setup(); + + name_mangle_list.data = NULL; + if (InitGList(&name_mangle_list, 256)) + CError_NoMem(); + + void_ptr.size = 4; + CError_Init(); + CInit_Init(); + CClass_Init(); + CIRTrans_Setup(); + CObjC_Setup(); + CInline_Init(); + + in_assembler = 0; + in_func_arglist = 0; + CParser_SetUniqueID(1); + dont_set_references = 0; + + copts.side_effects = 1; + cparser_classactions = NULL; + name_obj_check = NULL; + callbackactions = NULL; + init_expressions = NULL; + cparser_sfunclist = NULL; + trychain = NULL; + cparser_parentcleanup = NULL; + + memclrw(&cparser_fileoffset, sizeof(FileOffsetInfo)); + + memclrw(&catchinfostruct, sizeof(TypeStruct)); + catchinfostruct.type = TYPESTRUCT; + catchinfostruct.size = 24; + catchinfostruct.stype = STRUCT_TYPE_STRUCT; + catchinfostruct.align = 4; + + memclrw(&ptmstruct, sizeof(TypeStruct)); + ptmstruct.type = TYPESTRUCT; + ptmstruct.size = 12; + ptmstruct.stype = STRUCT_TYPE_STRUCT; + ptmstruct.align = 4; + + CMach_Configure(); + CTempl_Setup(); + + uniquenamespacename = NULL; + disallowgreaterthan = 0; + + CParser_SetupRuntimeObjects(); +} + +void CParser_Cleanup(void) { + CTempl_Cleanup(); + CIRTrans_Cleanup(); + CObjC_Cleanup(); + CScope_Cleanup(); + FreeGList(&name_mangle_list); +} + +short GetPrec(short token) { + switch (token) { + case '%': + case '*': + case '/': + return 11; + case '+': + case '-': + return 10; + case TK_SHL: + case TK_SHR: + return 9; + case '<': + case '>': + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + return 8; + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + return 7; + case '&': + return 6; + case '^': + return 5; + case '|': + return 4; + case TK_LOGICAL_AND: + return 3; + case TK_LOGICAL_OR: + return 2; + default: + return 0; + } +} + +Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2) { + HashNameNode *name; + + switch ((tk = lex())) { + case TK_NEW: + case TK_DELETE: + if (lookahead() == '[') { + lex(); + if (lex() != ']') + CError_Error(125); + //if (tk == TK_NEW) + // tk = TK_NEW_ARRAY; + //else + // tk = TK_DELETE_ARRAY; + tk = (tk == TK_NEW) ? TK_NEW_ARRAY : TK_DELETE_ARRAY; + } + break; + case '(': + if ((tk = lex()) != ')') { + CError_Error(204); + return 0; + } + tk = '('; + break; + case '[': + if ((tk = lex()) != ']') { + CError_Error(204); + return 0; + } + tk = '['; + break; + } + + if ((name = CMangler_OperatorName(tk))) { + if (token) + *token = tk; + tk = lex(); + tkidentifier = name; + return 1; + } + + if (flag1) { + if (flag2) { + DeclInfo declinfo; + memclrw(&declinfo, sizeof(DeclInfo)); + conversion_type_name(&declinfo); + tkidentifier = CMangler_ConversionFuncName(declinfo.thetype, declinfo.qual); + } + if (token) + *token = 0; + return 1; + } else { + CError_Error(204); + return 0; + } +} + +SInt32 CParser_GetUniqueID(void) { + return uniqueid++; +} + +void CParser_PrintUniqueID(char *buf) { + SInt32 id; + char mybuf[16]; + char *ptr; + + ptr = mybuf; + id = CParser_GetUniqueID(); + while (id) { + *ptr = '0' + (id - ((id / 10) * 10)); + id = id / 10; + ptr++; + } + + while (ptr > mybuf) + *(buf++) = *(--ptr); + + *buf = 0; +} + +void CParser_SetUniqueID(SInt32 id) { + uniqueid = id; +} + +HashNameNode *CParser_GetUniqueName(void) { + char buf[20]; + buf[0] = '@'; + CParser_PrintUniqueID(buf + 1); + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_NameConcat(char *a, char *b) { + char mybuf[256]; + char *buf; + char *dst; + int len; + + len = strlen(a) + strlen(b); + if (len > (sizeof(mybuf) - 1)) { + buf = lalloc(len + 1); + dst = buf; + } else { + buf = mybuf; + dst = buf; + } + + while (*a) + *(dst++) = *(a++); + while (*b) + *(dst++) = *(b++); + *dst = 0; + + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_AppendUniqueName(char *prefix) { + char buf[256]; + char *dst; + int i; + + dst = buf; + for (i = 0; *prefix && i < 240; i++) { + *(dst++) = *(prefix++); + } + *(dst++) = '$'; + + CParser_PrintUniqueID(dst); + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_AppendUniqueNameFile(char *prefix) { + Str255 filename; + char buf[256]; + char *src; + char *dst; + char c; + int i; + int j; + int len; + + dst = buf; + for (i = 0; *prefix && i < 200; i++) { + *(dst++) = *(prefix++); + } + *(dst++) = '$'; + + CParser_PrintUniqueID(dst); + + while (*dst) { + dst++; + i++; + } + + COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, filename); + src = (char *) &filename[1]; + len = filename[0]; + for (j = 0; j < len && i < 255; j++, i++) { + c = *(src++); + if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) + c = '_'; + *(dst++) = c; + } + + dst[0] = 0; + return GetHashNameNodeExport(buf); +} + +static HashNameNode *CParser_GetUnnamedNameSpaceName(void) { + Str255 filename; + char buf[256]; + char *src; + char *dst; + char c; + int i; + int len; + + if (!uniquenamespacename) { + strcpy(buf, "@unnamed@"); + dst = buf + strlen(buf); + + COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, filename); + src = (char *) &filename[1]; + len = filename[0]; + for (i = 0; i < len && dst < &buf[254]; i++) { + c = *(src++); + if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) + c = '_'; + *(dst++) = c; + } + + dst[0] = '@'; + dst[1] = 0; + uniquenamespacename = GetHashNameNodeExport(buf); + } + + return uniquenamespacename; +} + +Boolean IsTempName(HashNameNode *name) { + return !name || (name->name[0] == '@') || (name->name[0] == '$'); +} + +static void CParser_SetCFMFlags(Object *object, DeclInfo *declinfo) { + if (declinfo && declinfo->exportflags) + object->flags |= declinfo->exportflags; + + if (object->datatype == DDATA) { + if (copts.export) + object->flags |= OBJECT_FLAGS_40; + if (copts.internal) + object->flags |= OBJECT_FLAGS_10; + } else if (copts.internal) { + object->flags |= OBJECT_FLAGS_10; + } else { + if (copts.import) + object->flags |= OBJECT_FLAGS_20; + if (copts.export) + object->flags |= OBJECT_FLAGS_40; + if (copts.lib_export) + object->flags |= OBJECT_FLAGS_20 | OBJECT_FLAGS_40; + } +} + +void CParser_UpdateObject(Object *object, DeclInfo *declinfo) { + if (declinfo && declinfo->section) + object->section = declinfo->section; + + CParser_SetCFMFlags(object, declinfo); + CodeGen_UpdateObject(object); +} + +Object *CParser_NewObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + CParser_SetCFMFlags(object, declinfo); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + return object; +} + +Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) { + Object *object = lalloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + } + + if (add_to_locals) { + ObjectList *list = lalloc(sizeof(ObjectList)); + list->object = object; + list->next = locals; + locals = list; + } + + return object; +} + +Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DDATA; + object->nspace = cscope_current; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + if (copts.cplusplus && !declinfo->x4E) + object->qual |= Q_80000; + } + + CParser_UpdateObject(object, declinfo); + return object; +} + +Object *CParser_NewCompilerDefDataObject(void) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DDATA; + object->nspace = cscope_root; + + return object; +} + +Object *CParser_NewFunctionObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DFUNC; + object->nspace = cscope_current; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + if (copts.cplusplus && !declinfo->x4E) + object->qual |= Q_80000; + } + + CParser_UpdateObject(object, declinfo); + return object; +} + +Object *CParser_NewCompilerDefFunctionObject(void) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DFUNC; + object->nspace = cscope_root; + return object; +} + +Object *CParser_NewAliasObject(Object *object, SInt32 offset) { + Object *alias = galloc(sizeof(Object)); + *alias = *object; + alias->datatype = DALIAS; + alias->u.alias.object = object; + alias->u.alias.member = NULL; + alias->u.alias.offset = offset; + CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias)); + return alias; +} + +FuncArg *CParser_NewFuncArg(void) { + FuncArg *arg = galloc(sizeof(FuncArg)); + memclrw(arg, sizeof(FuncArg)); + return arg; +} + +Type *atomtype(void) { + switch (tksize) { + default: +#line 1145 + CError_FATAL(); + case ATOM_VOID: return &stvoid; + case ATOM_CHAR: return TYPE(&stchar); + case ATOM_WCHAR: return TYPE(&stwchar); + case ATOM_UCHAR: return TYPE(&stunsignedchar); + case ATOM_SHORT: return TYPE(&stsignedshort); + case ATOM_USHORT: return TYPE(&stunsignedshort); + case ATOM_INT: return TYPE(&stsignedint); + case ATOM_UINT: return TYPE(&stunsignedint); + case ATOM_LONG: return TYPE(&stsignedlong); + case ATOM_ULONG: return TYPE(&stunsignedlong); + case ATOM_LONGLONG: return TYPE(&stsignedlonglong); + case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong); + case ATOM_FLOAT: return TYPE(&stfloat); + case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble); + case ATOM_DOUBLE: return TYPE(&stdouble); + case ATOM_LONGDOUBLE: return TYPE(&stlongdouble); + } +} + +Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) { + NameSpaceObjectList *list; + NameSpaceObjectList *scan; + NameSpaceObjectList mylist; + CScopeParseResult pr; + Boolean first_time; + Boolean retry_flag; + Type *sizet; + Object *obj; + + list = NULL; + *outflag = 0; + if (IS_TYPE_CLASS(type) && !flag2) { + HashNameNode *name; + name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name; + if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { + if (pr.obj_10) { + mylist.next = NULL; + mylist.object = pr.obj_10; + list = &mylist; + } else { +#line 1202 + CError_ASSERT(pr.nsol_14); + list = pr.nsol_14; + } + } else if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) { +#line 1210 + CError_ASSERT(!args && !flag1); + return delh_func; + } + } + + first_time = 1; + retry_flag = flag1; + while (1) { + if (!args) { + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + !TYPE_FUNC(obj->type)->args->next && + is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) + ) + return obj; + } + +#line 1231 + CError_ASSERT(first_time); + + sizet = CABI_GetSizeTType(); + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + TYPE_FUNC(obj->type)->args->next && + !TYPE_FUNC(obj->type)->args->next->next && + is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) && + TYPE_FUNC(obj->type)->args->next->type == sizet + ) { + *outflag = 1; + return obj; + } + } + } else { + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + TYPE_FUNC(obj->type)->args->next && + is_arglistsame(TYPE_FUNC(obj->type)->args->next, args) + ) { + *outflag = 1; + return obj; + } + } + + if (!first_time) + return NULL; + } + + if (list) + CError_Warning(375, type, 0); + + list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first; + first_time = 0; + } +} + +static Boolean oldstylecompatible(FuncArg *arg) { + if (copts.ignore_oldstyle) + return 1; + + while (arg) { + if (arg == &elipsis) + return 0; + switch (arg->type->type) { + case TYPEINT: + if (TYPE_INTEGRAL(arg->type)->integral < IT_INT) + return 0; + break; + case TYPEFLOAT: + if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE) + return 0; + break; + } + arg = arg->next; + } + + return 1; +} + +static Boolean is_arglistequal(FuncArg *a, FuncArg *b) { + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return oldstylecompatible(b); + } else { + if (b == &oldstyle) + return oldstylecompatible(a); + } + + while (1) { + if (a == &elipsis || b == &elipsis) + return 1; + + if (!a) + return !b; + if (!b) + return 0; + + if (copts.mpwc_relax && !copts.cplusplus) { + if (!is_typeequal(a->type, b->type)) + return 0; + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + + if (a->type->type == TYPEPOINTER && a->qual != b->qual) + return 0; + + a = a->next; + b = b->next; + } +} + +short is_memberpointerequal(Type *a, Type *b) { + FuncArg *arg_a; + FuncArg *arg_b; + + if (a->type != b->type) + return 0; + if (!IS_TYPE_FUNC(a)) + return is_typeequal(a, b); + + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + + if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) + return 0; + +#line 1345 + CError_ASSERT((arg_a = TYPE_FUNC(a)->args)); + CError_ASSERT((arg_b = TYPE_FUNC(b)->args)); + + if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80) { +#line 1351 + CError_ASSERT((arg_a = arg_a->next)); + } + + if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80) { +#line 1355 + CError_ASSERT((arg_b = arg_b->next)); + } + + if (arg_a->qual != arg_b->qual) + return 0; + + return is_arglistsame(arg_a->next, arg_b->next); +} + +short is_typeequal(Type *a, Type *b) { +restart: + if (a->type != b->type) + return 0; + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid) + return 1; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + if (copts.mpwc_relax && !copts.cplusplus) + return 1; + goto restart; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size && b->size && a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (copts.cplusplus || !copts.cpp_extensions) { + if (copts.mpwc_relax && !copts.cplusplus) { + if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + } else { + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + } + if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) + return 0; + } + return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + default: +#line 1441 + CError_FATAL(); + return 0; + } +} + +short iscpp_typeequal(Type *a, Type *b) { + restart: + if (a->type != b->type) + return 0; + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if (TYPE_POINTER(b)->target == &stvoid) { + if (TYPE_POINTER(a)->target == &stvoid) + return 1; + else + return -1; + } + if (TYPE_POINTER(a)->target == &stvoid) { + illegalimplicitconversion = 1; + return 0; + } + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size && b->size && a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) + return 0; + return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + default: +#line 1500 + CError_FATAL(); + return 0; + } +} + +short CParser_CompareArgLists(FuncArg *a, FuncArg *b) { + Boolean r30; + + r30 = 0; + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return 2; + } + if (b == &oldstyle) + return 2; + + while (1) { + if (a == &elipsis) { + if (b != &elipsis) + return 0; + break; + } + if (b == &elipsis) + return 0; + + if (a == NULL) { + if (b) + return 0; + break; + } + if (b == NULL) + return 0; + + if (a->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) { + if (IS_TYPE_REFERENCE(b->type)) { + if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) + return 0; + if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + } else { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(TYPE_POINTER(a->type)->target, b->type)) + return 0; + if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + r30 = 1; + } + } else { + if (b->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) + return 0; + if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + r30 = 1; + } else { + if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) + return 0; + if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + } + } else { + return 0; + } + } + } else { + if (b->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) + return 0; + r30 = 1; + } else { + return 0; + } + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + } + + a = a->next; + b = b->next; + } + + if (r30) + return 2; + return 1; +} + +Boolean is_arglistsame(FuncArg *a, FuncArg *b) { + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return oldstylecompatible(b); + } else { + if (b == &oldstyle) + return oldstylecompatible(a); + } + + while (1) { + if (!a || !b || a == &elipsis || b == &elipsis) + return a == b; + + if (a->type->type == TYPEPOINTER) { + if (b->type->type != TYPEPOINTER || + (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) || + !is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) || + IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) + return 0; + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + + a = a->next; + b = b->next; + } +} + +short is_typesame(Type *a, Type *b) { +restart: + if (a->type != b->type) { + if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_FLAGS_100)) + return CTemplTool_IsSameTemplateType(b, a); + if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_FLAGS_100)) + return CTemplTool_IsSameTemplateType(a, b); + return 0; + } + + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEMEMBERPOINTER: + if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2)) + return 0; + if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual) + return 0; + if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) + return 0; + return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + default: +#line 1709 + CError_FATAL(); + return 0; + } +} + +Type *CParser_GetBoolType(void) { + if (copts.cplusplus && copts.booltruefalse) + return TYPE(&stbool); + else + return TYPE(&stsignedint); +} + +Type *CParser_GetWCharType(void) { + if (copts.cplusplus && copts.wchar_type) + return TYPE(&stwchar); + else + return TYPE(&stsignedint); +} + +short CParser_GetOperator(ENodeType t) { + switch (t) { + default: +#line 1748 + CError_FATAL(); + case EMONMIN: return '-'; + case EBINNOT: return '~'; + case ELOGNOT: return '!'; + case EADD: return '+'; + case ESUB: return '-'; + case EMUL: return '*'; + case EDIV: return '/'; + case EMODULO: return '%'; + case EAND: return '&'; + case EXOR: return '^'; + case EOR: return '|'; + case ESHL: return TK_SHL; + case ESHR: return TK_SHR; + case ELESS: return '<'; + case EGREATER: return '>'; + case ELESSEQU: return TK_LESS_EQUAL; + case EGREATEREQU: return TK_GREATER_EQUAL; + case EEQU: return TK_LOGICAL_EQ; + case ENOTEQU: return TK_LOGICAL_NE; + } +} + +Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) { + if ((a & Q_CONST) && !(b & Q_CONST)) { + return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); + } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { + return ((a & Q_CONST) || !(b & Q_CONST)); + } + return 0; +} + +Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) { + if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE))) + return 1; + + if ((a & Q_CONST) && !(b & Q_CONST)) { + return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); + } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { + return ((a & Q_CONST) || !(b & Q_CONST)); + } + return 0; +} + +Boolean is_unsigned(Type *type) { + if (IS_TYPE_ENUM(type)) + type = TYPE_ENUM(type)->enumtype; + + if ( + (type == TYPE(&stunsignedchar)) || + (type == TYPE(&stunsignedshort)) || + (type == TYPE(&stunsignedint)) || + (type == TYPE(&stunsignedlong)) || + (type == TYPE(&stunsignedlonglong)) || + (type == TYPE(&stbool)) || + (copts.unsignedchars && (type == TYPE(&stchar))) || + (type->type == TYPEPOINTER)) + return 1; + + return 0; +} + +StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) { + StructMember *member; + + for (member = tstruct->members; member; member = member->next) { + if (member->name == name) + return member; + } + + return NULL; +} + +void appendmember(TypeStruct *tstruct, StructMember *member) { + StructMember *last; + + if (!tstruct->members) { + tstruct->members = member; + return; + } + + for (last = tstruct->members; last->next; last = last->next) {} + last->next = member; +} + +static void CParser_InsertTryBlock(ParserTryBlock *block) { + block->cscope_current = cscope_current; + block->cscope_currentclass = cscope_currentclass; + block->cscope_currentfunc = cscope_currentfunc; + block->ctempl_curinstance = ctempl_curinstance; + block->cerror_locktoken = cerror_locktoken; + block->cscope_is_member_func = cscope_is_member_func; + block->next = trychain; + trychain = block; +} + +static void CParser_RemoveTryBlock(ParserTryBlock *block) { + cscope_current = block->cscope_current; + cscope_currentclass = block->cscope_currentclass; + cscope_currentfunc = block->cscope_currentfunc; + ctempl_curinstance = block->ctempl_curinstance; + cerror_locktoken = block->cerror_locktoken; + cscope_is_member_func = block->cscope_is_member_func; + trychain = block->next; +} + +static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) { + Boolean result; + DeclInfo declinfo; + struct ParserTryBlock tryblock; + + switch (tk) { + case TK_IDENTIFIER: + case TK_COLON_COLON: + break; + case TK_VOID: + case TK_CHAR: + case TK_SHORT: + case TK_INT: + case TK_LONG: + case TK_FLOAT: + case TK_DOUBLE: + case TK_SIGNED: + case TK_UNSIGNED: + case TK_UNK_113: + case TK_UNK_114: + case TK_UNK_115: + case TK_UNK_116: + case TK_UNK_117: + case TK_UNK_118: + case TK_UNK_119: + case TK_UNK_11A: + case TK_BOOL: + case TK_WCHAR_T: + if (lookahead() != '(') + return 1; + break; + default: + return 1; + } + + result = 0; + CParser_InsertTryBlock(&tryblock); + if (setjmp(tryblock.jmpbuf) == 0) { + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&declinfo, 0); + if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) { + if (flag1) { + declinfo.x46 = flag3; + scandeclarator(&declinfo); + if (!(flag2 && declinfo.name)) { + if (!token) { + if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>') + result = 1; + } else { + result = (tk == token); + } + } + } else { + result = 1; + } + } + } + + CParser_RemoveTryBlock(&tryblock); + return result; +} + +Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) { + SInt32 state; + + if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) + return 0; + } else { + if (!copts.cplusplus) + return 1; + } + + CPrep_TokenStreamGetState(&state); + if (TryIsDeclaration(flag1, flag2, flag3, token)) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } else { + CPrep_TokenStreamSetCurState(&state); + return 0; + } +} + +Boolean islookaheaddeclaration(void) { + SInt32 state; + + CPrep_TokenStreamGetState(&state); + tk = lex(); + if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) { + CPrep_TokenStreamSetCurState(&state); + return 0; + } + } else { + if (!copts.cplusplus) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } + } + + if (TryIsDeclaration(1, 1, 0, ')')) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } else { + CPrep_TokenStreamSetCurState(&state); + return 0; + } +} + +Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) { + SInt32 state; + DeclInfo di; + struct ParserTryBlock tryblock; + + memclrw(&di, sizeof(DeclInfo)); + CPrep_TokenStreamGetState(&state); + CParser_InsertTryBlock(&tryblock); + + if (setjmp(tryblock.jmpbuf) == 0) { + if (copts.cplusplus) + di.x55 = 1; + + if (flag) { + di.x56 = 1; + *flag = 0; + } + + CParser_GetDeclSpecs(&di, 0); + if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_100)) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + *flag = 1; + return di.thetype; + } + + if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT && + TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + *flag = 1; + return di.thetype; + } + + scandeclarator(&di); + if (!di.name) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + return di.thetype; + } + } + + CPrep_TokenStreamSetCurState(&state); + CParser_RemoveTryBlock(&tryblock); + return 0; +} + +Boolean CParser_TryFuncDecl(void) { + Boolean result; + SInt32 state; + DeclInfo di; + struct ParserTryBlock tryblock; + + result = 0; + CPrep_TokenStreamGetState(&state); + CParser_InsertTryBlock(&tryblock); + + if (setjmp(tryblock.jmpbuf) == 0) { + memclrw(&di, sizeof(DeclInfo)); + di.thetype = &stvoid; + scandeclarator(&di); + + if (IS_TYPE_FUNC(di.thetype)) + result = 1; + } + + CParser_RemoveTryBlock(&tryblock); + CPrep_TokenStreamSetCurState(&state); + return result; +} + +Boolean CParser_TryParamList(Boolean flag) { + Boolean result; + SInt32 state; + struct ParserTryBlock tryblock; + + result = 0; + CPrep_TokenStreamGetState(&state); + + switch ((tk = lex())) { + case ')': + case TK_ELLIPSIS: + result = 1; + break; + default: + CParser_InsertTryBlock(&tryblock); + if (setjmp(tryblock.jmpbuf) == 0) { + if (CFunc_ParseFakeArgList(flag) || tk == ')') + result = 1; + } + CParser_RemoveTryBlock(&tryblock); + break; + } + + CPrep_TokenStreamSetCurState(&state); + return result; +} + +Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) { + switch (type->type) { + case TYPEARRAY: + TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual); + return type; + case TYPEPOINTER: + if (TYPE_POINTER(type)->qual & Q_CONST) { + TypePointer *newtype = galloc(sizeof(TypePointer)); + *newtype = *TYPE_POINTER(type); + newtype->qual = 0; + return TYPE(newtype); + } + return type; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) { + TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer)); + *newtype = *TYPE_MEMBER_POINTER(type); + newtype->qual = 0; + return TYPE(newtype); + } + return type; + default: + *qual = 0; + return type; + } +} + +UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return qual; +} + +UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return qual & (Q_CONST | Q_VOLATILE); +} + +Boolean CParser_IsConst(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return qual & Q_CONST; +} + +Boolean CParser_IsVolatile(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return (qual & Q_VOLATILE) ? 1 : 0; +} + +Boolean is_const_object(Object *obj) { + return CParser_IsConst(obj->type, obj->qual); +} + +Boolean is_volatile_object(Object *obj) { + return CParser_IsVolatile(obj->type, obj->qual); +} + +Boolean CParserIsConstExpr(ENode *expr) { + return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS); +} + +Boolean CParserIsVolatileExpr(ENode *expr) { + return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS); +} + +Boolean CParser_HasInternalLinkage(Object *obj) { + NameSpace *nspace; + + for (nspace = obj->nspace; nspace; nspace = nspace->parent) { + if (nspace->is_unnamed) + return 1; + } + + if (obj->datatype == DLOCAL) + return 1; + if (obj->qual & (Q_20000 | Q_OVERLOAD)) + return 0; + if (obj->sclass == OBJECT_SCLASS_102) + return 1; + + if (obj->qual & Q_INLINE) + obj->qual |= Q_20000; + return 0; +} + +Boolean CParser_HasInternalLinkage2(Object *obj) { + if (obj->datatype == DLOCAL) + return 1; + if (obj->qual & (Q_20000 | Q_OVERLOAD)) + return 0; + if (obj->sclass == OBJECT_SCLASS_102) + return 1; + + if (obj->qual & Q_INLINE) + obj->qual |= Q_20000; + return 0; +} + +Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) { + if (obj->datatype == DVFUNC) { + *tclass = TYPE_METHOD(obj->type)->theclass; + *index = TYPE_METHOD(obj->type)->x1E; + return 1; + } + + return 0; +} + +Boolean is_pascal_object(Object *obj) { + return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_PASCAL); +} + +Boolean is_cfm_type(Type *type) { + return 0; +} + +Boolean CParser_IsVTableObject(Object *obj) { + return + obj->datatype == DDATA && + obj->nspace && + obj->nspace->theclass && + obj->nspace->theclass->vtable && + obj->nspace->theclass->vtable->object == obj; +} + +static Type *getthetype(short token, short size, short signedness) { + switch (token) { + case 0: + case TK_INT: + if (signedness == 1) { + switch (size) { + case 1: return TYPE(&stunsignedshort); + case 2: return TYPE(&stunsignedlong); + case 3: return TYPE(&stunsignedlonglong); + default: return TYPE(&stunsignedint); + } + } else { + switch (size) { + case 1: return TYPE(&stsignedshort); + case 2: return TYPE(&stsignedlong); + case 3: return TYPE(&stsignedlonglong); + default: return TYPE(&stsignedint); + } + } + case TK_BOOL: + return TYPE(&stbool); + case TK_WCHAR_T: + return TYPE(&stwchar); + case TK_CHAR: + switch (signedness) { + case 1: return TYPE(&stunsignedchar); + default: return TYPE(&stchar); + case -1: return TYPE(&stsignedchar); + } + case TK_DOUBLE: + switch (size) { + case 1: return TYPE(&stshortdouble); + case 2: return TYPE(&stlongdouble); + default: return TYPE(&stdouble); + } + case TK_FLOAT: + return TYPE(&stfloat); + case TK_VOID: + return TYPE(&stvoid); + default: + CError_Error(121); + return TYPE(&stvoid); + } +} + +void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual) { + if (type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(type))) { + declinfo->thetype = type; + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual; + return; + } + + declinfo->thetype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); + TYPE_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + } else if (type->type == TYPEMEMBERPOINTER) { + declinfo->thetype = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(declinfo->thetype) = *TYPE_MEMBER_POINTER(type); + TYPE_MEMBER_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + } else { + declinfo->thetype = type; + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size) { + declinfo->thetype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); + } + } + declinfo->x49 = 1; +} + +static void CParser_ParseAttributeFunctionSummary(DeclInfo *declinfo) { + Boolean flag; + + if ((tk = lex()) != '(') { + CError_Error(114); + return; + } + + flag = 1; + tk = lookahead(); + while (tk == TK_IDENTIFIER) { + if (flag && !strcmp(tkidentifier->name, "entry_points_to")) { + PointerAnalysis_ParseEntryPointsToSpecifier(declinfo); + } else if (!strcmp(tkidentifier->name, "exit_points_to")) { + PointerAnalysis_ParseExitPointsToSpecifier(declinfo); + flag = 0; + } else if (!strcmp(tkidentifier->name, "function_modifies")) { + PointerAnalysis_ParseFunctionModifiesSpecifier(declinfo); + flag = 0; + } else { + lex(); + CError_Error(121); + return; + } + + tk = lookahead(); + if (tk == ',') { + lex(); + tk = lookahead(); + } + } + + lex(); + if (tk != ')') + CError_Error(121); +} + +void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) { + CInt64 val64; + SInt32 val; + + do { + if ((tk = lex()) != '(') { + CError_Error(121); + return; + } + if ((tk = lex()) != '(') { + CError_Error(121); + return; + } + if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) { + CError_Error(121); + return; + } + + if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) { + if ((tk = lex()) != '(') { + CError_Error(121); + return; + } + + tk = lex(); + val64 = CExpr_IntegralConstExpr(); + switch ((val = CInt64_GetULong(&val64))) { + case 1: + case 2: + case 4: + case 8: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + case 0x100: + case 0x200: + case 0x400: + case 0x800: + case 0x1000: + case 0x2000: + break; + default: + CError_Error(124); + return; + } + if (type) { + if (IS_TYPE_STRUCT(type)) { + if (val > TYPE_STRUCT(type)->align) { + TYPE_STRUCT(type)->align = val; + type->size += CABI_StructSizeAlignValue(type, type->size); + } + } else if (IS_TYPE_CLASS(type)) { + if (val > TYPE_CLASS(type)->align) { + TYPE_CLASS(type)->align = val; + type->size += CABI_StructSizeAlignValue(type, type->size); + } + } else { + CError_Error(149); + } + } else if (declinfo) { + declinfo->qual &= ~Q_ALIGNED_MASK; + switch (val) { + case 1: + declinfo->qual |= Q_ALIGNED_1; + break; + case 2: + declinfo->qual |= Q_ALIGNED_2; + break; + case 4: + declinfo->qual |= Q_ALIGNED_4; + break; + case 8: + declinfo->qual |= Q_ALIGNED_8; + break; + case 16: + declinfo->qual |= Q_ALIGNED_16; + break; + case 32: + declinfo->qual |= Q_ALIGNED_32; + break; + case 64: + declinfo->qual |= Q_ALIGNED_64; + break; + case 128: + declinfo->qual |= Q_ALIGNED_128; + break; + case 256: + declinfo->qual |= Q_ALIGNED_256; + break; + case 512: + declinfo->qual |= Q_ALIGNED_512; + break; + case 1024: + declinfo->qual |= Q_ALIGNED_1024; + break; + case 2048: + declinfo->qual |= Q_ALIGNED_2048; + break; + case 4096: + declinfo->qual |= Q_ALIGNED_4096; + break; + case 8192: + declinfo->qual |= Q_ALIGNED_8192; + break; + default: +#line 2779 + CError_FATAL(); + break; + } + } else { + CError_Error(359); + } + + if (tk != ')') { + CError_Error(121); + return; + } + } else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) { + if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype)) + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_NOTHROW; + else + CError_Error(359); + } else if (!strcmp("function_summary", tkidentifier->name)) { + CParser_ParseAttributeFunctionSummary(declinfo); + } else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) { + CError_Error(359); + } else if (!strcmp(tkidentifier->name, "unused") || !strcmp(tkidentifier->name, "__unused__")) { + } else if (!strcmp(tkidentifier->name, "noreturn") || !strcmp(tkidentifier->name, "__noreturn__")) { + } else if (tk == TK_CONST || !strcmp(tkidentifier->name, "__const__")) { + } else if (!strcmp(tkidentifier->name, "format") || !strcmp(tkidentifier->name, "__format__")) { + CError_Warning(359); + if ((tk = lex()) != '(') { + CError_Warning(114); + return; + } + tk = lex(); + if ((tk = lex()) != ',') { + CError_Warning(116); + return; + } + tk = lex(); + if ((tk = lex()) != ',') { + CError_Warning(116); + return; + } + tk = lex(); + if ((tk = lex()) != ')') { + CError_Warning(115); + return; + } + } else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) { + CError_Warning(359); + if ((tk = lex()) != '(') { + CError_Warning(114); + return; + } + tk = lex(); + if ((tk = lex()) != ')') { + CError_Warning(115); + return; + } + } else { + CError_Error(359); + } + + if ((tk = lex()) != ')') { + CError_Error(121); + return; + } + if ((tk = lex()) != ')') { + CError_Error(121); + return; + } + tk = lex(); + } while (tk == TK_UU_ATTRIBUTE_UU); +} + +static void CParser_ParseTypeOf(DeclInfo *declinfo) { + DeclInfo subdi; + ENode *expr; + + if ((tk = lex()) == '(' && islookaheaddeclaration()) { + tk = lex(); + + memclrw(&subdi, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&subdi, 0); + scandeclarator(&subdi); + if (subdi.name) + CError_Error(121); + + if (tk != ')') + CError_ErrorSkip(115); + else + tk = lex(); + + TypedefDeclInfo(declinfo, subdi.thetype, subdi.qual); + } else { + expr = unary_expression(); + if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) + CError_Error(144); + TypedefDeclInfo(declinfo, expr->rtype, expr->flags & ENODE_FLAG_QUALS); + } +} + +void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag) { + if ((tk = lex()) != TK_IDENTIFIER) { + if (tk != TK_EXPORT) + CError_Error(107); + else + declinfo->exportflags |= EXPORT_FLAGS_EXPORT; + } else if (!strcmp("internal", tkidentifier->name)) { + declinfo->exportflags |= EXPORT_FLAGS_INTERNAL; + } else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) { + declinfo->exportflags |= EXPORT_FLAGS_IMPORT; + } else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) { + declinfo->exportflags |= EXPORT_FLAGS_EXPORT; + } else if (!strcmp("lib_export", tkidentifier->name)) { + declinfo->exportflags |= EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT; + } else if (!strcmp("weak", tkidentifier->name)) { + declinfo->qual |= Q_OVERLOAD; + } else { + CodeGen_ParseDeclSpec(tkidentifier, declinfo); + } +} + +static int CParser_GetVectorDeclSpec(Type **type) { + tk = lex(); + switch (tk) { + case TK_CHAR: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedchar); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedchar); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_SIGNED: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorsignedchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorsignedlong); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_UNSIGNED: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorunsignedchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorunsignedlong); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_BOOL: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_SHORT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_LONG: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + case TK_SIGNED: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorsignedlong); + return 1; + } + case TK_UNSIGNED: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorunsignedlong); + return 1; + } + case TK_SHORT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + } + default: + CError_Error(121); + } + break; + case TK_LONG: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + } + } + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + tk = lex(); + switch (tk) { + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboolshort); + return 1; + } + } + default: + CError_Error(121); + } + break; + case TK_FLOAT: + *type = TYPE(&stvectorfloat); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("pixel") || tkidentifier == GetHashNameNode("__pixel")) { + *type = TYPE(&stvectorpixel); + tk = lex(); + return 1; + } + if (tkidentifier == GetHashNameNode("bool")) { + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + } + } + default: + CError_Error(121); + } + + return 0; +} + +Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag) { + NameSpace *nspace; + + if (tmclass->templ__params) { + nspace = cscope_current; + while (1) { + if (!nspace) { + if (flag) + CError_Error(230); + return 0; + } + if (nspace->theclass == TYPE_CLASS(tmclass)) + break; + nspace = nspace->parent; + } + } + + return 1; +} + +static Boolean CParser_IsAltiVecPrefix(void) { + HashNameNode *save = tkidentifier; + + switch (lookahead()) { + case TK_CHAR: + case TK_SHORT: + case TK_INT: + case TK_LONG: + case TK_FLOAT: + case TK_SIGNED: + case TK_UNSIGNED: + case TK_BOOL: + return 1; + case TK_IDENTIFIER: + if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel")) + return 1; + } + + tkidentifier = save; + return 0; +} + +void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) { + short typesize; + short signedness; + short typetoken; + Boolean r24; + Boolean r23; + SInt32 state; + CScopeParseResult pr; + + di->fileoffsetinfo.file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition( + (CPrepFileInfo **) &di->fileoffsetinfo.tokenline, + &di->fileoffsetinfo.tokenoffset); + + r24 = 1; + r23 = copts.cplusplus; + typetoken = 0; + signedness = 0; + typesize = 0; + +restart: + switch (tk) { + case TK_AUTO: + case TK_REGISTER: + case TK_STATIC: + case TK_EXTERN: + case TK_TYPEDEF: + case TK_MUTABLE: + if (di->storageclass) + CError_Error(121); + di->storageclass = tk; + break; + case TK_CONST: + if (di->thetype) { + if (di->thetype->type == TYPEPOINTER) { + if (TYPE_POINTER(di->thetype)->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + TYPE_POINTER(di->thetype)->qual |= Q_CONST; + break; + } else if (di->thetype->type == TYPEMEMBERPOINTER) { + if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_CONST; + break; + } + } + if (di->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + di->qual |= Q_CONST; + break; + case TK_VOLATILE: + if (di->thetype) { + if (di->thetype->type == TYPEPOINTER) { + if (TYPE_POINTER(di->thetype)->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + TYPE_POINTER(di->thetype)->qual |= Q_VOLATILE; + break; + } else if (di->thetype->type == TYPEMEMBERPOINTER) { + if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_VOLATILE; + break; + } + } + if (di->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + di->qual |= Q_VOLATILE; + break; + case TK_PASCAL: + if (di->qual & Q_PASCAL) + CError_QualifierCheck(Q_PASCAL); + di->qual |= Q_PASCAL; + break; + case TK_EXPLICIT: + CError_QualifierCheck(di->qual & Q_EXPLICIT); + di->qual |= Q_EXPLICIT; + break; + case TK_VIRTUAL: + CError_QualifierCheck(di->qual & Q_VIRTUAL); + di->qual |= Q_VIRTUAL; + break; + case TK_IN: + CError_QualifierCheck(di->qual & Q_IN); + di->qual |= Q_IN; + break; + case TK_OUT: + CError_QualifierCheck(di->qual & Q_OUT); + di->qual |= Q_OUT; + break; + case TK_INOUT: + CError_QualifierCheck(di->qual & Q_INOUT); + di->qual |= Q_INOUT; + break; + case TK_BYCOPY: + CError_QualifierCheck(di->qual & Q_BYCOPY); + di->qual |= Q_BYCOPY; + break; + case TK_BYREF: + CError_QualifierCheck(di->qual & Q_BYREF); + di->qual |= Q_BYREF; + break; + case TK_ONEWAY: + CError_QualifierCheck(di->qual & Q_ONEWAY); + di->qual |= Q_ONEWAY; + break; + case TK_UU_DECLSPEC: + if ((tk = lex()) != '(') + CError_Error(114); + CParser_ParseDeclSpec(di, 0); + if ((tk = lex()) != ')') + CError_Error(115); + break; + case TK_ASM: + if (di->qual & Q_ASM) + CError_QualifierCheck(Q_ASM); + di->qual |= Q_ASM; + break; + case TK_INLINE: + if (di->qual & Q_INLINE) + CError_QualifierCheck(Q_INLINE); + di->qual |= Q_INLINE; + break; + case TK_SHORT: + if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) + CError_Error(121); + typesize = 1; + break; + case TK_LONG: + if (copts.longlong) { + if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE) + CError_Error(121); + if (typesize) { + if (typesize != 2 || typetoken == TK_DOUBLE) + CError_Error(121); + typesize = 3; + } else { + typesize = 2; + } + } else { + if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) + CError_Error(121); + typesize = 2; + } + break; + case TK_SIGNED: + if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) + CError_Error(121); + signedness = -1; + break; + case TK_UNSIGNED: + if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) + CError_Error(121); + signedness = 1; + break; + case TK_VOID: + if (typetoken || typesize || signedness) + CError_Error(121); + typetoken = TK_VOID; + break; + case TK_FLOAT: + if (typetoken || typesize || signedness) + CError_Error(121); + typetoken = TK_FLOAT; + break; + case TK_BOOL: + if (typetoken || typesize) + CError_Error(121); + typetoken = TK_BOOL; + break; + case TK_CHAR: + if (typetoken || typesize) + CError_Error(121); + typetoken = TK_CHAR; + break; + case TK_WCHAR_T: + if (typetoken || typesize || signedness) + CError_Error(121); + typetoken = TK_WCHAR_T; + break; + case TK_INT: + if (typetoken) + CError_Error(121); + typetoken = TK_INT; + break; + case TK_DOUBLE: + if (typetoken || signedness) + CError_Error(121); + typetoken = TK_DOUBLE; + break; + case TK_STRUCT: + if (typetoken || signedness || typesize) + CError_Error(121); + tk = lex(); + scanstruct(di, STRUCT_TYPE_STRUCT); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_CLASS: + if (typetoken || signedness || typesize) + CError_Error(121); + tk = lex(); + CDecl_ParseClass(di, CLASS_MODE_2, 1, 0); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_UNION: + if (typetoken || signedness || typesize) + CError_Error(121); + tk = lex(); + scanstruct(di, STRUCT_TYPE_UNION); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_ENUM: + if (typetoken || signedness || typesize) + CError_Error(121); + tk = lex(); + scanenum(di); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_TYPENAME: + if (typetoken || signedness || typesize || di->x53) + CError_Error(121); + di->x53 = 1; + tk = lex(); + if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) { + CError_Error(121); + break; + } + goto some_shared_label; + case TK_COLON_COLON: + if (typetoken || signedness || typesize) + goto switchDefault; + goto some_shared_label; + case TK_UU_VECTOR: + if (typetoken || signedness || typesize) + CError_Error(121); + handle_vector: + if (CParser_GetVectorDeclSpec(&di->thetype)) { + if (tk == TK_CONST) { + if (di->qual == 0) { + di->qual |= Q_CONST; + tk = lex(); + } else { + CError_Error(121); + } + } + if (tk == TK_VOLATILE) { + if (di->qual == 0) { + di->qual |= Q_VOLATILE; + tk = lex(); + } else { + CError_Error(121); + } + } + return; + } + break; + case TK_UU_TYPEOF_UU: + if (typetoken || signedness || typesize) + CError_Error(121); + CParser_ParseTypeOf(di); + typetoken = -1; + goto bailOut; + case TK_IDENTIFIER: + if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) { + if (CParser_IsAltiVecPrefix()) + goto handle_vector; + } + if (!typetoken && !signedness && !typesize) { + if (copts.objective_c && !strcmp(tkidentifier->name, "id")) { + di->thetype = CObjC_ParseID(); + typetoken = -1; + goto bailOut; + } + some_shared_label: + CPrep_TokenStreamGetState(&state); + if (CScope_ParseDeclName(&pr)) { + if (pr.x8) { + if (IS_TYPE_TEMPLATE(pr.x8)) { + switch (TYPE_TEMPLATE(pr.x8)->dtype) { + case TEMPLDEP_ARGUMENT: + switch (TYPE_TEMPLATE(pr.x8)->u.pid.type) { + case TPT_TYPE: + break; + case TPT_NONTYPE: + CError_Error(348); + pr.x8 = TYPE(&stsignedint); + break; + case TPT_TEMPLATE: + CError_Error(230); + pr.x8 = TYPE(&stsignedint); + break; + default: +#line 4109 + CError_FATAL(); + } + break; + case TEMPLDEP_QUALNAME: + if (!di->x53 && !pr.x20 && di->x55) + CError_Error(355); + break; + case TEMPLDEP_TEMPLATE: + case TEMPLDEP_ARRAY: + case TEMPLDEP_QUALTEMPL: + case TEMPLDEP_BITFIELD: + break; + default: +#line 4136 + CError_FATAL(); + } + } + + if (IS_TYPE_CLASS(pr.x8) && (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) { + if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 0)) { + if (di->x56) { + if (di->qual) + CError_Error(121); + di->thetype = pr.x8; + di->x57 = 1; + tk = lex(); + return; + } else { + CError_Error(230); + pr.x8 = TYPE(&stsignedint); + } + } + } + + TypedefDeclInfo(di, pr.x8, pr.xC); + di->x49 = pr.x20; + typetoken = -1; + tk = lex(); + if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo) + di->thetype = CObjC_ParseTypeProtocol(di->thetype); + goto bailOut; + } else if (pr.nsol_14) { + if (pr.x1D) { + if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->x4C)) { + di->x14 = pr.nsol_14; + if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000)) + r23 = 0; + } else { + CError_Error(121); + } + } + } else if (pr.obj_10) { + switch (pr.obj_10->otype) { + case OT_OBJECT: + if (pr.x1D) { + if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->x4C)) { + di->x10 = OBJECT(pr.obj_10); + if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000)) + r23 = 0; + } else { + CError_Error(121); + } + } + break; + case OT_ENUMCONST: + case OT_MEMBERVAR: + CError_Error(121); + break; + default: +#line 4217 + CError_FATAL(); + } + } else if (pr.name_4) { + if (copts.cplusplus) + CError_Error(121); + } else if (pr.x21) { + CPrep_TokenStreamSetState(&state); + CPrep_UnLex(); + tk = lex(); + r23 = 0; + } else { +#line 4234 + CError_FATAL(); + } + } + } + default: + switchDefault: + if (!typetoken && !signedness && !typesize) { + di->x4A = 1; + if (r23) { + if (!di->storageclass && !di->qual && !di->exportflags) + CError_Error(121); + else + CError_Warning(349); + } + } + if (typetoken >= 0) + di->thetype = getthetype(typetoken, typesize, signedness); + if (r24) + di->x48 = 1; + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, di); + return; + case ';': + if (!typetoken && !signedness && !typesize && copts.warn_emptydecl) + CError_Warning(216); + if (typetoken >= 0) + di->thetype = getthetype(typetoken, typesize, signedness); + return; + } + + tk = lex(); +bailOut: + r24 = 0; + goto restart; +} + +void CParser_RegisterNonGlobalClass(TypeClass *tclass) { + struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup)); + p->next = cparser_parentcleanup; + p->tclass = tclass; + cparser_parentcleanup = p; +} + +void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) { + struct SFuncList *p = lalloc(sizeof(struct SFuncList)); + p->next = cparser_sfunclist; + p->func = func; + p->obj = NULL; + p->expr = expr; + cparser_sfunclist = p; +} + +void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) { + struct SFuncList *p = lalloc(sizeof(struct SFuncList)); + p->next = cparser_sfunclist; + p->func = func; + p->obj = obj; + p->expr = NULL; + cparser_sfunclist = p; +} + +static void CParser_FreeLocalHeap(void) { + struct SFuncList *s; + struct ParentCleanup *p; + + while ((s = cparser_sfunclist)) { + cparser_sfunclist = s->next; + if (s->expr) + CFunc_GenerateSingleExprFunc(s->func, s->expr); + else + CFunc_GenerateDummyCtorFunc(s->func, s->obj); + } + + if (cparser_parentcleanup) { + if (!CInline_CanFreeLHeap()) + return; + + for (p = cparser_parentcleanup; p; p = p->next) { + while (!p->tclass->nspace->parent->is_global) + p->tclass->nspace->parent = p->tclass->nspace->parent->parent; + } + + cparser_parentcleanup = NULL; + } + + freelheap(); +} + +static void CParser_GlobalCleanup(Boolean flag) { + Boolean working; + + do { + CParser_FreeLocalHeap(); + working = 0; + + if (flag) { + if (cparser_classactions) { + CClass_ClassAction(cparser_classactions->tclass); + cparser_classactions = cparser_classactions->next; + working = 1; + } else if (CTempl_Instantiate()) { + working = 1; + } + } + + while (CInline_GenerateDeferredFuncs()) { + CParser_FreeLocalHeap(); + working = 1; + } + } while (working); +} + +Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) { + return IS_TYPE_CLASS(di->thetype) && + ((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_1 || (flag && copts.cpp_extensions))) && + IsTempName(TYPE_CLASS(di->thetype)->classname); +} + +void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) { + ObjMemberVar *ivar; + Object *obj; + Object *ivar_obj; + + if (!CParser_IsAnonymousUnion(di, 0)) { + if (copts.warn_emptydecl) { + switch (di->thetype->type) { + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + if (!di->storageclass && !di->qual) + return; + } + CError_Warning(216); + } + return; + } + + if (!flag && di->storageclass != TK_STATIC) + CError_Error(177); + + if (flag && di->storageclass != TK_STATIC) { + obj = CParser_NewLocalDataObject(di, 1); + obj->name = CParser_GetUniqueName(); + CFunc_SetupLocalVarInfo(obj); + obj->u.var.info->noregister = 1; + } else { + obj = CParser_NewGlobalDataObject(di); + obj->name = CParser_GetUniqueName(); + obj->nspace = cscope_root; + obj->sclass = TK_STATIC; + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + + for (ivar = TYPE_CLASS(di->thetype)->ivars; ivar; ivar = ivar->next) { + ivar_obj = galloc(sizeof(Object)); + *ivar_obj = *obj; + ivar_obj->name = ivar->name; + ivar_obj->type = ivar->type; + ivar_obj->qual = ivar->qual; + ivar_obj->datatype = DALIAS; + ivar_obj->u.alias.object = obj; + ivar_obj->u.alias.offset = ivar->offset; + ivar_obj->u.alias.member = NULL; + CScope_AddObject(cscope_current, ivar_obj->name, OBJ_BASE(ivar_obj)); + } +} + +void CParser_NewCallBackAction(Object *obj, TypeClass *tclass) { + CallbackAction *act = galloc(sizeof(CallbackAction)); + act->next = callbackactions; + act->obj = obj; + act->tclass = tclass; + callbackactions = act; + obj->flags |= OBJECT_FLAGS_8; +} + +void CParser_NewClassAction(TypeClass *tclass) { + struct ClassAction *act = galloc(sizeof(struct ClassAction)); + act->next = cparser_classactions; + act->tclass = tclass; + cparser_classactions = act; +} + +void CParser_CallBackAction(Object *obj) { + CallbackAction *act; + + for (act = callbackactions; act; act = act->next) { + if (act->obj == obj) { + CParser_NewClassAction(act->tclass); + return; + } + } + +#line 4551 + CError_FATAL(); +} + +static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) { + while (list) { + if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type)) + if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1) + return OBJECT(list->object); + list = list->next; + } + + return NULL; +} + +Object *CParser_ParseObject(void) { + DeclInfo di; + CScopeParseResult pr; + NameSpaceObjectList *list; + Object *obj; + + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 1); + scandeclarator(&di); + + if (di.name && (list = CScope_FindObjectList(&pr, di.name))) { + if (list->object->otype == OT_OBJECT) { + if (IS_TYPE_FUNC(di.thetype)) + return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype)); + + if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual) + return OBJECT(list->object); + + obj = OBJECT(list->object); + CError_Error(249, CError_GetObjectName(obj), obj->type, obj->qual, di.thetype, di.qual); + } + } + + return NULL; +} + +void CParser_ParseGlobalDeclaration(void) { + DeclInfo di; + + if (tk) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 1); + if (di.storageclass == TK_REGISTER || di.storageclass == TK_AUTO) { + CError_Error(177); + di.storageclass = 0; + } + + if (tk != ';') + scandeclaratorlist(&di); + else + CParser_CheckAnonymousUnion(&di, 0); + + tk = lex(); + } else { + CError_Error(102); + } +} + +static void CParser_ParseLinkageSpecification(DeclInfo *di) { + UInt32 r29; + UInt8 r28; + + if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) { + r29 = 0; + r28 = 1; + } else if (!strcmp(tkstring, "C++")) { + r29 = 0; + r28 = 0; + } else if (!strcmp(tkstring, "Pascal")) { + r29 = 8; + r28 = 1; + } else { + CError_Error(121); + r29 = 0; + r28 = 1; + } + + if ((tk = lex()) == '{') { + while (1) { + if ((tk = lex()) == 0) { + CError_Error(130); + return; + } + + if (tk == '}') + break; + + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(di, sizeof(DeclInfo)); + di->x4E = r28; + di->qual = r29; + CParser_ParseDeclaration(di); + } + } else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) { + tk = lex(); + CParser_ParseLinkageSpecification(di); + } else { + memclrw(di, sizeof(DeclInfo)); + di->x4E = r28; + di->qual = r29; + CParser_GetDeclSpecs(di, 1); + + if (di->storageclass != TK_TYPEDEF) { + if (di->storageclass && copts.pedantic) + CError_Warning(177); + if (!di->storageclass) + di->storageclass = TK_EXTERN; + } + if (copts.cpp_extensions) + di->x48 = 0; + if (tk != ';') + scandeclaratorlist(di); + } +} + +static void CParser_ParseNameSpace(DeclInfo *di) { + NameSpace *nspace; + ObjNameSpace *objns; + HashNameNode *name; + Boolean flag; + CScopeSave save; + NameSpaceObjectList *list; + NameSpaceList *nsl; + + if ((tk = lex()) == TK_IDENTIFIER) { + name = tkidentifier; + flag = 0; + if ((tk = lex()) == '=') { + CScope_ParseNameSpaceAlias(name); + return; + } + } else { + if (tk != '{') { + CError_Error(107); + return; + } + name = CParser_GetUnnamedNameSpaceName(); + flag = 1; + } + + nspace = cscope_current; + if (!(list = CScope_FindName(nspace, name))) { + objns = galloc(sizeof(ObjNameSpace)); + memclrw(objns, sizeof(ObjNameSpace)); + objns->otype = OT_NAMESPACE; + objns->access = ACCESSPUBLIC; + if (flag) { + nspace = CScope_NewListNameSpace(name, 1); + nspace->is_unnamed = 1; + nsl = galloc(sizeof(NameSpaceList)); + nsl->next = cscope_current->usings; + nsl->nspace = nspace; + cscope_current->usings = nsl; + } else { + nspace = CScope_NewHashNameSpace(name); + if (cscope_current->is_unnamed) + nspace->is_unnamed = 1; + } + + nspace->parent = cscope_current; + objns->nspace = nspace; + CScope_AddObject(cscope_current, name, OBJ_BASE(objns)); + } else { + if (list->object->otype != OT_NAMESPACE) + CError_Error(320); + else + nspace = OBJ_NAMESPACE(list->object)->nspace; + } + + if (tk != '{') { + CError_Error(135); + return; + } + + CScope_SetNameSpaceScope(nspace, &save); + while (1) { + if ((tk = lex()) == 0) { + CError_Error(130); + break; + } + + if (tk == '}') + break; + + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(di, sizeof(DeclInfo)); + CParser_ParseDeclaration(di); + } + CScope_RestoreScope(&save); +} + +static void CParser_ParseDeclaration(DeclInfo *di) { + switch (tk) { + case TK_AT_INTERFACE: + CObjC_ParseInterface(); + break; + case TK_AT_IMPLEMENTATION: + CObjC_ParseImplementation(); + break; + case TK_AT_PROTOCOL: + CObjC_ParseProtocol(); + break; + case TK_AT_CLASS: + CObjC_ParseClassDeclaration(); + break; + case TK_NAMESPACE: + CParser_ParseNameSpace(di); + break; + case TK_EXPORT: + CError_Error(190); + if ((tk = lex()) != TK_TEMPLATE) { + CError_Error(121); + return; + } + case TK_TEMPLATE: + CTempl_Parse(NULL, 0); + break; + case TK_USING: + if ((tk = lex()) == TK_NAMESPACE) { + tk = lex(); + CScope_ParseUsingDirective(cscope_current); + } else { + CScope_ParseUsingDeclaration(cscope_current, 0, 0); + } + break; + case TK_EXTERN: + if (copts.cplusplus) { + di->storageclass = TK_EXTERN; + if ((tk = lex()) == TK_STRING) { + CParser_ParseLinkageSpecification(di); + break; + } + } + default: + CParser_GetDeclSpecs(di, 1); + if ((di->storageclass == TK_REGISTER || di->storageclass == TK_AUTO) != 0) { + CError_Error(177); + di->storageclass = 0; + } + if (tk != ';') + scandeclaratorlist(di); + else + CParser_CheckAnonymousUnion(di, 0); + CParser_GlobalCleanup(0); + } +} + +void cparser(void) { + DeclInfo di; + + if (copts.crippled && copts.optimizationlevel > 1) { + CError_Warning(385); + copts.optimizationlevel = 1; + CodeGen_UpdateOptimizerOptions(); + CodeGen_UpdateBackEndOptions(); + } + + if ((tk = lex())) { + do { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(&di, sizeof(DeclInfo)); + CParser_ParseDeclaration(&di); + } while (tk && (tk = lex())); + } else { + if (!copts.cplusplus && copts.ANSI_strict) + CError_Error(102); + } + + CInit_DefineTentativeData(); + copts.defer_codegen = 0; + CParser_GlobalCleanup(1); + + if (cparamblkptr->isPrecompiling != 1) { + CInline_Finish(); + CParser_GlobalCleanup(1); + } + + CClass_GenThunks(); + if (cparamblkptr->isPrecompiling != 1) + CObjC_GenerateModule(); + + CSOM_Cleanup(); + CInit_DefineTentativeData(); +} diff --git a/compiler_and_linker/unsorted/CodeGen.c b/compiler_and_linker/unsorted/CodeGen.c new file mode 100644 index 0000000..0867270 --- /dev/null +++ b/compiler_and_linker/unsorted/CodeGen.c @@ -0,0 +1,697 @@ +#include "compiler.h" +#include "compiler/CError.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/tokens.h" +#include "compiler/types.h" + +static Macro powcM; +static Macro __powcM; +static Macro ppc_cpu; +static Macro profM; +static Macro hostM; +static Macro bendM; +static Macro _ppc_M; +static Macro longI; +static Macro IEEED; +Macro vecM; +Macro altivecM; +static Macro macM2; +static Macro appleM; +static Macro optM; +static Macro alignM; +static Macro _machM; +static Macro archM; +static Macro dynM; +static Macro ppcM; +Object *gFunction; +static ObjectList *temps; +PCodeLabel *returnlabel; +PCodeLabel *cleanreturnlabel; +Boolean needs_cleanup; +Statement *current_statement; +int has_catch_blocks; +int disable_optimizer; +SInt32 current_linenumber; +Boolean has_altivec_arrays; +short high_reg; +short low_reg; +short high_offset; +short low_offset; +short low_reg2; +short high_reg2; +PCodeLabel *pic_base_pcodelabel; +Object *dyld_stub_binding_helper; +Object *rt_cvt_fp2unsigned; +Object *rt_profile_entry; +Object *rt_profile_exit; +Object *rt_div2i; +Object *rt_div2u; +Object *rt_mod2i; +Object *rt_mod2u; +Object *rt_shr2i; +Object *rt_shr2u; +Object *rt_shl2i; +Object *rt_cvt_ull_dbl; +Object *rt_cvt_sll_dbl; +Object *rt_cvt_ull_flt; +Object *rt_cvt_sll_flt; +Object *rt_cvt_dbl_usll; +static void *saveheaperror; + +enum { + GPRLimit = 10, + FPRLimit = 13, + VRLimit = 13 +}; + +VarInfo *CodeGen_GetNewVarInfo(void) { + VarInfo *vi; + + vi = lalloc(sizeof(VarInfo)); + memclrw(vi, sizeof(VarInfo)); + + vi->deftoken = *CPrep_CurStreamElement(); + vi->varnumber = localcount++; + + return vi; +} + +Object *maketemporary(Type *type) { + ObjectList *list; + Object *obj; + + for (list = temps; list; list = list->next) { + obj = list->object; + if (obj->u.var.uid == 0 && obj->type == type) { + obj->u.var.uid = 1; + return obj; + } + } + + obj = lalloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DLOCAL; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 1; + + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->next = temps; + list->object = obj; + temps = list; + + return obj; +} + +static void free_temporaries(void) { + ObjectList *list; + + for (list = temps; list; list = list->next) + list->object->u.var.uid = 0; +} + +static void allocate_temporaries(void) { + ObjectList *list; + + for (list = temps; list; list = list->next) + assign_local_memory(list->object); +} + +void process_arguments(ArgumentProcessor func, Boolean flag) { + short gpr = 3; + short fpr = 1; + short vr = 2; + Type *type; + ObjectList *list; + + for (list = arguments; list; list = list->next) { + type = list->object->type; + if (IS_TYPE_FLOAT(type)) { + func(list->object, (fpr <= FPRLimit) ? fpr : 0); + fpr++; + if (type->size == 4) + gpr++; + else + gpr += 2; + } else if (IS_TYPE_VECTOR(type)) { + func(list->object, (vr <= VRLimit) ? vr : 0); + vr++; + if (flag) { + if ((vr - 1) == 2) + gpr = 9; + else if ((vr - 1) > 2) + gpr = 11; + } + } else { + func(list->object, (gpr <= GPRLimit) ? gpr : 0); + if (TYPE_FITS_IN_REGISTER(type)) { + if (type->size <= 4) + gpr += 1; + else + gpr += 2; + } else { + gpr += (type->size >> 2); + if (type->size & 3) + gpr++; + } + } + } + + last_argument_register[RegClass_GPR] = gpr - 1; + last_argument_register[RegClass_FPR] = fpr - 1; + last_argument_register[RegClass_VR] = vr - 1; + if (flag) + move_varargs_to_memory(); +} + +static void retain_argument_register(Object *obj, short reg) { + VarInfo *vi = Registers_GetVarInfo(obj); + Type *type = obj->type; + + if (reg && !vi->noregister && vi->used) { + if (TYPE_FITS_IN_REGISTER(type)) { + if (type->size <= 4) { + retain_register(obj, RegClass_GPR, reg); + } else if (reg < GPRLimit) { + if (copts.little_endian) + retain_GPR_pair(obj, reg, reg + 1); + else + retain_GPR_pair(obj, reg + 1, reg); + } + } else if (IS_TYPE_FLOAT(type)) { + retain_register(obj, RegClass_FPR, reg); + } else if (IS_TYPE_VECTOR(type)) { + retain_register(obj, RegClass_VR, reg); + } + } +} + +static void allocate_local_vregs(void) { + VarInfo *vi; + ObjectList *list; + Object *obj; + + if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { + if (assignable_registers[RegClass_GPR]) { + vi = pic_base.u.var.info; + vi->reg = 0; + assign_register_by_type(&pic_base); + pic_base_reg = vi->reg; +#line 497 + CError_ASSERT(pic_base_reg); + } else { +#line 500 + CError_FATAL(); + } + } else { + pic_base_reg = 0; + } + + for (list = exceptionlist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + + set_last_exception_registers(); + + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + + for (list = locals; list; list = list->next) { + obj = list->object; + if (!IsTempName(obj->name)) { + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + } + + open_fe_temp_registers(); + + for (list = locals; list; list = list->next) { + obj = list->object; + if (IsTempName(obj->name)) { + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + } + + for (list = toclist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (!vi->reg && vi->used && vi->usage > 1) + assign_register_by_type(obj); + } +} + +static void allocate_local_GPRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + Type *type; + + if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { + vi = pic_base.u.var.info; + vi->reg = 0; + assign_register_by_type(&pic_base); + pic_base_reg = vi->reg; +#line 605 + CError_ASSERT(pic_base_reg); + } else { + pic_base_reg = 0; + } + + while (assignable_registers[RegClass_GPR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + type = obj->type; + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + type = obj->type; + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + for (list = toclist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used) { + if (vi->usage >= winning_usage && vi->usage >= 3) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); +#line 698 + CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_local_FPRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + Type *type; + + while (assignable_registers[RegClass_FPR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + type = obj->type; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_FLOAT(type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_FLOAT(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); +#line 782 + CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_local_VRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + + while (assignable_registers[RegClass_VR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_VECTOR(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_VECTOR(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); +#line 846 + CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_locals(void) { + has_altivec_arrays = 0; + + if (!requires_frame && !optimizing) + process_arguments(retain_argument_register, 0); + + if (optimizing) { + allocate_local_vregs(); + } else { + allocate_local_GPRs(); + allocate_local_FPRs(); + allocate_local_VRs(); + } + + assign_locals_to_memory(locals); +} + +void move_assigned_argument(Object *obj, short reg) { + VarInfo *vi; + Type *type; + SInt32 bytesLeft; + SInt32 offset; + + vi = Registers_GetVarInfo(obj); + type = obj->type; +#line 901 + CError_ASSERT(obj->datatype == DLOCAL); + + if (!vi->used) + return; + + if (reg) { + if (vi->reg) { + if (TYPE_IS_8BYTES(type)) { + if (copts.little_endian) { + if (vi->reg != reg) + emitpcode(PC_MR, vi->reg, reg); + if (reg < GPRLimit) { +#line 916 + CError_FAIL((vi->regHi == reg) || (vi->reg == (reg + 1))); + if (vi->regHi != (reg + 1)) + emitpcode(PC_MR, vi->regHi, reg + 1); + } else { + load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); + } + } else { + if (vi->regHi != reg) + emitpcode(PC_MR, vi->regHi, reg); + if (reg < GPRLimit) { +#line 931 + CError_FAIL((vi->reg == reg) || (vi->regHi == (reg + 1))); + if (vi->reg != (reg + 1)) + emitpcode(PC_MR, vi->reg, reg + 1); + } else { + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); + } + } + } else if (vi->reg != reg) { + if (IS_TYPE_FLOAT(type)) { + emitpcode(PC_FMR, vi->reg, reg); + } else if (IS_TYPE_VECTOR(type)) { + emitpcode(PC_VMR, vi->reg, reg); + } else { + emitpcode(PC_MR, vi->reg, reg); + } + } + } else { + if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + load_store_register(PC_STB, reg, local_base_register(obj), obj, 0); + break; + case 2: + load_store_register(PC_STH, reg, local_base_register(obj), obj, 0); + break; + case 4: + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + break; + case 8: + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + if (reg < GPRLimit) + load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4); + break; + default: +#line 993 + CError_FATAL(); + } + } else if (IS_TYPE_FLOAT(type)) { + load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_VECTOR(type)) { + load_store_register(PC_STVX, reg, local_base_register(obj), obj, 0); + } else { + bytesLeft = (11 - reg) * 4; + if (bytesLeft > obj->type->size) + bytesLeft = obj->type->size; + offset = 0; + while (bytesLeft > 0) { + load_store_register(PC_STW, reg, local_base_register(obj), obj, offset); + reg++; + offset += 4; + bytesLeft -= 4; + } + } + } + } else { + if (vi->reg) { + if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_FLOAT(type)) { + load_store_register((type->size == 4) ? PC_LFS : PC_LFD, vi->reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_VECTOR(type)) { + load_store_register(PC_LVX, vi->reg, local_base_register(obj), obj, 0); + } else { + switch (type->size) { + case 1: + load_store_register(PC_LBZ, vi->reg, local_base_register(obj), obj, 0); + break; + case 2: + load_store_register(is_unsigned(type) ? PC_LHZ : PC_LHA, vi->reg, local_base_register(obj), obj, 0); + break; + case 4: + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); + break; + case 8: + load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); + break; + default: +#line 1095 + CError_FATAL(); + } + } + } else if (!optimizing) { + local_base_register(obj); + } + } +} + +static void load_TOC_pointers(void) { + VarInfo *vi; + Object *obj; + ObjectList *list; + PCode *pc; + + if (uses_globals && pic_base_reg) { + pic_base_pcodelabel = makepclabel(); + pc = makepcode(PC_BC, 20, 7, 3); + pcsetlinkbit(pc); + pcsetsideeffects(pc); + appendpcode(pclastblock, pc); + pcbranch(pclastblock, pic_base_pcodelabel); + makepcblock(); + pclabel(pclastblock, pic_base_pcodelabel); + emitpcode(PC_MFLR, pic_base_reg); + } + + // TODO: depends on Operands + for (list = toclist; list; list = list->next) { + + } +} + +static Boolean has_vararglist(Object *funcobj) { + FuncArg *arg; + + arg = TYPE_FUNC(funcobj->type)->args; + while (arg && arg != &elipsis) + arg = arg->next; + + return arg == &elipsis; +} + +void assign_labels() { + // TODO +} + +static Boolean islaststatement(Statement *stmt) { + for (stmt = stmt->next; stmt; stmt = stmt->next) { + if (stmt->type > ST_LABEL) + return 0; + } + return 1; +} + +static void newstatement(SInt32 sourceoffset, UInt16 value, int flag) { + PCodeBlock *block = pclastblock; + + pcloopweight = value; + if (!block->pcodeCount) + block->loopWeight = value; + + if (block->pcodeCount > 100) + branch_label(makepclabel()); + + if (flag) + block->flags |= fPCBlockFlag4000; +} + +static void expressionstatement(ENode *expr) { +} + +static void labelstatement() {} +static void gotostatement() {} +static void gotoexpression() {} +static void conditionalstatement() {} +static void returnstatement() {} +static void capturestackpointer() {} +static void resetstackpointer() {} +static void callprofiler() {} +static void exitprofiler() {} +void CodeGen_Generator() {} +void CodeGen_GenVDispatchThunk() {} +void CodeGen_SetupRuntimeObjects() {} +Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) {} +Boolean CodeGen_IsPublicRuntimeObject(Object *obj) {} +void CodeGen_SOMStub() {} +void CodeGen_ParseDeclSpec() {} +static void CodeGen_EOLCheck() {} +static void schedule_for() {} +static void pragma_scheduling() {} +static void CodeGen_ParseLongIntegerORonORoff() {} +void CodeGen_ParsePragma(HashNameNode *name) {} +void CodeGen_UpdateObject(Object *object) {} +void CodeGen_UpdateBackEndOptions() {} +void CodeGen_objc_method_self_offset() {} +void CodeGen_objc_method_sel_offset() {} +void CodeGen_objc_method_arg_offset() {} +void CodeGen_objc_method_args_size() {} +void CodeGen_HandleIntrinsicCall() {} +void CodeGen_HandleTypeCast() {} +void CodeGen_AssignCheck() {} +void CodeGen_CollapseVectorExpression() {} +void CodeGen_InsertSpecialMacros() {} +char *CodeGen_ExpandSpecialMacro(Macro *macro) {} +void CodeGen_reportheapinfo() {} +static void CodeGen_heaperror() {} +void CodeGen_InitialSanityCheck() {} diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c new file mode 100644 index 0000000..c0fee65 --- /dev/null +++ b/compiler_and_linker/unsorted/Operands.c @@ -0,0 +1,1044 @@ +#include "compiler/Operands.h" +#include "compiler/CError.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler.h" + +unsigned long long uns_to_float_cc = 0x4330000000000000; +unsigned long long int_to_float_cc = 0x4330000080000000; +Float one_point_zero = {1.0}; + +void load_immediate(short reg, SInt32 value) { + short tmpreg = reg; + short tmpreg2; + + if (!FITS_IN_SHORT(value)) { + if (copts.optimizationlevel > 1 && value) + tmpreg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value)); + if (value) + emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value)); + } else { + emitpcode(PC_LI, reg, value); + } +} + +static void set_op_flags(Operand *op, ENode *expr) { +#line 118 + CError_ASSERT(op); + + if (expr) { + if (expr->type == EINTCONST) { + op->flags = 0; + if (expr->flags & ENODE_FLAG_VOLATILE) + op->flags |= OpndFlags_Volatile; + if (expr->flags & ENODE_FLAG_CONST) + op->flags |= OpndFlags_Const; + } else { + op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0; + op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0; + } + } else { + op->flags = 0; + } +} + +void symbol_operand(Operand *op, Object *obj) { + memclrw(op, sizeof(Operand)); + op->optype = OpndType_Symbol; + op->object = obj; +} + +void indirect(Operand *op, ENode *expr) { + switch (op->optype) { + case OpndType_GPRPair: +#line 163 + CError_FATAL(); + case OpndType_CRField: + case OpndType_IndirectGPR_ImmOffset: + case OpndType_IndirectGPR_Indexed: + case OpndType_IndirectSymbol: + if (op->optype) + Coerce_to_register(op, (Type *) &void_ptr, 0); + case OpndType_GPR: + op->immOffset = 0; + op->object = NULL; + case OpndType_GPR_ImmOffset: + op->optype = OpndType_IndirectGPR_ImmOffset; + set_op_flags(op, expr); + break; + case OpndType_GPR_Indexed: + op->optype = OpndType_IndirectGPR_Indexed; + set_op_flags(op, expr); + break; + case OpndType_Absolute: + if (FITS_IN_SHORT(op->abs_address)) { + op->reg = 0; + op->immOffset = op->abs_address; + } else { + emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->abs_address)); + op->immOffset = LOW_PART(op->abs_address); + } + op->object = NULL; + op->optype = OpndType_IndirectGPR_ImmOffset; + set_op_flags(op, expr); + break; + case OpndType_Symbol: + op->optype = OpndType_IndirectSymbol; + set_op_flags(op, expr); + break; + default: +#line 215 + CError_FATAL(); + } +} + +#define COMBO_OP(a, b) (b + (a * 11)) + +void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) { + Operand *tmp_op; + int tmp; + + if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opA); + if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opB); + + switch (COMBO_OP(opA->optype, opB->optype)) { + case COMBO_OP(OpndType_GPR, OpndType_GPR): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = opB->reg; + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset): + if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) { + opB->immOffset += opA->immOffset; + if (!opB->object) + opB->object = opA->object; + } else { + tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(tmp, opA->reg, opA->object, opA->immOffset); + opA->reg = tmp; + } + case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR): + if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opB->reg; + add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); + } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opA->reg; + add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset)); + } else if (opA->object) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opB->reg; + add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); + } else { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->immOffset = opA->immOffset; + opOut->object = opA->object; + emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg); + } + break; + case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg); + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset): + if (opB->object) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); + add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset); + } else { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->immOffset = opB->immOffset; + opOut->object = opB->object; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); + emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg); + } + break; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset); + emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset); + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset): + if (!opB->object) { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->reg = opB->reg; + opOut->immOffset = opB->immOffset; + opOut->object = opB->object; + if (FITS_IN_SHORT(opOut->immOffset + opA->abs_address)) { + opOut->immOffset += opA->abs_address; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (!HIGH_PART(opA->abs_address)) { + emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->abs_address)); + } else { + emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->abs_address)); + if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->abs_address))) { + opOut->immOffset += LOW_PART(opA->abs_address); + } else { + emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->abs_address)); + } + } + } + break; + } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->abs_address)) { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->object = opB->object; + opOut->reg = opB->reg; + opOut->immOffset = LOW_PART(opB->immOffset + opA->abs_address); + break; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset); + opB->optype = OpndType_GPR; + opB->reg = opOut->reg; + tmp_op = opA; + opA = opB; + opB = tmp_op; + } + case COMBO_OP(OpndType_GPR, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR): + opOut->optype = (opA->abs_address != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR; + opOut->immOffset = LOW_PART(opA->abs_address); + opOut->object = NULL; + if (FITS_IN_SHORT(opA->abs_address)) { + opOut->reg = opB->reg; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->abs_address)); + } + break; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opB->reg; + opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (!HIGH_PART(opA->abs_address)) { + emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->abs_address)); + } else { + emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->abs_address)); + if (opA->abs_address != 0) + emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->abs_address)); + } + break; + case COMBO_OP(OpndType_Absolute, OpndType_Absolute): + opOut->optype = OpndType_Absolute; + opOut->abs_address = opA->abs_address + opB->abs_address; + break; + default: +#line 415 + CError_FATAL(); + } +} + +void coerce_to_addressable(Operand *op) { + UInt32 offset; + short reg; + short flag; + short tmp; + Object *obj; + + flag = 0; + obj = op->object; + tmp = 0; + + switch (op->optype) { + case OpndType_GPR: + case OpndType_GPR_ImmOffset: + case OpndType_GPR_Indexed: + case OpndType_GPRPair: + case OpndType_Absolute: + case OpndType_VR: + case OpndType_CRField: + case OpndType_IndirectGPR_ImmOffset: + case OpndType_IndirectGPR_Indexed: + break; + case OpndType_IndirectSymbol: + flag = 1; + case OpndType_Symbol: + if (obj->datatype == DLOCAL) { + if (!local_is_16bit_offset(obj)) { + reg = used_virtual_registers[RegClass_GPR]++; + op_absolute_ha(reg, local_base_register(obj), obj, 0, 1); + op->optype = OpndType_GPR_ImmOffset; + op->reg = reg; + op->object = obj; + } else { + op->optype = OpndType_GPR_ImmOffset; + op->reg = local_base_register(obj); + op->object = obj; + } + } else if (obj->datatype == DABSOLUTE) { + offset = obj->u.address; + if (FITS_IN_SHORT(offset)) { + op->reg = 0; + op->immOffset = obj->u.address; + } else { + emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset)); + op->immOffset = LOW_PART(obj->u.address); + } + op->object = obj; + op->optype = OpndType_GPR_ImmOffset; + } else { + if (copts.codegen_pic) + tmp = pic_base_reg; + reg = used_virtual_registers[RegClass_GPR]++; + op_absolute_ha(reg, tmp, obj, 0, 1); + op->optype = OpndType_GPR_ImmOffset; + op->reg = reg; + } + if (flag) { + if (op->optype == OpndType_GPR_ImmOffset) { + op->optype = OpndType_IndirectGPR_ImmOffset; + } else { +#line 563 + CError_FATAL(); + } + } + break; + default: +#line 581 + CError_FATAL(); + } +} + +void Coerce_to_register(Operand *op, Type *type, short output_reg) { + SInt32 offset; + short opcode; + short reg; + short tmp; + short cond_neg; + short cond; + short bit_offset; + short bit_size; + + if (TYPE_IS_8BYTES(type)) { + coerce_to_register_pair(op, type, output_reg, 0); + return; + } + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_GPRPair: + return; + case OpndType_GPR: + return; + case OpndType_GPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(reg, op->reg, op->object, op->immOffset); + break; + case OpndType_GPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, reg, op->reg, op->regOffset); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + offset = op->abs_address; + if (FITS_IN_SHORT(offset)) { + emitpcode(PC_LI, reg, offset); + } else { + tmp = reg; + if (copts.optimizationlevel > 1 && offset) + tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset)); + if (offset) + emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset)); + } + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opcode = PC_LWZ; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_LBZ; + break; + case 2: + if (is_unsigned(type)) + opcode = PC_LHZ; + else + opcode = PC_LHA; + break; + } + } else { +#line 680 + CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + load_store_register(opcode, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opcode = PC_LWZX; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_LBZX; + break; + case 2: + if (is_unsigned(type)) + opcode = PC_LHZX; + else + opcode = PC_LHAX; + break; + } + } else { +#line 724 + CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + emitpcode(opcode, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + case OpndType_CRField: + cond_neg = 0; + cond = 0; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MFCR, tmp = reg); + switch (op->regOffset) { + case ENOTEQU: + cond_neg = 1; + case EEQU: + cond = 2; + break; + case EGREATEREQU: + cond_neg = 1; + case ELESS: + cond = 0; + break; + case ELESSEQU: + cond_neg = 1; + case EGREATER: + cond = 1; + break; + default: +#line 758 + CError_FATAL(); + } + bit_offset = cond + (op->reg << 2); + bit_size = 1; + emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31); + if (cond_neg) + emitpcode(PC_XORI, tmp, tmp, 1); + break; + default: +#line 769 + CError_FATAL(); + } + + op->optype = OpndType_GPR; + op->reg = reg; +} + +void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) { + SInt32 offset; + short reg; + short regHi; + short tmp1; + short tmp2; + + regHi = -1; + +#line 794 + CError_ASSERT(TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8)); + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_GPRPair: + if (output_reg && !output_regHi) + output_regHi = used_virtual_registers[RegClass_GPR]++; + if (output_regHi && !output_reg) + output_reg = used_virtual_registers[RegClass_GPR]++; + if (op->reg != output_reg || op->regHi != output_regHi) { + tmp1 = output_reg ? output_reg : op->reg; + tmp2 = output_regHi ? output_regHi : op->regHi; + if (tmp1 != op->reg) { + if (tmp1 == op->regHi) { +#line 818 + CError_ASSERT(tmp1 != tmp2); + emitpcode(PC_MR, tmp2, op->regHi); + emitpcode(PC_MR, tmp1, op->reg); + } else { + emitpcode(PC_MR, tmp1, op->reg); + if (op->regHi != tmp2) + emitpcode(PC_MR, tmp2, op->regHi); + } + } else if (tmp2 != op->regHi) { + if (tmp2 == op->reg) { +#line 832 + CError_ASSERT(tmp1 != tmp2); + emitpcode(PC_MR, tmp1, op->reg); + emitpcode(PC_MR, tmp2, op->regHi); + } else { + emitpcode(PC_MR, tmp2, op->regHi); + if (op->reg != tmp1) + emitpcode(PC_MR, tmp1, op->reg); + } + } + } + reg = op->reg; + regHi = op->regHi; + break; + case OpndType_GPR: +#line 849 + CError_FATAL(); + break; + case OpndType_GPR_ImmOffset: +#line 852 + CError_FATAL(); + break; + case OpndType_GPR_Indexed: +#line 855 + CError_FATAL(); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + offset = op->abs_address; + if (FITS_IN_SHORT(offset)) { + emitpcode(PC_LI, reg, offset); + } else { + tmp1 = reg; + if (copts.optimizationlevel > 1 && offset) + tmp1 = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset)); + if (offset) + emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset)); + } + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (is_unsigned(type) || offset >= 0) + load_immediate(regHi, 0); + else + load_immediate(regHi, -1); + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (op->reg == regHi) { + if (op->reg == reg) { +#line 887 + CError_FATAL(); + } else { + load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + } + } else { + load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + } + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, reg, op->reg, op->regOffset); + load_store_register(PC_LWZ, regHi, reg, NULL, high_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, reg, reg, NULL, low_offset); + setpcodeflags(op->flags); + break; + default: +#line 912 + CError_FATAL(); + } + + if (regHi == -1) { +#line 916 + CError_FATAL(); + } else { + op->optype = OpndType_GPRPair; + op->reg = reg; + op->regHi = regHi; + } +} + +void Coerce_to_fp_register(Operand *op, TypeIntegral *tint, short output_reg) { + short reg; + + coerce_to_addressable(op); + + switch (op->optype) { + case OpndType_FPR: + reg = op->reg; + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + load_store_register((tint->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + emitpcode((tint->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390); + setpcodeflags(op->flags); + break; + default: +#line 986 + CError_FATAL(); + } + + op->optype = OpndType_FPR; + op->reg = reg; +} + +void Coerce_to_v_register(Operand *op, TypeStruct *tstruct, short output_reg) { + short reg; + + coerce_to_addressable(op); + + switch (op->optype) { + case OpndType_VR: + reg = op->reg; + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + emitpcode(PC_LVX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + switch (tstruct->stype) { + case STRUCT_TYPE_4: + case STRUCT_TYPE_5: + case STRUCT_TYPE_6: + emitpcode(PC_VSPLTISB, reg, op->abs_address); + break; + case STRUCT_TYPE_7: + case STRUCT_TYPE_8: + case STRUCT_TYPE_9: + case STRUCT_TYPE_E: + emitpcode(PC_VSPLTISH, reg, op->abs_address); + break; + case STRUCT_TYPE_A: + case STRUCT_TYPE_B: + case STRUCT_TYPE_C: + case STRUCT_TYPE_D: + emitpcode(PC_VSPLTISW, reg, op->abs_address); + break; + default: +#line 1049 + CError_FATAL(); + } + op->optype = OpndType_VR; + op->reg = reg; + setpcodeflags(op->flags); + break; + default: +#line 1059 + CError_FATAL(); + } + + op->optype = OpndType_VR; + op->reg = reg; +} + +void store(short reg, Operand *op, Type *type) { + short opcode; + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + opcode = PC_STW; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_STB; + break; + case 2: + opcode = PC_STH; + break; + } + } else { +#line 1171 + CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + load_store_register(opcode, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + opcode = PC_STWX; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_STBX; + break; + case 2: + opcode = PC_STHX; + break; + } + } else { +#line 1188 + CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + emitpcode(opcode, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: +#line 1193 + CError_FATAL(); + } +} + +void store_pair(short reg, short regHi, Operand *op, Type *type) { + short tmp; + +#line 1208 + CError_ASSERT(TYPE_IS_8BYTES(type)); + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, tmp, op->reg, op->regOffset); + load_store_register(PC_STW, reg, tmp, NULL, low_offset); + setpcodeflags(op->flags); + load_store_register(PC_STW, regHi, tmp, NULL, high_offset); + setpcodeflags(op->flags); + break; + default: +#line 1228 + CError_FATAL(); + } +} + +void store_fp(short reg, Operand *op, TypeIntegral *tint) { + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register((tint->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + emitpcode((tint->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: +#line 1259 + CError_FATAL(); + } +} + +void store_v(short reg, Operand *op, TypeStruct *tstruct) { + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + emitpcode(PC_STVX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: +#line 1283 + CError_FATAL(); + } +} + +static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) { + PCode *pc; + + if (pclastblock->pcodeCount <= 0) + return 0; + + pc = pclastblock->lastPCode; + if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg) + return 0; + + if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB)) + return 0; + + if (opcode == PC_RLWINM) { + if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c) + return 0; + } + + return 1; +} + +void extend32(Operand *op, Type *type, short output_reg) { + int r28; + int reg; + + r28 = op->optype >= OpndType_IndirectGPR_ImmOffset; + if (op->optype != OpndType_GPR) + Coerce_to_register(op, type, output_reg); + + switch (type->size) { + case 1: + if (is_unsigned(type)) { + if (r28) + return; + if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31); + } else { + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0)) + return; + emitpcode(PC_EXTSB, reg, op->reg); + } + break; + case 2: + if (r28) + return; + if (is_unsigned(type)) { + if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31); + } else { + if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_EXTSH, reg, op->reg); + } + break; + default: +#line 1389 + CError_FATAL(); + } + + op->optype = OpndType_GPR; + op->reg = reg; +} + +void extend64(Operand *op, Type *type, short output_reg, short output_regHi) { + short tmp; + short regHi; + + if (op->optype != OpndType_GPR) + Coerce_to_register(op, type, output_reg); + + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (regHi == op->reg) { + tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, tmp, op->reg); + op->reg = tmp; + } + + if (is_unsigned(type)) + load_immediate(regHi, 0); + else + emitpcode(PC_SRAWI, regHi, op->reg, 31); + + op->optype = OpndType_GPRPair; + op->regHi = regHi; +} + +void load_floating_constant(short reg, TypeIntegral *type, double *data) { + // do me AFTER +} + +void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) { + // issue with matching the PC_FSUB/PC_FSUBS ternary + Operand temp_op; + double d; + int const_reg; + int tmp_reg; + int work_reg; + int result_reg; + short opcode; + + symbol_operand(&temp_op, maketemporary((Type *) &stdouble)); + coerce_to_addressable(&temp_op); + d = *((double *) &int_to_float_cc); + + const_reg = used_virtual_registers[RegClass_FPR]++; + load_floating_constant(const_reg, &stdouble, &d); + + tmp_reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset); + + emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); + + load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + //opcode = PC_FSUB; + //if (is_single) + // opcode = PC_FSUBS; + //opcode = (is_single != 0) ? PC_FSUBS : PC_FSUB; + if (is_single != 0) + opcode = PC_FSUBS; + else + opcode = PC_FSUB; + emitpcode(opcode, result_reg, work_reg, const_reg); + + op->optype = OpndType_FPR; + op->reg = result_reg; +} + +void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) { + // issue with matching the PC_FSUB/PC_FSUBS ternary + Operand temp_op; + double d; + int const_reg; + int tmp_reg; + int work_reg; + int result_reg; + short opcode; + + symbol_operand(&temp_op, maketemporary((Type *) &stdouble)); + coerce_to_addressable(&temp_op); + d = *((double *) &uns_to_float_cc); + + const_reg = used_virtual_registers[RegClass_FPR]++; + load_floating_constant(const_reg, &stdouble, &d); + + load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset); + + emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); + + load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + //opcode = PC_FSUB; + //if (is_single) + // opcode = PC_FSUBS; + //opcode = (is_single != 0) ? PC_FSUBS : PC_FSUB; + if (is_single != 0) + opcode = PC_FSUBS; + else + opcode = PC_FSUB; + emitpcode(opcode, result_reg, work_reg, const_reg); + + op->optype = OpndType_FPR; + op->reg = result_reg; +} + +void convert_floating_to_integer(Operand *op, short output_reg) { + Operand temp_op; + int tmp_reg; + int result_reg; + + symbol_operand(&temp_op, maketemporary((Type *) &stdouble)); + coerce_to_addressable(&temp_op); + + tmp_reg = used_virtual_registers[RegClass_FPR]++; + emitpcode(PC_FCTIWZ, tmp_reg, op->reg); + load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset); + + op->optype = OpndType_GPR; + op->reg = result_reg; +} + +void convert_floating_to_unsigned(Operand *op, short output_reg) { + static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0}; + + if (op->reg != 1) + emitpcode(PC_FMR, 1, op->reg); + + branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs); + + op->optype = OpndType_GPR; + op->reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, op->reg, 3); +} + +void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) { + int r27; + int offset; + int tmp_reg; + int output; + + offset = tbitfield->unkB; + output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + r27 = tbitfield->unkA + (32 - (tbitfield->bitfieldtype->size * 8)); + if (is_unsigned(tbitfield->bitfieldtype)) { + emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31); + } else if (r27 == 0) { + emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset); + } else { + tmp_reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset); + emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset); + } + + output_op->optype = OpndType_GPR; + output_op->reg = output; +} + +void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) { + int offset = tbitfield->unkB; + int r7 = tbitfield->unkA + (32 - (tbitfield->bitfieldtype->size * 8)); + emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1); +} + +void load_address(short dest_reg, Operand *op) { + coerce_to_addressable(op); + if (op->optype == OpndType_IndirectGPR_ImmOffset) { + if (!op->immOffset && !op->object) { + if (op->reg != dest_reg) { + emitpcode(PC_MR, dest_reg, op->reg); + } + } else { + add_immediate(dest_reg, op->reg, op->object, op->immOffset); + } + } else if (op->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset); + } else { +#line 1849 + CError_FATAL(); + } +} diff --git a/compiler_and_linker/unsorted/PCode.c b/compiler_and_linker/unsorted/PCode.c new file mode 100644 index 0000000..0fde159 --- /dev/null +++ b/compiler_and_linker/unsorted/PCode.c @@ -0,0 +1,299 @@ +#include "compiler.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +PCodeBlock *pcbasicblocks; +PCodeBlock *pclastblock; +void *prologue; +void *epilogue; +PCodeBlock **depthfirstordering; +int pcblockcount; +int pcloopweight; +static unsigned short pclabelcount; + +void initpcode() { + pclastblock = 0; + pcbasicblocks = 0; + pcblockcount = 0; + pclabelcount = 0; + pcloopweight = 1; + initialize_aliases(); +} + +PCode *makepcode(short op, ...) { + PCode *pcode; + va_list list; + + va_start(list, op); + pcode = vformatpcode(op, list); + pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; + return pcode; +} + +void emitpcode(short op, ...) { + PCode *pcode; + va_list list; + + va_start(list, op); + pcode = vformatpcode(op, list); + pcode->sourceoffset = current_statement ? current_statement->sourceoffset : -1; + appendpcode(pclastblock, pcode); +} + +PCode *copypcode(PCode *pcode) { + PCode *newpc; + int extra_arg; + int i; + + extra_arg = 0; + if ((PCODE_FLAG_SET_F(pcode) & fPCodeFlag8000000) && !(PCODE_FLAG_SET_F(pcode) & fPCodeFlag20000000)) + extra_arg = 1; + + newpc = lalloc(sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg)); + memclrw(newpc, sizeof(PCode) + sizeof(PCodeArg) * (pcode->argCount + extra_arg)); + + newpc->op = pcode->op; + newpc->flags = pcode->flags; + newpc->argCount = pcode->argCount; + newpc->_18 = pcode->_18; + for (i = 0; i < pcode->argCount; i++) { + newpc->args[i] = pcode->args[i]; + } + + if (extra_arg) + newpc->args[pcode->argCount].kind = PCOp_PLACEHOLDEROPERAND; + + return newpc; +} + +PCodeLabel *makepclabel() { + PCodeLabel *label; + + label = (PCodeLabel *) lalloc(sizeof(PCodeLabel)); + memclrw(label, sizeof(PCodeLabel)); + label->index = pclabelcount++; + return label; +} + +PCodeBlock *makepcblock() { + PCodeBlock *block; + + block = (PCodeBlock *) lalloc(sizeof(PCodeBlock)); + memclrw(block, sizeof(PCodeBlock)); + block->loopWeight = pcloopweight; + block->blockIndex = pcblockcount++; + if (pclastblock) { + pclastblock->nextBlock = block; + block->prevBlock = pclastblock; + } else { + pcbasicblocks = block; + } + pclastblock = block; + return block; +} + +void pclabel(PCodeBlock *block, PCodeLabel *label) { + PCLink *iter; + PCLink *next; + + iter = (PCLink *) label->block; + while (iter) { + next = (PCLink *) iter->block; + iter->block = block; + iter = next; + } + + label->block = block; + label->resolved = 1; + label->nextLabel = block->labels; + block->labels = label; +} + +void pcbranch(PCodeBlock *block, PCodeLabel *label) { + PCLink *link; + + link = (PCLink *) lalloc(sizeof(PCLink)); + memclrw(link, sizeof(PCLink)); + + link->block = label->block; + if (!label->resolved) + label->block = (PCodeBlock *) link; + link->nextLink = block->successors; + block->successors = link; +} + +void pccomputepredecessors() { + PCodeBlock *block; + PCLink *succ; + PCLink *pred; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (succ = block->successors; succ; succ = succ->nextLink) { + pred = (PCLink *) lalloc(sizeof(PCLink)); + memclrw(pred, sizeof(PCLink)); + + pred->block = block; + pred->nextLink = succ->block->predecessors; + succ->block->predecessors = pred; + } + } +} + +void deleteblock(PCodeBlock *block) { + block->prevBlock->nextBlock = block->nextBlock; + if (block->nextBlock) + block->nextBlock->prevBlock = block->prevBlock; + block->flags |= fPCBlockFlag20; +} + +void deleteunreachableblocks() { + PCodeBlock *block; + + computedepthfirstordering(); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + if (!(block->flags & fPCBlockFlag4)) + deleteblock(block); + } +} + +void appendpcode(PCodeBlock *block, PCode *pcode) { + if (block->firstPCode) { + pcode->nextPCode = 0; + pcode->prevPCode = block->lastPCode; + block->lastPCode->nextPCode = pcode; + block->lastPCode = pcode; + } else { + block->lastPCode = pcode; + block->firstPCode = pcode; + pcode->prevPCode = 0; + pcode->nextPCode = 0; + } + pcode->block = block; + block->pcodeCount++; +} + +void deletepcode(PCode *pcode) { + PCodeBlock *block; + + block = pcode->block; + if (pcode->prevPCode) + pcode->prevPCode->nextPCode = pcode->nextPCode; + else + block->firstPCode = pcode->nextPCode; + if (pcode->nextPCode) + pcode->nextPCode->prevPCode = pcode->prevPCode; + else + block->lastPCode = pcode->prevPCode; + + pcode->block = 0; + block->pcodeCount--; + block->flags &= ~fPCBlockFlag8; +} + +void insertpcodebefore(PCode *anchor, PCode *newpcode) { + PCodeBlock *block; + + block = anchor->block; + if (anchor->prevPCode) + anchor->prevPCode->nextPCode = newpcode; + else + block->firstPCode = newpcode; + newpcode->nextPCode = anchor; + newpcode->prevPCode = anchor->prevPCode; + anchor->prevPCode = newpcode; + newpcode->sourceoffset = anchor->sourceoffset; + + newpcode->block = block; + block->pcodeCount++; + block->flags &= ~fPCBlockFlag8; +} + +void insertpcodeafter(PCode *anchor, PCode *newpcode) { + PCodeBlock *block; + + block = anchor->block; + if (anchor->nextPCode) + anchor->nextPCode->prevPCode = newpcode; + else + block->lastPCode = newpcode; + newpcode->prevPCode = anchor; + newpcode->nextPCode = anchor->nextPCode; + anchor->nextPCode = newpcode; + newpcode->sourceoffset = anchor->sourceoffset; + + newpcode->block = block; + block->pcodeCount++; + block->flags &= ~fPCBlockFlag8; +} + +void setpcodeflags(int flags) { + pclastblock->lastPCode->flags |= flags; + if (flags & fSideEffects) + pclastblock->lastPCode->flags &= ~(fIsCSE | fCommutative | fPCodeFlag10); +} + +void clearpcodeflags(int flags) { + pclastblock->lastPCode->flags &= ~flags; +} + +int pccomputeoffsets() { + int offset; + PCodeBlock *block; + + offset = 0; + for (block = pcbasicblocks; block; block = block->nextBlock) { + block->codeOffset = offset; + offset += block->pcodeCount * 4; + } + + return offset; +} + +typedef struct _DFO { + PCodeBlock *block; + PCLink *link; +} DFO; + +static int depthfirstorder; + +void computedepthfirstordering() { + PCodeBlock *block; + PCLink *link; + DFO *dfo; + int index; + + depthfirstordering = (PCodeBlock **) lalloc(sizeof(PCodeBlock *) * pcblockcount); + memclrw(depthfirstordering, sizeof(PCodeBlock *) * pcblockcount); + depthfirstorder = pcblockcount; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + block->flags &= ~fPCBlockFlag4; + } + + dfo = (DFO *) oalloc(sizeof(DFO) * pcblockcount); + pcbasicblocks->flags |= fPCBlockFlag4; + + dfo->block = pcbasicblocks; + dfo->link = pcbasicblocks->successors; + index = 1; + while (index) { + if ((link = dfo[index - 1].link)) { + dfo[index - 1].link = link->nextLink; + block = link->block; + if (!(block->flags & fPCBlockFlag4)) { + block->flags |= fPCBlockFlag4; + dfo[index].block = block; + dfo[index].link = block->successors; + index++; + } + } else { + depthfirstordering[--depthfirstorder] = dfo[--index].block; + } + } + + while (depthfirstorder) { + depthfirstordering[--depthfirstorder] = 0; + } +} diff --git a/compiler_and_linker/unsorted/PCodeInfo.c b/compiler_and_linker/unsorted/PCodeInfo.c new file mode 100644 index 0000000..e48dac0 --- /dev/null +++ b/compiler_and_linker/unsorted/PCodeInfo.c @@ -0,0 +1,1308 @@ +#include "compiler.h" +#include "compiler/objects.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/CError.h" + +#pragma pool_strings on + +int pcode_bad_operand; +char *orig_buf; +static int do_show_basic_blocks; + +void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo) { + if (bits == 0) { + *hi = 0; + *lo = 0; + return; + } + if (bits == 32) { + *hi = 0x7FFFFFFF; + *lo = -0x80000000; + return; + } + + if (bits < 32 && bits > 0) { + switch (typechar) { + case 'u': + *hi = (1 << bits) - 1; + *lo = 0; + break; + case 'i': + case 'x': + *hi = (1 << bits) - 1; + *lo = -(1 << (bits - 1)); + break; + default: + *hi = (1 << (bits - 1)) - 1; + *lo = -(1 << (bits - 1)); + } + } else { +#line 65 + CError_FATAL(); + } +} + +int pcode_check_imm_bits(SInt32 value, int bits, char typechar) { + char buf[2]; + int forcedBits; + SInt32 r6; + SInt32 r0; + + forcedBits = 0; + if (bits >= 0 && bits < 32) { + if (bits == 0) { + r6 = 0; + r0 = 0; + } else { + switch (typechar) { + case 'u': + r6 = (1 << bits) - 1; + r0 = 0; + break; + case 'i': + case 'x': + r6 = (1 << bits) - 1; + r0 = -(1 << (bits - 1)); + break; + case '1': + case '2': + case '3': + case '4': + buf[0] = typechar; + buf[1] = 0; + forcedBits = atoi(buf); + default: + r6 = (1 << (bits - 1)) - 1; + r0 = -(1 << (bits - 1)); + } + } + + if ((value < r0) || (value > r6)) + return 1; + if (forcedBits > 0 && value != ((value >> forcedBits) << forcedBits)) + return 1; + } else if (bits > 32) { +#line 110 + CError_FATAL(); + } + + return 0; +} + +int pcode_const_from_format(const char *format, int *pResult) { + char buf[32]; + int len = 0; + + for (len = 0; len < 30 && isdigit(format[len]); len++) { + buf[len] = format[len]; + } + buf[len] = 0; + + *pResult = atoi(buf); + return len; +} + +PCode *vformatpcode(short opcode, va_list argList) { + // has many wrong registers but probably ok otherwise + int argcount; // r29 + OpcodeInfo *info; // r27 for a short time + int effect; // r27 + const char *format; // r26 + PCode *pcode; // r25 + PCodeArg *arg; // r24 + int unkreg_r23; // r23 + int unkreg_r22; // r22 + PCodeArg *lastArg; // r21 + int pcode_size; // r20 for a short time + int tmp; + int tmp2; // r19 + int i; + int thing; + int thing2; + int thing3; + int thing4; + Object *obj; + PCodeLabel *label; + char c; + + info = &opcodeinfo[opcode]; + format = info->format; + argcount = info->x8; + unkreg_r23 = 0; + unkreg_r22 = 0; + + if (format[0] == '#') { + unkreg_r23 = va_arg(argList, int); + argcount += unkreg_r23; + format++; + } + + if (info->flags & fPCodeFlag8000000) + unkreg_r22 = 1; + + if ((argcount + unkreg_r22) < 5) + unkreg_r22 += 5 - (argcount + unkreg_r22); + + pcode_size = (argcount + unkreg_r22) * sizeof(PCodeArg) + sizeof(PCode); + pcode = lalloc(pcode_size); + memclrw(pcode, pcode_size); + + pcode->op = opcode; + pcode->argCount = argcount; + pcode->flags = info->flags; + lastArg = pcode->args + pcode->argCount; + arg = pcode->args; + while (*format) { + if (arg >= lastArg) { +#line 189 + CError_FATAL(); + } + + if (*format == ',' || *format == ';') + format++; + if (*format == '[' || *format == '(') + format++; + + effect = EffectRead; + if (*format == '=') { + effect = EffectWrite; + format++; + } else if (*format == '+') { + effect = EffectRead | EffectWrite; + format++; + } + + if (*format == '-') + format++; + if (*format == '?') + format++; + if (*format == '!') + format++; + + switch ((c = *format)) { + case 'b': + tmp = va_arg(argList, int); + if (!tmp) + effect = 0; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + break; + case 'r': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'f': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_FPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'v': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_VR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'c': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'C': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 2; + arg->data.reg.effect = effect; + break; + case 'L': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 1; + arg->data.reg.effect = effect; + break; + case 'V': + i = unkreg_r23; + while (i > 0) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = 31 - --i; + arg->data.reg.effect = effect; + arg++; + } + arg--; + break; + case 'X': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0; + arg->data.reg.effect = effect; + break; + case 'Y': + if (pcode->op == PC_MTCRF) { + tmp = pcode->args[0].data.imm.value; + for (i = 0; i < 8; i++) { + if (tmp & (0x80 >> i)) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = i; + arg->data.reg.effect = EffectWrite; + arg++; + } + } + } else { + i = 0; + while (i < 8) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = i++; + arg->data.reg.effect = EffectRead; + arg++; + } + } + arg--; + break; + case 'Z': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = 0; + arg->data.reg.effect = effect; + break; + case 'P': + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing); + } else { +#line 319 + CError_FATAL(); + } + tmp = va_arg(argList, int); + tmp2 = -1; + for (i = 0; i < 4; i++) { + if (tmp == spr_to_sysreg[i]) { + tmp2 = i; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = i; + arg->data.reg.effect = effect; + if ((effect & EffectWrite) && (tmp == 0x100)) + pcsetsideeffects(pcode); + break; + } + } + + if (tmp2 < 0) { + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + } + + break; + + case 'T': + tmp = va_arg(argList, int); + if (tmp == 0x10C) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0x11C; + arg->data.reg.effect = effect; + } else if (tmp == 0x10D) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0x11D; + arg->data.reg.effect = effect; + } else { +#line 353 + CError_FATAL(); + } + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + + case 'S': + tmp2 = -1; + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing2); + } else { +#line 371 + CError_FATAL(); + } + + for (i = 0; i < 4; i++) { + if (thing2 == spr_to_sysreg[i]) { + tmp2 = i; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = i; + arg->data.reg.effect = effect; + if ((effect & EffectWrite) && (thing2 == 0x100)) + pcsetsideeffects(pcode); + break; + } + } + + if (tmp2 < 0) { + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + } + break; + + case 'a': + case 'i': + case 'n': + case 'u': + case 'w': + case 'x': + tmp2 = (unsigned char) c; + thing3 = 16; + if (*format == 'a') { + if (isdigit(format[1])) { + tmp2 = (unsigned char) *(++format); + } else { +#line 408 + CError_FATAL(); + } + } + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing3); + } + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, thing3, tmp2)) { +#line 419 + CError_FATAL(); + } + break; + + case 'N': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 6, 'u')) { +#line 429 + CError_FATAL(); + } + break; + + case 'D': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 10, 'u')) { +#line 438 + CError_FATAL(); + } + break; + + case 'B': + case 't': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 5, 'u')) { +#line 448 + CError_FATAL(); + } + break; + + case 'Q': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + arg++; + case 'q': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 4, 'u')) { +#line 463 + CError_FATAL(); + } + break; + + case 'l': + if ((label = va_arg(argList, PCodeLabel *))) { + arg->kind = PCOp_LABEL; + arg->data.label.label = label; + } else { + arg->kind = PCOp_MEMORY; + obj = va_arg(argList, Object *); +#line 476 + CError_ASSERT(obj->otype == OT_OBJECT); + arg->data.mem.obj = obj; + arg->data.mem.offset = 0; + arg->arg = 1; + } + break; + + case 'd': +#line 490 + CError_ASSERT(format[1] == '('); + effect = EffectRead; + format += 2; + if (*format == '=') { + effect = EffectWrite; + format++; + } else if (*format == '+') { + effect = EffectRead | EffectWrite; + format++; + } + +#line 502 + CError_ASSERT(format[0] == 'b'); + + tmp = va_arg(argList, int); + if (tmp == 0) + effect = 0; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + arg++; + + case 'm': + obj = va_arg(argList, Object *); + if (obj) { +#line 515 + CError_ASSERT(obj->otype == OT_OBJECT); + + if (obj->datatype == DABSOLUTE) { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.obj = obj; + arg->data.imm.value = va_arg(argList, SInt32); + } else { + arg->kind = PCOp_MEMORY; + arg->data.mem.obj = obj; + arg->data.mem.offset = va_arg(argList, SInt32); + + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { + pcode->_18 = make_alias(obj, arg->data.mem.offset, nbytes_loaded_or_stored_by(pcode)); + if (is_volatile_object(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } else { + if (pcode->op == PC_ADDI) + pcode->_18 = make_alias(obj, arg->data.mem.offset, 1); + } +#line 536 + CError_ASSERT(obj->datatype == DLOCAL || arg->data.mem.offset == 0); + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) { + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) + if (OBJ_GET_TARGET_VOLATILE(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } + + if (pcode->flags & (fPCodeFlag1 | fPCodeFlag8)) { + arg->arg = RefType_4; + } else if (obj->datatype == DLOCAL) { + if (!local_is_16bit_offset(obj)) + arg->arg = RefType_D; + else + arg->arg = RefType_1; + } else { + arg->arg = RefType_6; + } + } + } else { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, SInt32); + arg->data.imm.obj = NULL; + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) + pcode->flags |= fPCodeFlag20; + } + break; + + case 'M': + obj = va_arg(argList, Object *); + if (obj) { +#line 578 + CError_ASSERT(obj->otype == OT_OBJECT); + + if (obj->datatype == DABSOLUTE) { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.obj = obj; + arg->data.imm.value = va_arg(argList, SInt32); + } else { + arg->kind = PCOp_MEMORY; + arg->data.mem.obj = obj; + arg->data.mem.offset = va_arg(argList, SInt32); + +#line 590 + CError_ASSERT(obj->datatype == DLOCAL || arg->data.mem.offset == 0); + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) { + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) + if (OBJ_GET_TARGET_VOLATILE(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } + + if (obj->datatype == DLOCAL) { + arg->arg = RefType_C; + } else { + arg->arg = RefType_8; + } + } + } else { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, SInt32); + arg->data.imm.obj = NULL; + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) + pcode->flags |= fPCodeFlag20; + } + break; + + case 'p': + arg->kind = PCOp_PLACEHOLDEROPERAND; + break; + + case 'O': + arg--; + break; + + default: +#line 629 + CError_FATAL(); + } + + while (format[1] && strchr("/<>|*", format[1])) { + switch (*(++format)) { + case '/': + if (format[1] == '2') + format++; + break; + case '<': + case '*': + case '|': + case '>': + if (format[1] == 'p') { + format++; + } else if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing4); + } else { +#line 659 + CError_FATAL(); + } + } + } + + if ((c = *(++format)) == ']' || c == ')') + format++; + arg++; + } + + while (arg < lastArg) { + arg->kind = PCOp_PLACEHOLDEROPERAND; + arg++; + } + while (unkreg_r22) { + arg->kind = PCOp_PLACEHOLDEROPERAND; + arg++; + unkreg_r22--; + } + return pcode; +} + +int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, int bitCount, char *buf) { + int errorlen; + char *name; + int tmp; + int regclass; + int refis1; + int b_null; + + errorlen = 0; + + if (operand->kind != expectedKind) { + char *kindstr; + switch (expectedKind) { + case PCOp_REGISTER: kindstr = "REGISTER"; break; + case PCOp_SYSREG: kindstr = "SYSREG"; break; + case PCOp_IMMEDIATE: kindstr = "IMMEDIATE"; break; + case PCOp_MEMORY: kindstr = "MEMORY"; break; + case PCOp_LABEL: kindstr = "LABEL"; break; + case PCOp_LABELDIFF: kindstr = "LABELDIFF"; break; + case PCOp_PLACEHOLDEROPERAND: kindstr = "PLACEHOLDEROPERAND"; break; + default: kindstr = "unknown kind"; + } + tmp = sprintf(buf, "{EXPECTED %s}", kindstr); + errorlen += tmp; + buf += tmp; + pclist_bad_operand = 1; + } + + switch (operand->kind) { + case PCOp_REGISTER: + if (operand->arg != (regclass = a3)) { + tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[regclass]); + errorlen += tmp; + buf += tmp; + } + if (operand->data.reg.reg < n_real_registers[regclass] && (name = special_register_names[operand->arg][operand->data.reg.reg])) + tmp = sprintf(buf, "%s", name); + else + tmp = sprintf(buf, register_class_format[operand->arg], operand->data.reg.reg); + errorlen += tmp; + break; + case PCOp_SYSREG: + if (operand->arg != RegClass_SPR) { + tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[RegClass_SPR]); + errorlen += tmp; + buf += tmp; + } + tmp = sprintf(buf, register_class_format[RegClass_SPR], operand->data.reg.reg); + errorlen += tmp; + break; + case PCOp_IMMEDIATE: + switch (a3) { + case 'x': + tmp = sprintf(buf, "0x%x", operand->data.imm.value); + break; + case 'u': + tmp = sprintf(buf, "%u", operand->data.imm.value); + break; + default: + tmp = sprintf(buf, "%ld", operand->data.imm.value); + break; + } + errorlen += tmp; + buf += tmp; + if (operand->data.imm.obj) { + name = CMangler_GetLinkName(operand->data.imm.obj)->name; + if (strlen(name) > 50) + tmp = sprintf(buf, "{%45.45s...}", name); + else + tmp = sprintf(buf, "{%s}", name); + errorlen += tmp; + buf += tmp; + } + if (pcode_check_imm_bits(operand->data.imm.value, bitCount, (char) a3)) { + errorlen += sprintf(buf, "{IMM too large %i bits}", bitCount); + pclist_bad_operand = 1; + } + break; + case PCOp_MEMORY: + switch ((unsigned char) operand->arg) { + case RefType_0: + case RefType_1: + case RefType_2: + case RefType_3: + case RefType_4: + case RefType_5: + case RefType_9: + break; + case RefType_8: + case RefType_B: + case RefType_C: + tmp = sprintf(buf, "HA("); + errorlen += tmp; + buf += tmp; + break; + case RefType_7: + tmp = sprintf(buf, "HI("); + errorlen += tmp; + buf += tmp; + break; + case RefType_6: + case RefType_A: + case RefType_D: + tmp = sprintf(buf, "LO("); + errorlen += tmp; + buf += tmp; + break; + default: + tmp = sprintf(buf, "{UNEXPECTED reftype = %d}", (unsigned char) operand->arg); + errorlen += tmp; + buf += tmp; + } + name = CMangler_GetLinkName(operand->data.mem.obj)->name; + if (strlen(name) == 0 || strlen(name) > 3200 || name[0] < 0) { +#line 849 + CError_FATAL(); + } + if (strlen(name) > 50) + tmp = sprintf(buf, "%45.45s...", name); + else + tmp = sprintf(buf, "%s", name); + errorlen += tmp; + buf += tmp; + if (operand->data.mem.offset > 0) + tmp = sprintf(buf, "+%d", operand->data.mem.offset); + else if (operand->data.mem.offset != 0) + tmp = sprintf(buf, "-%d", -operand->data.mem.offset); + else + tmp = 0; + errorlen += tmp; + buf += tmp; + if (copts.codegen_pic && uses_globals && pic_base_reg) { + tmp = sprintf(buf, "-B%d", pic_base_pcodelabel->block->blockIndex); + errorlen += tmp; + buf += tmp; + } + switch ((unsigned char) operand->arg) { + case RefType_6: + case RefType_7: + case RefType_8: + case RefType_A: + case RefType_B: + case RefType_C: + case RefType_D: + errorlen += sprintf(buf, ")"); + } + break; + case PCOp_LABEL: + if (do_show_basic_blocks) { + if (!operand->data.label.label->block) + tmp = sprintf(buf, "B<unknown>"); + else + tmp = sprintf(buf, "B%ld", operand->data.label.label->block->blockIndex); + } else { + tmp = sprintf(buf, "%.8lX", operand->data.label.label->block->codeOffset); + } + errorlen += tmp; + break; + case PCOp_LABELDIFF: + refis1 = ((unsigned char) operand->arg == 1); + b_null = !operand->data.labeldiff.labelB->block; + if (operand->data.labeldiff.labelA->block == NULL) { + if (b_null) + tmp = sprintf(buf, "%sB<unknown>-B<unknown>+%ld", refis1 ? "-" : "", operand->data.labeldiff.offset); + else + tmp = sprintf(buf, "%sB<unknown>-B%ld+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); + } else { + if (b_null) + tmp = sprintf(buf, "%sB%ld-%B<unknown>+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.offset); + else + tmp = sprintf(buf, "%sB%ld-B%ld+%ld", refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); + } + errorlen += tmp; + break; + case PCOp_PLACEHOLDEROPERAND: + errorlen += sprintf(buf, "{placeholder}"); + break; + default: + errorlen += sprintf(buf, "{UNEXPECTED kind = %d}", operand->kind); + } + + return errorlen; +} + +int formatoperand(PCodeArg *operand, char *buf) { + +} + +void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { + const char *format; // r29 + // there might be a PCodeArg *arg in r28 + // not sure lol + PCodeArg *pa; + int arg_index; // r27 + + char *name; + int i; + int tmp; + int tmp2; + int thing; + int thing2; + int thing4; + char c; + int flagSetT; + int flagSetF; + + static char *cc[] = { + "lt", "gt", "eq", "un" + }; + static char *to[] = { + "", "lgt", "llt", "", + "eq", "lge", "lle", "", + "gt", "", "", "", + "ge", "", "", "", + "lt", "", "", "", + "le", "", "", "", + "ne", "", "", "", + "", "", "" + }; + + format = opcodeinfo[pcode->op].format; + orig_buf = buf; + do_show_basic_blocks = showBasicBlocks; + + if (format[0] == '#') { + format++; + if (format[0] == ',') + format++; + } + + arg_index = 0; + pa = pcode->args; + while (*format) { + if (*format == ';') + break; + if (arg_index == pcode->argCount) { + pclist_bad_operand = 1; + buf += sprintf(buf, "{EXCEDED noperands, remaning format = %s}", format); + break; + } + + if (*format == ',') { + *(buf++) = ','; + format++; + } + + if (*format == '[' || *format == '(') { + *(buf++) = *format; + format++; + } + + if (*format == '=' || *format == '+') + format++; + if (*format == '-') + format++; + + if (*format == '?') { + format++; + if (*format != 'c') + *(buf++) = ','; + } + + if (*format == '!') + format++; + + switch (*format) { + case 'b': + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { + if (pa->data.reg.effect & EffectWrite) { + pclist_bad_operand = 1; + buf += sprintf(buf, "!!!r"); + } + buf += sprintf(buf, "0"); + } + break; + case 'r': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + break; + case 'f': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_FPR, -1, buf); + break; + case 'v': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_VR, -1, buf); + break; + case 'c': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); + break; + case 'X': +#line 1124 + CError_ASSERT(pa->data.reg.reg == 0); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'C': +#line 1129 + CError_ASSERT(pa->data.reg.reg == 2); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'L': +#line 1134 + CError_ASSERT(pa->data.reg.reg == 1); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'Z': +#line 1139 + CError_ASSERT(pa->data.reg.reg == 0); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'P': + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing); + } else { +#line 1149 + CError_FATAL(); + } + case 'S': + case 'T': + case 's': + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_SPR) { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + } else { + for (i = 0; i < 4; i++) { + if (pa->data.reg.reg == spr_to_sysreg[i]) { +#line 1161 + CError_FATAL(); + break; + } + } + + buf += expectandformatoperand(pa, PCOp_SYSREG, RegClass_SPR, -1, buf); + } + break; + + case 'V': + do { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR); + buf--; + pa--; + arg_index--; + break; + + case 'Y': + do { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_CRFIELD); + buf--; + pa--; + arg_index--; + break; + + case 'Q': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + case 'q': + if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value >= 0 && pa->data.imm.value < 4 && (name = cc[pa->data.imm.value])[0]) { + buf += sprintf(buf, "%s", name); + } else { + buf += sprintf(buf, "{OUT OF RANGE}"); + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + } + break; + case 'a': + case 'i': + case 'u': + case 'x': + tmp = *format; + if (tmp == 'a') { + if (isdigit(format[1])) { + format++; + tmp = *format; + } else { +#line 1227 + CError_FATAL(); + } + } + if ((tmp2 = isdigit(format[1]))) + format += pcode_const_from_format(format + 1, &thing2); + if (!tmp2) + thing2 = -1; + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, tmp, thing2, buf); + break; + + case 'N': + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 6, buf); + break; + + case 'D': + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 10, buf); + break; + + case 't': + if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value > 0 && pa->data.imm.value < 31 && (name = to[pa->data.imm.value])[0]) { + buf += sprintf(buf, "%s", name); + } else { + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'x', 5, buf); + } + break; + + case 'l': + if (pa->kind == PCOp_IMMEDIATE) { + buf += sprintf(buf, "*%s%ld", (pa->data.imm.value >= 0) ? "+" : "", pa->data.imm.value); + } else if (pa->kind == PCOp_LABELDIFF) { + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + } else if (pa->kind == PCOp_LABEL) { + buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); + } else { + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + } + break; + + case 'd': + if (pa[1].kind == PCOp_MEMORY) + buf += expectandformatoperand(pa + 1, PCOp_MEMORY, 0, -1, buf); + else + buf += expectandformatoperand(pa + 1, PCOp_IMMEDIATE, 0, -1, buf); +#line 1283 + CError_ASSERT(format[1] == '('); + format++; + *(buf++) = *(format++); + if (*format == '+') + format++; +#line 1291 + CError_ASSERT(format[0] == 'b'); + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { + if (pa->data.reg.effect & (EffectRead | EffectWrite)) { + pclist_bad_operand = 1; + buf += sprintf(buf, "!!!r"); + } + buf += sprintf(buf, "0"); + } else { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + } + pa++; + i++; + break; + + case 'w': + if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'm': + case 'n': + if (pa->kind == PCOp_MEMORY) + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + else if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else if ((pcode->flags & (fPCodeFlag1 | fPCodeFlag8)) && (pa->kind == PCOp_LABEL)) + buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'M': + if (pa->kind == PCOp_MEMORY) { +#line 1335 + CError_ASSERT(pa->arg == RefType_8 || pa->arg == RefType_B || pa->arg == RefType_C); + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + } else if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'O': + pa--; + arg_index--; + break; + + case 'p': + buf += expectandformatoperand(pa, PCOp_PLACEHOLDEROPERAND, 0, -1, buf); + break; + + default: +#line 1465 + CError_FATAL(); + } + + while (format[1] && strchr("/<>|*", format[1])) { + switch (*(++format)) { + case '/': + if (format[1] == '2') + format++; + break; + case '<': + case '*': + case '|': + case '>': + if (format[1] == 'p') { + format++; + } else if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing4); + } else { +#line 1495 + CError_FATAL(); + } + } + } + + if ((c = *(++format)) == ']' || c == ')') { + *(buf++) = c; + format++; + } + + pa++; + arg_index++; + } + + if (buf[-1] == ',') + buf--; + + flagSetT = PCODE_FLAG_SET_T(pcode); + flagSetF = PCODE_FLAG_SET_F(pcode); + if (pcode->flags & fIsConst) + buf += sprintf(buf, "; fIsConst"); + if (pcode->flags & fIsVolatile) + buf += sprintf(buf, "; fIsVolatile"); + if (pcode->flags & fSideEffects) + buf += sprintf(buf, "; fSideEffects"); + if (pcode->flags & fIsCSE) + buf += sprintf(buf, "; fIsCSE"); + if (pcode->flags & fCommutative) + buf += sprintf(buf, "; fCommutative"); + + if (flagSetT & fIsPtrOp) + buf += sprintf(buf, "; fIsPtrOp"); + + if (flagSetF) { + if (flagSetF & fLink) + buf += sprintf(buf, "; fLink"); + if (flagSetF & fAbsolute) + buf += sprintf(buf, "; fAbsolute"); + if (flagSetF & fBranchTaken) + buf += sprintf(buf, "; fBranchTaken"); + if (flagSetF & fBranchNotTaken) + buf += sprintf(buf, "; fBranchNotTaken"); + } else if (flagSetT) { + if (flagSetT & fSetsCarry) + buf += sprintf(buf, "; fSetsCarry"); + if (flagSetT & fOverflow) + buf += sprintf(buf, "; fOverflow"); + } + + *buf = 0; +} + +PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b) { + +} + +int is_location_independent(PCode *pcode) { + +} + +int can_reuse_stored_value(PCode *a, PCode *b) { + +} + +int nbytes_loaded_or_stored_by(PCode *pcode) { + OpcodeInfo *oinfo = opcodeinfo + pcode->op; + if (oinfo->flags & (fPCodeFlag2 | fPCodeFlag4)) { + switch (pcode->op) { + case PC_LBZ: + case PC_LBZU: + case PC_LBZX: + case PC_LBZUX: + case PC_STB: + case PC_STBU: + case PC_STBX: + case PC_STBUX: + return 1; + case PC_LHZ: + case PC_LHZU: + case PC_LHZX: + case PC_LHZUX: + case PC_LHA: + case PC_LHAU: + case PC_LHAX: + case PC_LHAUX: + case PC_LHBRX: + case PC_STH: + case PC_STHU: + case PC_STHX: + case PC_STHUX: + case PC_STHBRX: + return 2; + case PC_LWZ: + case PC_LWZU: + case PC_LWZX: + case PC_LWZUX: + case PC_LWBRX: + case PC_STW: + case PC_STWU: + case PC_STWX: + case PC_STWUX: + case PC_STWBRX: + case PC_LFS: + case PC_LFSU: + case PC_LFSX: + case PC_LFSUX: + case PC_STFS: + case PC_STFSU: + case PC_STFSX: + case PC_STFSUX: + case PC_LWARX: + case PC_STFIWX: + case PC_STWCX: + case PC_ECIWX: + case PC_ECOWX: + case PC_MFROM: + case PC_LSCBX: + return 4; + case PC_LMW: + case PC_STMW: + if (pcode->args[0].kind == PCOp_REGISTER && pcode->args[0].arg == RegClass_GPR) + return (32 - pcode->args[0].data.reg.reg) * 4; + else + return 128; + case PC_LFD: + case PC_LFDU: + case PC_LFDX: + case PC_LFDUX: + case PC_STFD: + case PC_STFDU: + case PC_STFDX: + case PC_STFDUX: + return 8; + case PC_LSWI: + case PC_STSWI: + return pcode->args[2].data.imm.value; // not sure if imm is the right union type here + case PC_LSWX: + case PC_STSWX: + return 128; + + // there's probably an ifdef here lmao + case PC_LVEBX: + case PC_STVEBX: + return 1; + case PC_LVEHX: + case PC_STVEHX: + return 2; + case PC_LVEWX: + case PC_STVEWX: + return 4; + case PC_LVSL: + case PC_LVSR: + case PC_LVX: + case PC_LVXL: + case PC_STVX: + case PC_STVXL: + return 16; + + default: +#line 2011 + CError_FATAL(); + } + } + +#line 2014 + CError_FATAL(); + return 0; +} + +void change_num_operands(PCode *pcode, int newNum) { + +} + +void change_opcode(PCode *pcode, short opcode) { + pcode->flags = (pcode->flags & ~(opcodeinfo[pcode->op].flags & ~fIsPtrOp)) | opcodeinfo[opcode].flags; + if ((pcode->flags & fPCodeFlag10) && (PCODE_FLAG_SET_F(pcode) & fPCodeFlag20000000)) + pcode->flags &= ~fPCodeFlag10; + pcode->op = opcode; +} diff --git a/compiler_and_linker/unsorted/PCodeUtilities.c b/compiler_and_linker/unsorted/PCodeUtilities.c new file mode 100644 index 0000000..b0191e9 --- /dev/null +++ b/compiler_and_linker/unsorted/PCodeUtilities.c @@ -0,0 +1,348 @@ +#include "compiler/PCodeUtilities.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/CError.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler.h" + +void pcsetrecordbit(PCode *pc) { + int reg; + PCodeArg *arg; + short argCount; + int argIdx; + + pc->flags &= ~(fPCodeFlag10 | fCommutative | fIsCSE); + if ((pc->flags & (fPCodeFlag80000000 | fPCodeFlag40000000)) == fPCodeFlag40000000) { + reg = 1; + } else if ((pc->flags & (fPCodeFlag80000000 | fPCodeFlag40000000)) == (fPCodeFlag80000000 | fPCodeFlag40000000)) { + reg = 6; + } else { + reg = 0; + } + + if (pc->op == PC_ANDI || pc->op == PC_ANDIS) { + pc->flags |= fPCodeFlag20000000; + } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) { + pc->flags |= fPCodeFlag10000000; + pc->flags |= fPCodeFlag20000000; + change_num_operands(pc, 5); + pc->op = PC_ADDICR; + +#line 76 + CError_ASSERT(pc->args[3].kind == PCOp_PLACEHOLDEROPERAND); + pc->args[3].kind = PCOp_REGISTER; + pc->args[3].arg = RegClass_SPR; + pc->args[3].data.reg.reg = 0; + pc->args[3].data.reg.effect = EffectWrite; +#line 80 + CError_ASSERT(pc->args[4].kind == PCOp_PLACEHOLDEROPERAND); + pc->args[4].kind = PCOp_REGISTER; + pc->args[4].arg = RegClass_CRFIELD; + pc->args[4].data.reg.reg = reg; + pc->args[4].data.reg.effect = EffectWrite; + } else { + arg = pc->args; + argIdx = argCount = pc->argCount; + while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { + if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) { + arg->data.reg.effect |= EffectWrite; + pc->flags |= fPCodeFlag20000000; + return; + } + arg++; + argIdx--; + } + + if (argIdx <= 0) { + arg = &pc->args[argCount]; + pc->argCount++; + } + +#line 105 + CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND); + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = reg; + arg->data.reg.effect = EffectWrite; + if (pc->op != PC_ADDICR) + pc->flags |= fPCodeFlag20000000; + } +} + +void pcsetsideeffects(PCode *pc) { + pc->flags &= ~(fPCodeFlag10 | fCommutative | fIsCSE); + pc->flags |= fSideEffects; +} + +void pcsetlinkbit(PCode *pc) { + PCodeArg *arg; + int argIdx; + + switch (pc->op) { + case PC_B: + pc->op = PC_BL; + break; + case PC_BCTR: + pc->op = PC_BCTRL; + break; + case PC_BLR: + pc->op = PC_BLRL; + break; + } + + arg = pc->args; + argIdx = pc->argCount; + while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { + if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) { + arg->data.reg.effect |= EffectWrite; + pc->flags |= fLink; + return; + } + arg++; + argIdx--; + } + +#line 169 + CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND); + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 1; + arg->data.reg.effect = EffectWrite; + + if (opcodeinfo[pc->op].flags & fPCodeFlag8) { + pc->flags &= ~fPCodeFlag1; + pc->flags |= fPCodeFlag8; + } + pc->flags |= fLink; +} + +void branch_label(PCodeLabel *label) { + if (pclastblock->pcodeCount) { + pcbranch(pclastblock, label); + makepcblock(); + } + pclabel(pclastblock, label); +} + +void branch_conditional(short a, short compareop, short c, PCodeLabel *label) { + PCodeBlock *tmpblock; + PCodeLabel *tmplabel; + int r28; + + tmpblock = pclastblock; + tmplabel = makepclabel(); + + switch (compareop) { + case ENOTEQU: + c = !c; + case EEQU: + r28 = 2; + break; + case EGREATEREQU: + c = !c; + case ELESS: + r28 = 0; + break; + case ELESSEQU: + c = !c; + case EGREATER: + r28 = 1; + break; + } + + emitpcode(c ? PC_BT : PC_BF, a, r28, label); + pcbranch(pclastblock, label); + pcbranch(pclastblock, tmplabel); + makepcblock(); + pclabel(pclastblock, tmplabel); +} + +void branch_always(PCodeLabel *label) { + emitpcode(PC_B, label); + pcbranch(pclastblock, label); + makepcblock(); +} + +void branch_decrement_always(short opcode, PCodeLabel *label) { + PCodeLabel *tmplabel = makepclabel(); + emitpcode(opcode, label); + pcbranch(pclastblock, label); + pcbranch(pclastblock, tmplabel); + makepcblock(); + pclabel(pclastblock, tmplabel); +} + +void branch_indirect(Object *obj) { + emitpcode(PC_BCTR, obj, 0); + makepcblock(); +} + +int branch_count_volatiles(void) { + int count = 0; + int i; + char rclass; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (i = 0; i < n_scratch_registers[(char)rclass]; i++) { + count++; + } + } + + return count; +} + +PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) { + int i; + char rclass; + + for (rclass = RegClassMax - 1; rclass >= 0; rclass--) { + for (i = 0; i < n_scratch_registers[(char)rclass]; i++) { + arglist->kind = PCOp_REGISTER; + arglist->arg = rclass; + arglist->data.reg.reg = scratch_registers[(char)rclass][i]; + arglist->data.reg.effect = EffectWrite; + if (masks[(char)rclass] & (1 << scratch_registers[(char)rclass][i])) + arglist->data.reg.effect |= EffectRead; + arglist++; + } + } + + return arglist; +} + +void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) { + int count; + PCode *pc; + PCodeArg *arg; + + count = branch_count_volatiles(); + if (copts.exceptions && current_statement) + count += countexceptionactionregisters(current_statement->dobjstack); + + pc = makepcode(PC_BL, count, obj, 0); + arg = branch_record_volatiles(pc->args + 1, masks); + if (copts.exceptions && current_statement) + noteexceptionactionregisters(current_statement->dobjstack, arg); + appendpcode(pclastblock, pc); + + if (add_nop) + emitpcode(PC_NOP); + + branch_label(makepclabel()); + if (copts.exceptions && current_statement) + recordexceptionactions(pc, current_statement->dobjstack); +} + +void branch_subroutine_ctr(UInt32 *masks) { + int count; + PCode *pc; + PCodeArg *arg; + + count = branch_count_volatiles(); + if (copts.exceptions && current_statement) + count += countexceptionactionregisters(current_statement->dobjstack); + + pc = makepcode(PC_BCTRL, count); + arg = branch_record_volatiles(pc->args + 1, masks); + if (copts.exceptions && current_statement) + noteexceptionactionregisters(current_statement->dobjstack, arg); + appendpcode(pclastblock, pc); + + branch_label(makepclabel()); + if (copts.exceptions && current_statement) + recordexceptionactions(pc, current_statement->dobjstack); +} + +void add_immediate(short dest_reg, short base_reg, Object *obj, short offset) { + short tmp_reg = base_reg; + + if (obj && offset && obj->datatype != DLOCAL) { + tmp_reg = used_virtual_registers[RegClass_GPR]++; + add_immediate_lo(tmp_reg, base_reg, obj, 0, 1); + obj = NULL; + } + + if (!obj && !offset) + emitpcode(PC_MR, dest_reg, tmp_reg); + else + emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset); +} + +PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) { + PCode *pc; + +#line 577 + CError_ASSERT(obj); + + pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset); + if (add_to_block) + appendpcode(pclastblock, pc); + return pc; +} + +PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) { + PCode *pc; + int tmp_reg; + + if (obj->datatype == DLOCAL) { + pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset); + } else if (copts.codegen_pic) { + tmp_reg = base_reg; +#line 601 + CError_ASSERT(tmp_reg); + pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset); + } else { +#line 606 + CError_ASSERT(base_reg == 0); + pc = makepcode(PC_LIS, dest_reg, obj, offset); + } + + if (add_to_block) + appendpcode(pclastblock, pc); + return pc; +} + +void load_store_register(short opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) { + short addi_tmp; + short offset_reg1; + short offset_reg2; + + offset_reg1 = base_reg; + if (obj && offset && obj->datatype != DLOCAL) { + offset_reg1 = used_virtual_registers[RegClass_GPR]++; + add_immediate_lo(offset_reg1, base_reg, obj, 0, 1); + obj = NULL; + } + + if (offset != (short)offset) { + if (opcode == PC_LWZ && dest_reg == 12) + offset_reg2 = 12; + else if (opcode == PC_LWZ && dest_reg == 11) + offset_reg2 = 11; + else + offset_reg2 = used_virtual_registers[RegClass_GPR]++; + + emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15))); + offset = (short) offset; + offset_reg1 = offset_reg2; + } + + if (opcode == PC_STVX || opcode == PC_LVX) { + offset_reg2 = 0; + if (obj) { + addi_tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset); + offset_reg1 = addi_tmp; + } else if (offset) { + offset_reg2 = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LI, offset_reg2, offset); + } + if (!offset_reg2) + emitpcode(opcode, dest_reg, 0, offset_reg1); + else + emitpcode(opcode, dest_reg, offset_reg1, offset_reg2); + } else { + emitpcode(opcode, dest_reg, offset_reg1, obj, offset); + } +} diff --git a/compiler_and_linker/unsorted/RegisterInfo.c b/compiler_and_linker/unsorted/RegisterInfo.c new file mode 100644 index 0000000..c1e67d8 --- /dev/null +++ b/compiler_and_linker/unsorted/RegisterInfo.c @@ -0,0 +1,392 @@ +#include "compiler.h" +#include "compiler/CError.h" +#include "compiler/objects.h" +#include "compiler/PCode.h" + +short last_exception_register[RegClassMax]; +short first_fe_temporary_register[RegClassMax]; +short last_argument_register[RegClassMax]; +short _FP_; +short _CALLER_SP_; +char *special_register_names[RegClassMax][RegisterMax]; +static short used_regs_before_coloring; +static UInt8 save_state[RegisterMax]; + +char *XXspecial_register_names[RegClassMax * RegisterMax]; + +short spr_to_sysreg[4] = {1, 8, 9, 0x100}; + +void asm_used_register(char rclass, short reg) { + int i; + + if ((reg < n_real_registers[rclass]) && (reg_state[rclass][reg] == RegState0)) { + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) { + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + used_nonvolatile_registers[rclass]++; + } else { + for (i = used_nonvolatile_registers[rclass]; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) { + reg_state[rclass][reg] = RegState1; + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + } + } + } + } +} + +void retain_register(Object *obj, char rclass, short reg) { + VarInfo *vi; + +#line 95 + CError_ASSERT((short) reg < RegisterMax); + + if (reg_state[rclass][reg] == RegState0) { + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) + used_nonvolatile_registers[rclass]++; + } + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = rclass; + vi->flags |= VarInfoFlag2; + vi->reg = reg; + } +} + +void retain_GPR_pair(Object *obj, short reg, short regHi) { + VarInfo *vi; + + retain_register(NULL, RegClass_GPR, reg); + retain_register(NULL, RegClass_GPR, regHi); + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = RegClass_GPR; + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } +} + +int is_register_object(Object *obj) { + return obj->sclass == OBJECT_SCLASS_101; +} + +int GetABIFirstNonVolatile(char rclass) { + switch (rclass) { + case RegClass_SPR: return 3; + case RegClass_CRFIELD: return 2; + case RegClass_VR: return 20; + case RegClass_GPR: return 13; + case RegClass_FPR: return 14; + default: return -1; + } +} + +char GetRegisterClassName(char rclass) { + switch (rclass) { + case RegClass_VR: return 'v'; + case RegClass_GPR: return 'r'; + case RegClass_FPR: return 'f'; + default: +#line 242 + CError_FATAL(); + return '?'; + } +} + +static int first_nonvolatile_reg(char rclass) { + return GetABIFirstNonVolatile(rclass); +} + +void setup_diagnostic_reg_strings() { + register_class_name[RegClass_SPR] = "SPR"; + register_class_format[RegClass_SPR] = "spr%ld"; + register_class_name[RegClass_CRFIELD] = "CRFIELD"; + register_class_format[RegClass_CRFIELD] = "cr%ld"; + register_class_name[RegClass_VR] = "VR"; + register_class_format[RegClass_VR] = "vr%ld"; + register_class_name[RegClass_FPR] = "FPR"; + register_class_format[RegClass_FPR] = "f%ld"; + register_class_name[RegClass_GPR] = "GPR"; + register_class_format[RegClass_GPR] = "r%ld"; +} + +void init_target_registers() { + char rclass; + int reg; + int end; + int tmp; + + static int last_nonvolatile_reg[] = {3, 5, 31, 31, 31}; + static int nonvol_reserve[] = {0, 0, 0, 4, 3}; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (reg = 0; reg < RegisterMax; reg++) + special_register_names[(char)rclass][reg] = NULL; + } + + special_register_names[RegClass_SPR][0] = "XER"; + special_register_names[RegClass_SPR][1] = "LR"; + special_register_names[RegClass_SPR][2] = "CTR"; + special_register_names[RegClass_SPR][3] = "VRSAVE"; + special_register_names[RegClass_GPR][1] = "SP"; + + setup_diagnostic_reg_strings(); + n_real_registers[RegClass_SPR] = 4; + n_real_registers[RegClass_CRFIELD] = 8; + n_real_registers[RegClass_VR] = 32; + n_real_registers[RegClass_FPR] = 32; + n_real_registers[RegClass_GPR] = 32; + reg_state[RegClass_GPR][1] = RegState2; + reg_state[RegClass_GPR][2] = RegState2; + reg_state[RegClass_CRFIELD][5] = RegState2; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + n_nonvolatile_registers[(char)rclass] = 0; + if (last_nonvolatile_reg[(char)rclass] >= 0) { + end = first_nonvolatile_reg(rclass); + for (reg = last_nonvolatile_reg[(char)rclass]; reg >= end; reg--) { + if (reg_state[(char)rclass][reg] == RegState0) { + tmp = n_nonvolatile_registers[(char)rclass]++; + nonvolatile_registers[(char)rclass][tmp] = reg; + } + } + } + + assignable_registers[(char)rclass] = n_nonvolatile_registers[(char)rclass] - nonvol_reserve[(char)rclass]; + if (assignable_registers[(char)rclass] < 0) + assignable_registers[(char)rclass] = 0; + + n_scratch_registers[(char)rclass] = 0; + for (reg = 0; reg < n_real_registers[(char)rclass]; reg++) { + if (reg < GetABIFirstNonVolatile(rclass) || reg > last_nonvolatile_reg[(char)rclass]) { + if (reg_state[(char)rclass][reg] == RegState0) { + tmp = n_scratch_registers[(char)rclass]++; + scratch_registers[(char)rclass][tmp] = reg; + } + } + } + } + + _FP_ = -1; + _CALLER_SP_ = -1; + optimizing = (copts.optimizationlevel > 0) && !disable_optimizer; +} + +void assign_register_by_type(Object *obj) { + VarInfo *vi; + Type *ty; + Boolean flag; + + ty = obj->type; + vi = Registers_GetVarInfo(obj); + flag = 0; + vi->rclass = RegClassMax; + vi->reg = 0; + vi->regHi = 0; + + if ((ty->type == TYPEINT) || (ty->type == TYPEENUM) || ((ty->type == TYPEPOINTER || ty->type == TYPEARRAY) && (ty->type != TYPEARRAY)) || ((ty->type == TYPEMEMBERPOINTER) && (ty->size == 4U))) { + if (((ty->type == TYPEINT) || (ty->type == TYPEENUM)) && (ty->size == 8)) + flag = 1; + vi->rclass = RegClass_GPR; + } else if (ty->type == TYPEFLOAT) { + vi->rclass = RegClass_FPR; + } else if ((ty->type == TYPESTRUCT) && (TYPE_STRUCT(ty)->stype >= STRUCT_TYPE_4) && (TYPE_STRUCT(ty)->stype <= STRUCT_TYPE_E)) { + vi->rclass = RegClass_VR; + } else { + return; + } + + if (vi->rclass < RegClassMax) { + if (flag) { +#line 520 + CError_ASSERT(vi->rclass == RegClass_GPR); + if (assignable_registers[vi->rclass] > 1) + assign_GPR_pair(obj); + } else { + if (assignable_registers[vi->rclass] > 0) + assign_register_to_variable(obj, vi->rclass); + } + } +} + +void assign_GPR_pair(Object *obj) { + VarInfo *vi; + short reg; + short regHi; + + vi = Registers_GetVarInfo(obj); + if (optimizing) { + reg = used_virtual_registers[RegClass_GPR]++; + regHi = used_virtual_registers[RegClass_GPR]++; + } else { +#line 554 + CError_ASSERT(assignable_registers[RegClass_GPR] >= 2); + reg = obtain_nonvolatile_register(RegClass_GPR); + regHi = obtain_nonvolatile_register(RegClass_GPR); + retain_GPR_pair(obj, reg, regHi); + } + + vi->rclass = RegClass_GPR; + if (reg > 0 && regHi > 0) { + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } else { +#line 567 + CError_FATAL(); + } +} + +void open_fe_temp_registers() { + int r; + + r = used_virtual_registers[RegClass_GPR]; + first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = r; + r = used_virtual_registers[RegClass_FPR]; + first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = r; + r = used_virtual_registers[RegClass_VR]; + first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = r; + //first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR]; + //first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR]; + //first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = used_virtual_registers[RegClass_VR]; +} + +void set_last_exception_registers() { + last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1; + last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1; + last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1; +} + +static VarInfo *Registers_GetNewVarInfo() { + VarInfo *vi = galloc(sizeof(VarInfo)); + memclrw(vi, sizeof(VarInfo)); + return vi; +} + +VarInfo *Registers_GetVarInfo(Object *obj) { + switch (obj->datatype) { + case DDATA: + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + case DNONLAZYPTR: + // not sure if this is the right union + if (!obj->u.toc.info) { +#line 639 + CError_FATAL(); + obj->u.toc.info = CodeGen_GetNewVarInfo(); + } + return obj->u.toc.info; + case DLOCAL: + if (!obj->u.var.info) { +#line 647 + CError_FATAL(); + } + return obj->u.var.info; + case DABSOLUTE: + // not sure if this is the right union + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + default: +#line 660 + CError_FATAL(); + return NULL; + } +} + +int used_vrstate_VRs() { + int count = 0; + int i; + for (i = 0; i < RegisterMax; i++) { + if (reg_state[RegClass_VR][i]) + count++; + } + return count; +} + +UInt32 colored_vrs_as_vrsave(PCodeBlock *block) { + PCode *pc; + UInt32 mask; + int i; + + mask = 0; + if (copts.x1B == 2) + return 0xFFFFFFFF; + if (copts.x1B == 0) + return 0; + + while (block) { + for (pc = block->firstPCode; pc; pc = pc->nextPCode) { + if (pc->flags & (fPCodeFlag40000000 | fPCodeFlag80000000)) { + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_REGISTER && pc->args[i].arg == RegClass_VR) + mask |= 1 << (31 - pc->args[i].data.reg.reg); + } + } + } + block = block->nextBlock; + } + + return mask; +} + +void save_before_coloring_nonvolatile_registers(char rclass) { + used_regs_before_coloring = used_nonvolatile_registers[rclass]; + memcpy(save_state, reg_state[rclass], sizeof(save_state)); +} + +void reset_nonvolatile_registers(char rclass) { + used_nonvolatile_registers[rclass] = used_regs_before_coloring; + memcpy(reg_state[rclass], save_state, sizeof(save_state)); +} + +int is_nonvolatile_register(char rclass, int reg) { + int i; + + for (i = 0; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) + return 1; + } + + return 0; +} + +void init_endian() { + if (copts.little_endian) { + high_offset = 4; + low_offset = 0; + high_reg = 4; + low_reg = 3; + high_reg2 = 6; + low_reg2 = 5; + } else { + high_offset = 0; + low_offset = 4; + high_reg = 3; + low_reg = 4; + high_reg2 = 5; + low_reg2 = 6; + } +} + +void update_asm_nonvolatile_registers() { + char rclass; + int r31; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (r31 = n_nonvolatile_registers[rclass] - 1; r31 >= 0; r31--) { + if (reg_state[rclass][nonvolatile_registers[rclass][r31]] == RegState1) + break; + } + if (r31 > used_nonvolatile_registers[rclass]) + used_nonvolatile_registers[rclass] = r31; + } +} diff --git a/compiler_and_linker/unsorted/Registers.c b/compiler_and_linker/unsorted/Registers.c new file mode 100644 index 0000000..9bcbf05 --- /dev/null +++ b/compiler_and_linker/unsorted/Registers.c @@ -0,0 +1,225 @@ +#include "compiler.h" +#include "compiler/objects.h" +#include "compiler/PCode.h" + +// haven't checked this object file for .data stuff yet + +// ONLY FOR TESTING +// this file gets kinda fucked up by the loop unroller +//#pragma opt_unroll_loops off + +int used_virtual_registers[RegClassMax]; +int used_nonvolatile_registers[RegClassMax]; +int assignable_registers[RegClassMax]; +int n_real_registers[RegClassMax]; +int n_scratch_registers[RegClassMax]; +int scratch_registers[RegClassMax][RegisterMax]; +int n_nonvolatile_registers[RegClassMax]; +int nonvolatile_registers[RegClassMax][RegisterMax]; +UInt8 reg_state[RegClassMax][RegisterMax]; +int first_temporary_register[RegClassMax]; +int last_temporary_register[RegClassMax]; +char *register_class_name[RegClassMax]; +char *register_class_format[RegClassMax]; +int coloring; +int optimizing; +typedef struct ModifiedRegisters { + struct ModifiedRegisters *next; + Object *obj; + UInt32 mask[RegClassMax]; +} ModifiedRegisters; +static ModifiedRegisters *mod_regs_table[128]; + +void init_registers() { + char rclass; + int j; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (j = 0; j < RegisterMax; j++) { + reg_state[(char)rclass][j] = RegState0; + } + } + + for (rclass = 0; rclass < RegClassMax; rclass++) + used_nonvolatile_registers[(char)rclass] = 0; + + optimizing = 1; + + init_target_registers(); + for (rclass = 0; rclass < RegClassMax; rclass++) + used_virtual_registers[(char)rclass] = n_real_registers[(char)rclass]; + + coloring = 1; +} + +void assign_register_to_variable(Object *obj, char rclass) { + VarInfo *vi; + short reg; + + vi = Registers_GetVarInfo(obj); + if (optimizing) { + reg = used_virtual_registers[rclass]++; + } else { + reg = obtain_nonvolatile_register(rclass); + retain_register(obj, rclass, reg); + } + + vi->flags |= VarInfoFlag2; + vi->rclass = rclass; + vi->reg = reg; +} + +void retain_register_for_argument(Object *obj, char rclass, short reg) { + VarInfo *vi = obj->u.var.info; + reg_state[rclass][reg] = RegState1; + vi->flags |= VarInfoFlag2; + vi->rclass = rclass; + vi->reg = reg; +} + +int available_registers(char rclass) { + int i; + int count = 0; + + for (i = 0; i < n_real_registers[rclass]; i++) { + if (reg_state[rclass][i] == RegState0) + count++; + } + + return count; +} + +UInt32 volatile_registers(char rclass) { + UInt32 mask = 0; + int i; + int reg; + + for (i = 0; i < n_scratch_registers[rclass]; i++) { + reg = scratch_registers[rclass][i]; + if (reg_state[rclass][reg] == RegState0) + mask |= 1 << reg; + } + + return mask; +} + +short obtain_nonvolatile_register(char rclass) { + int best = -1; + + while (used_nonvolatile_registers[rclass] < n_nonvolatile_registers[rclass]) { + int tmp = nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]++]; + if (reg_state[rclass][tmp] == RegState0) { + best = tmp; + break; + } + } + + return best; +} + +void open_temp_registers() { + int rclass; + + for (rclass = 0; (char)rclass < RegClassMax; rclass++) { + int r = used_virtual_registers[(char)rclass]; + //last_temporary_register[rclass] = r; + //first_temporary_register[rclass] = r; + first_temporary_register[(char)rclass] = last_temporary_register[(char)rclass] = r; + } + /*rclass = 0; + while (rclass < RegClassMax) { + r = used_virtual_registers[(char)rclass]; + last_temporary_register[(char)rclass] = r; + first_temporary_register[(char)rclass] = r; + rclass = rclass + 1; + }*/ +} + +void check_temp_registers() { + char rclass; + + if (!optimizing) { + for (rclass = 0; rclass < RegClassMax; rclass++) { + if (used_virtual_registers[(char)rclass] > last_temporary_register[(char)rclass]) + last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass]; + if (used_virtual_registers[(char)rclass] > 256) + used_virtual_registers[(char)rclass] = first_temporary_register[(char)rclass]; + } + } +} + +void close_temp_registers() { + char rclass; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + if (used_virtual_registers[(char)rclass] < last_temporary_register[(char)rclass]) + used_virtual_registers[(char)rclass] = last_temporary_register[(char)rclass]; + else + last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass]; + } +} + +int count_scratch_registers() { + int rclass; + int count; + + count = 0; + for (rclass = 0; (char)rclass < RegClassMax; rclass++) + count += n_scratch_registers[(char)rclass]; + return count; +} + +void init_modified_registers() { + int i = 0; + + for (i = 0; i < 128; i++) + mod_regs_table[i] = NULL; +} + +static void compute_modified_registers(UInt32 *masks) { + int rclass; + PCodeBlock *block; + PCode *pcode; + int i; + + for (rclass = 0; rclass < RegClassMax; rclass++) + masks[(char)rclass] = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + for (i = 0; i < pcode->argCount; i++) { + if (pcode->args[i].kind == PCOp_REGISTER && pcode->args[i].data.reg.effect & EffectWrite) + masks[pcode->args[i].arg] |= 1 << pcode->args[i].data.reg.reg; + } + } + } +} + +void note_modified_registers(Object *obj) { + ModifiedRegisters *mr; + + mr = galloc(sizeof(ModifiedRegisters)); + mr->obj = obj; + compute_modified_registers(mr->mask); + mr->next = mod_regs_table[obj->name->hashval]; + mod_regs_table[obj->name->hashval] = mr; +} + +void find_modified_registers(Object *obj, UInt32 *masks) { + char rclass; + ModifiedRegisters *scan; + + for (rclass = 0; rclass < RegClassMax; rclass++) + masks[(char)rclass] = 0xFFFFFFFF; + + if (CParser_HasInternalLinkage(obj)) { + for (scan = mod_regs_table[obj->name->hashval]; scan; scan = scan->next) { + if (scan->obj == obj) + break; + } + if (scan) { + for (rclass = 0; rclass < RegClassMax; rclass++) + masks[(char)rclass] = scan->mask[(char)rclass]; + } + } +} diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c new file mode 100644 index 0000000..5789cb5 --- /dev/null +++ b/compiler_and_linker/unsorted/StackFrame.c @@ -0,0 +1,1265 @@ +#include "compiler/StackFrame.h" +#include "compiler/CError.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/objects.h" +#include "compiler.h" + +#define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) ) +#define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) ) + +Boolean requires_frame; +Boolean makes_call; +Boolean uses_globals; +Boolean dynamic_stack; +Boolean large_stack; +static SInt32 out_param_alignment; +static SInt32 in_parameter_size; +static SInt32 in_param_alignment; +static SInt32 frame_alignment; +static SInt32 alloca_alignment; +static SInt32 linkage_area_size; +static SInt32 parameter_area_size; +static SInt32 parameter_area_size_estimate; +static SInt32 local_data_size; +static SInt32 local_data_limit; +static SInt32 large_data_near_size; +static SInt32 large_data_far_size; +static ObjectList *local_objects[ObjClassMax]; +static ObjectList *local_objects_tail[ObjClassMax]; +static SInt32 non_volatile_save_offset[RegClassMax]; +static SInt32 VRSAVE_save_offset; +static SInt32 LR_save_offset; +static SInt32 nonvolatile_save_size; +static UInt32 vrsave_mask; +static SInt32 frame_size; +static SInt32 frame_size_estimate; +static SInt32 genuine_frame_size; +static Object *dummylocal; +static Boolean dynamic_align_stack; +static Boolean has_varargs; +static Boolean compressing_data_area; +static PCode *setup_caller_sp; +static PCode *align_instr1; +static PCode *align_instr2; +static short vrsave_register; +static PCode *loadvrsave; +static PCode *storevrsave; +Object *dummyvaparam; +void *dummyprofiler; + +// forward declarations +static void insert_local_object(UInt8 oclass, Object *obj); +static void compress_data_area(void); +static UInt32 align_bits(UInt32 value, UInt8 bitcount); +static Boolean use_helper_function(char rclass); +static Boolean need_link_register(void); +static void call_helper_function(char *name, char rclass, short effect); +static void save_nonvolatile_FPRs(int reg, SInt32 offset); +static void save_nonvolatile_VRs(int reg, SInt32 offset); +static void restore_nonvolatile_FPRs(int reg, SInt32 offset); +static void restore_nonvolatile_VRs(int reg, SInt32 offset); +static void save_nonvolatile_GPRs(int reg, SInt32 offset); +static void restore_nonvolatile_GPRs(int reg, SInt32 offset); +static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size); + +void init_stack_globals(void) { + char rclass; + UInt8 oclass; + + requires_frame = 0; + makes_call = 0; + uses_globals = 0; + dynamic_stack = 0; + large_stack = 0; + vrsave_register = -1; + dynamic_align_stack = 0; + compressing_data_area = 0; + align_instr1 = NULL; + align_instr2 = NULL; + setup_caller_sp = NULL; + dummyvaparam = NULL; + loadvrsave = NULL; + storevrsave = NULL; + local_data_size = 0; + local_data_limit = 0x2000; + large_data_near_size = 0; + large_data_far_size = 0; + frame_size_estimate = 0; + in_parameter_size = 0; + parameter_area_size = 0; + parameter_area_size_estimate = 0; + frame_alignment = 8; + out_param_alignment = 8; + in_param_alignment = 8; + alloca_alignment = 0; + has_varargs = 0; + linkage_area_size = 0; + frame_size = 0; + genuine_frame_size = 0; + nonvolatile_save_size = -1; + VRSAVE_save_offset = -1; + LR_save_offset = -1; + + for (rclass = 0; rclass < RegClassMax; rclass++) + non_volatile_save_offset[(char) rclass] = -1; + + dummyprofiler = NULL; + dummyvaparam = NULL; + dummylocal = NULL; + + for (oclass = 0; oclass < ObjClassMax; oclass++) { + local_objects[oclass] = NULL; + local_objects_tail[oclass] = NULL; + } +} + +void init_frame_sizes(void) { + ObjectList *scan; + Object *obj; + SInt32 r30; + SInt32 align; + SInt32 mask; + + r30 = in_parameter_size + parameter_area_size_estimate; + frame_size_estimate = r30 + 2484; + for (scan = locals; scan; scan = scan->next) { + obj = scan->object; + { + align = CMach_AllocationAlignment(obj->type, obj->qual) - 1; + mask = ~align; + } + frame_size_estimate = (frame_size_estimate + align) & mask; + frame_size_estimate += obj->type->size; + } + + if (frame_size_estimate > 0x8000) { + dynamic_stack = 1; + large_stack = 1; + requires_frame = 1; + } + + local_data_limit = 0x8000 - (r30 + 2484); + + if (dynamic_stack) { + requires_frame = 1; + dummylocal = galloc(sizeof(Object)); + memclrw(dummylocal, sizeof(Object)); + dummylocal->type = (Type *) &stvoid; + dummylocal->otype = OT_OBJECT; + dummylocal->name = GetHashNameNode("<dummy>"); + dummylocal->datatype = DLOCAL; + dummylocal->u.var.info = CodeGen_GetNewVarInfo(); + dummylocal->u.var.info->flags |= VarInfoFlag80; + dummylocal->u.var.info->noregister = 1; + } + + if (dynamic_stack) { + retain_register(NULL, RegClass_GPR, 31); + _FP_ = 31; + } else { + _FP_ = 1; + } +} + +void assign_local_memory(Object *obj) { + // some misassigned registers x.x + short align; + VarInfo *vi; + + align = CMach_AllocationAlignment(obj->type, obj->qual); + if (!compressing_data_area && (obj->u.var.info->flags & VarInfoFlag80)) + return; + + update_frame_align(align); + if (local_data_size + (ALIGN_REMAINDER(local_data_size, align) + ALIGN(obj->type->size, align)) < local_data_limit) { + local_data_size = ALIGN(local_data_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = local_data_size; + local_data_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass0, obj); + return; + } + if (compressing_data_area || obj->type->size <= 32) { + large_data_near_size = ALIGN(large_data_near_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = 0x8000 + large_data_near_size; + large_data_near_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass1, obj); + } else { + large_data_far_size = ALIGN(large_data_far_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = 0x10000 + large_data_far_size; + large_data_far_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass2, obj); + } +} + +void assign_locals_to_memory(ObjectList *first) { + ObjectList *list; + Object *obj; + SInt32 i; + + for (i = 1; i < 1024; i <<= 1) { + for (list = first; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) { + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { + if (obj->type->size <= i) + assign_local_memory(obj); + } + } + } + } + + for (list = first; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) { + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { + assign_local_memory(list->object); + } + } + + if (obj->type && IS_TYPE_ARRAY(obj->type) && IS_TYPE_VECTOR(TYPE_POINTER(obj->type)->target)) + has_altivec_arrays = 1; + } +} + +void compute_frame_sizes(void) { + SInt32 altivec_size; + SInt32 altivec_offset; + +#line 897 + CError_ASSERT(alloca_alignment == 0 || alloca_alignment == frame_alignment); + + update_asm_nonvolatile_registers(); + LR_save_offset = 8; + non_volatile_save_offset[RegClass_FPR] = -(used_nonvolatile_registers[RegClass_FPR] * 8); + non_volatile_save_offset[RegClass_GPR] = -(((15 - non_volatile_save_offset[RegClass_FPR]) & ~15) + used_nonvolatile_registers[RegClass_GPR] * 4); + nonvolatile_save_size = -non_volatile_save_offset[RegClass_GPR]; + non_volatile_save_offset[RegClass_CRFIELD] = 4; + VRSAVE_save_offset = -1; + non_volatile_save_offset[RegClass_VR] = -1; + + if (copts.altivec_model) { + if (vrsave_mask) { + VRSAVE_save_offset = non_volatile_save_offset[RegClass_GPR] - 4; + nonvolatile_save_size = nonvolatile_save_size + 4; + } + altivec_size = used_nonvolatile_registers[RegClass_VR] * 16; + if (altivec_size > 0) + nonvolatile_save_size = ALIGN(nonvolatile_save_size + altivec_size, frame_alignment); + } + + if (parameter_area_size) + requires_frame = 1; + + compress_data_area(); + local_data_size = ALIGN(local_data_size, frame_alignment); + nonvolatile_save_size = ALIGN(nonvolatile_save_size, frame_alignment); + if (!requires_frame && (local_data_size + nonvolatile_save_size) <= 224) { +#line 1005 + CError_ASSERT(!dynamic_align_stack); + linkage_area_size = 0; + frame_size = 0; + genuine_frame_size = local_data_size + nonvolatile_save_size; + } else { + requires_frame = 1; + if (parameter_area_size < 32) + parameter_area_size = 32; + parameter_area_size = ALIGN(parameter_area_size + 24, frame_alignment) - 24; + if (large_stack) { +#line 1019 + CError_ASSERT(!large_data_far_size); + large_data_near_size += parameter_area_size; + parameter_area_size = 0; + } + linkage_area_size = 24; + frame_size = nonvolatile_save_size + (altivec_offset = parameter_area_size + 24 + local_data_size); + if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) + non_volatile_save_offset[RegClass_VR] = altivec_offset; + frame_size += ALIGN_REMAINDER(frame_size, 16); + frame_size = ALIGN(frame_size, frame_alignment); + genuine_frame_size = frame_size; + } + if (!large_stack && frame_size > 0x7FFF) + CError_ErrorTerm(210); +} + +static void allocate_new_frame(int reg1, int reg2) { + if (dynamic_align_stack) { +#line 1116 + CError_ASSERT(reg1 != _CALLER_SP_); + emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31); + if (frame_size > 0x7FFF) { +#line 1122 + CError_FATAL(); + return; + } + + if (frame_size) + emitpcode(PC_SUBFIC, reg1, reg1, -frame_size); + else + emitpcode(PC_SUBFIC, reg1, reg1, -genuine_frame_size); + + if (reg2) + emitpcode(PC_MR, reg2, 1); + + emitpcode(PC_STWUX, 1, 1, reg1); + } else { + if (frame_size > 0x7FFF) { +#line 1153 + CError_FATAL(); + } else { + emitpcode(PC_STWU, 1, 1, 0, -frame_size); + } + + if (reg2) + emitpcode(PC_MR, reg2, 1); + } +} + +void generate_prologue(PCodeBlock *block) { + PCodeBlock *save_block; + Boolean needs_lr; + Statement *save_statement; + Statement stmt; + UInt32 vrsave_low; + UInt32 vrsave_high; + + save_block = pclastblock; + needs_lr = need_link_register(); + save_statement = current_statement; + stmt.sourceoffset = functionbodyoffset; + current_statement = &stmt; + pclastblock = block; + + if (setup_caller_sp && setup_caller_sp->block) { + if ( + setup_caller_sp->op == PC_MR && + setup_caller_sp->args[1].kind == PCOp_REGISTER && + setup_caller_sp->args[1].arg == RegClass_GPR && + setup_caller_sp->args[1].data.reg.reg == _FP_ + ) { +#line 1197 + CError_FATAL(); + } + _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg; + deletepcode(setup_caller_sp); + setup_caller_sp = NULL; + } else if (_CALLER_SP_ != _FP_) { + _CALLER_SP_ = -1; + } + + if (align_instr1 && align_instr1->block) { + deletepcode(align_instr1); + align_instr1 = NULL; + } + + if (align_instr2 && align_instr2->block) { + deletepcode(align_instr2); + align_instr2 = NULL; + } + + if (loadvrsave && loadvrsave->block) { + deletepcode(loadvrsave); + loadvrsave = NULL; + } + + if (storevrsave && storevrsave->block) { + deletepcode(storevrsave); + storevrsave = NULL; + } + + if (needs_lr) + emitpcode(PC_MFLR, 0); + + if (used_nonvolatile_registers[RegClass_CRFIELD]) { + emitpcode(PC_MFCR, 12); + emitpcode(PC_STW, 12, 1, 0, non_volatile_save_offset[RegClass_CRFIELD]); + } + + if (used_nonvolatile_registers[RegClass_FPR]) + save_nonvolatile_FPRs(1, 0); + if (used_nonvolatile_registers[RegClass_GPR]) + save_nonvolatile_GPRs(1, 0); + if (needs_lr) + emitpcode(PC_STW, 0, 1, 0, 8); + + if (frame_size) { + if (vrsave_mask) { + emitpcode(PC_MFSPR, 0, 256); + emitpcode(PC_STW, 0, 1, 0, VRSAVE_save_offset); + vrsave_register = 0; + } + allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0); + } else { +#line 1326 + CError_ASSERT(!dynamic_align_stack); + if (vrsave_mask) + emitpcode(PC_MFSPR, vrsave_register, 256); + } + + if (vrsave_mask) { + vrsave_high = vrsave_mask >> 16; + vrsave_low = vrsave_mask & 0xFFFF; + if (vrsave_mask == 0xFFFFFFFF) { + emitpcode(PC_LI, 0, -1); + } else { + if (vrsave_high) + emitpcode(PC_ORIS, 0, vrsave_register, vrsave_high); + if (vrsave_low) + emitpcode(PC_ORI, 0, 0, vrsave_low); + } + emitpcode(PC_MTSPR, 256, 0); + } + + if (used_nonvolatile_registers[RegClass_VR]) + save_nonvolatile_VRs(1, 0); + + if (dynamic_stack) + emitpcode(PC_MR, 31, 1); + + if (large_stack) + do_allocate_dynamic_stack_space(1, 11, 0, large_data_near_size); + + block->flags |= fPCBlockFlag1; + pclastblock = save_block; + current_statement = save_statement; +} + +void generate_epilogue(PCodeBlock *block, Boolean add_blr) { + PCodeBlock *save_block; + Boolean needs_lr; + Statement *save_statement; + Statement stmt; + + save_block = pclastblock; + needs_lr = need_link_register(); + save_statement = current_statement; + if (!save_statement) { + stmt.sourceoffset = current_linenumber; + current_statement = &stmt; + } + pclastblock = block; + + if (used_nonvolatile_registers[RegClass_VR]) + restore_nonvolatile_VRs(_FP_, 0); + + if (dynamic_align_stack) { + load_store_register(PC_LWZ, 1, 1, NULL, 0); + setpcodeflags(fSideEffects); + if (needs_lr) + load_store_register(PC_LWZ, 0, 1, 0, 8); + } else { + if (needs_lr) + load_store_register(PC_LWZ, 0, _FP_, 0, frame_size + 8); + if (frame_size > 0) { + if (dynamic_stack) { + load_store_register(PC_LWZ, 1, 1, 0, 0); + setpcodeflags(fSideEffects); + } else { + emitpcode(PC_ADDI, 1, 1, 0, frame_size); + setpcodeflags(fSideEffects); + } + } + } + + if (used_nonvolatile_registers[RegClass_CRFIELD]) { + load_store_register(PC_LWZ, 12, 1, NULL, non_volatile_save_offset[RegClass_CRFIELD]); + emitpcode(PC_MTCRF, 255, 12); + } + + if (vrsave_mask) { + if (!requires_frame) { + emitpcode(PC_MTSPR, 256, vrsave_register); + } else { + emitpcode(PC_LWZ, 11, 1, 0, VRSAVE_save_offset); + emitpcode(PC_MTSPR, 256, 11); + } + } + + if (used_nonvolatile_registers[RegClass_FPR]) + restore_nonvolatile_FPRs(1, 0); + if (needs_lr && !use_helper_function(RegClass_GPR)) + emitpcode(PC_MTLR, 0); + + if (used_nonvolatile_registers[RegClass_GPR]) + restore_nonvolatile_GPRs(1, 0); + if (needs_lr && use_helper_function(RegClass_GPR)) + emitpcode(PC_MTLR, 0); + + if (add_blr) { + emitpcode(PC_BLR); + setpcodeflags(fIsVolatile); + } + + block->flags |= fPCBlockFlag2; + pclastblock = save_block; + current_statement = save_statement; +} + +static void load_base_offset(int dest_reg, int base_reg, SInt32 offset) { + if (offset) + emitpcode(PC_ADDI, dest_reg, base_reg, 0, offset); + else + emitpcode(PC_MR, dest_reg, base_reg); +} + +static void save_nonvolatile_FPRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_FPR]; + + if (!use_helper_function(RegClass_FPR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { + emitpcode(PC_STFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); + call_helper_function("__save_fpr_%d", RegClass_FPR, EffectRead); + } +} + +static void save_nonvolatile_VRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_VR]; + + if (!use_helper_function(RegClass_VR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { + emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); + emitpcode(PC_STVX, 32 - i, reg, 0); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); + call_helper_function("__savev%d", RegClass_VR, EffectRead); + } +} + +static void restore_nonvolatile_FPRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_FPR]; + + if (!use_helper_function(RegClass_FPR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { + load_store_register(PC_LFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); + call_helper_function("__restore_fpr_%d", RegClass_FPR, EffectWrite); + } +} + +static void restore_nonvolatile_VRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_VR]; + + if (!use_helper_function(RegClass_VR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { + emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); + setpcodeflags(fIsVolatile); + emitpcode(PC_LVX, 32 - i, reg, 0); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); + call_helper_function("__restv%d", RegClass_VR, EffectWrite); + } +} + +static void save_nonvolatile_GPRs(int reg, SInt32 offset) { + int i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_GPR]; + + if (!use_helper_function(RegClass_GPR)) { + if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { + emitpcode(PC_STMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); + } else { + for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { + emitpcode(PC_STW, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); + } + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); + call_helper_function("__savegpr_%d", RegClass_GPR, EffectRead); + } +} + +static void restore_nonvolatile_GPRs(int reg, SInt32 offset) { + int i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_GPR]; + + if (!use_helper_function(RegClass_GPR)) { + if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { + emitpcode(PC_LMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); + setpcodeflags(fIsVolatile); + } else { + for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { + emitpcode(PC_LWZ, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); + setpcodeflags(fIsVolatile); + } + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); + call_helper_function("__restgpr_%d", RegClass_GPR, EffectWrite); + } +} + +static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) { + load_store_register(PC_LWZ, reg2, 1, NULL, 0); + if (flag1) { + size = ALIGN(size, frame_alignment); + if (size < 0x8000) { + emitpcode(PC_STWU, reg2, 1, 0, -size); + } else { + emitpcode(PC_LIS, reg1, 0, (short) HIGH_PART(-size)); + if (-size) + emitpcode(PC_ADDI, reg1, reg1, 0, LOW_PART(-size)); + emitpcode(PC_STWUX, reg2, 1, reg1); + setpcodeflags(fIsVolatile | fSideEffects); + } + } else { + emitpcode(PC_STWUX, reg2, 1, reg1); + setpcodeflags(fIsVolatile | fSideEffects); + } +} + +void allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) { + if (copts.altivec_model) + update_frame_align(16); + do_allocate_dynamic_stack_space(flag1, reg1, reg2, size); + add_immediate(reg1, 1, dummylocal, 0); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct Traceback { + UInt8 x0; + UInt8 x1; + UInt8 x2; + UInt8 x3; + UInt8 x4; + UInt8 x5; + + UInt8 x6_0 : 2; + UInt8 x6_1 : 1; // set to 1 + UInt8 x6_2 : 5; + + UInt8 x7_0 : 1; + UInt8 x7_1 : 1; // set to 1 + UInt8 has_dynamic_stack : 1; // set to 1 if dynamic_stack + UInt8 x7_3 : 3; + UInt8 uses_CRs : 1; // set to 1 if CRs used + UInt8 needs_link_register : 1; // set to 1 if link register used + + UInt8 has_frame_size : 1; // set to 1 if frame_size is nonzero + UInt8 x8_1 : 1; // set to 0 + UInt8 used_FPRs : 6; // stores non-volatile FPRs used + + UInt8 x9_0 : 1; // set to 0 + UInt8 x9_1 : 1; // set to 1 if VRs or vrsave used + UInt8 used_GPRs : 6; // stores non-volatile GPRs used + + UInt8 xA; + UInt8 xB; + + SInt32 funcsize; + SInt16 namelen; + char name[0]; +} Traceback; + +typedef struct TracebackExtra { + UInt8 used_VRs : 6; + UInt8 has_vrsave_mask : 1; + UInt8 is_varargs : 1; + UInt8 vec_arg_count : 7; + UInt8 has_vrsave_mask_or_used_VRs : 1; +} TracebackExtra; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func) { + char *work; + short namelen; + Traceback *buf; + SInt32 bufsize; + + namelen = strlen(funcname); + bufsize = ALIGN(sizeof(Traceback) + namelen + (dynamic_stack ? 1 : 0) + ((used_nonvolatile_registers[RegClass_VR] || vrsave_mask) ? sizeof(TracebackExtra) : 0), 4); + buf = lalloc(bufsize); + memclrw(buf, bufsize); + + buf->x4 = 0; + buf->x5 = copts.cplusplus ? 9 : 0; + buf->x6_1 = 1; + buf->x7_1 = 1; + if (dynamic_stack) + buf->has_dynamic_stack = 1; + if (used_nonvolatile_registers[RegClass_CRFIELD]) + buf->uses_CRs = 1; + if (need_link_register()) + buf->needs_link_register = 1; + if (frame_size) + buf->has_frame_size = 1; + buf->used_FPRs = used_nonvolatile_registers[RegClass_FPR]; + buf->used_GPRs = used_nonvolatile_registers[RegClass_GPR]; + buf->x8_1 = 0; + buf->x9_0 = 0; + buf->x9_1 = (used_nonvolatile_registers[RegClass_VR] || vrsave_mask) != 0; + buf->funcsize = funcsize; + buf->namelen = namelen; + + work = buf->name; + strcpy(work, funcname); + work += namelen; + if (dynamic_stack) { + *(work++) = 31; + } + + if (vrsave_mask || used_nonvolatile_registers[RegClass_VR]) { + TracebackExtra *extra; + Boolean is_varargs; + int vec_count; + FuncArg *args, *scan; + Type *type; + + extra = (TracebackExtra *) work; + vec_count = 0; + args = TYPE_FUNC(func->type)->args; + scan = args; + while (scan && scan != &elipsis) + scan = scan->next; + is_varargs = scan == &elipsis; + while (args) { + if ((type = args->type) && IS_TYPE_VECTOR(type)) + vec_count++; + args = args->next; + } + extra->used_VRs = used_nonvolatile_registers[RegClass_VR]; + extra->has_vrsave_mask = vrsave_mask != 0; + extra->is_varargs = is_varargs; + extra->vec_arg_count = vec_count; + extra->has_vrsave_mask_or_used_VRs = vrsave_mask || used_nonvolatile_registers[RegClass_VR]; + } + + *tbsize = bufsize; + return (char *) buf; +} + +static SInt32 localsbase(void) { + SInt32 size = parameter_area_size; + if (frame_size || dynamic_align_stack) + size += linkage_area_size; + else + size -= genuine_frame_size; + return size; +} + +static SInt32 parametersbase(int flag) { + if (flag) + return 24; + + return frame_size ? (genuine_frame_size + 24) : 24; +} + +void check_dynamic_aligned_frame(void) { + PCode *pc; + + if (used_nonvolatile_registers[RegClass_VR]) { + update_frame_align(16); + requires_frame = 1; + } + + if (frame_alignment > in_param_alignment) { + dynamic_align_stack = 1; + requires_frame = 1; +#line 2091 + CError_ASSERT(!has_varargs || _CALLER_SP_ != -1); +#line 2096 + CError_ASSERT(_CALLER_SP_ != _FP_); + if (setup_caller_sp && setup_caller_sp->block) { + align_instr1 = makepcode(PC_RLWINM, 12, 1, 0, 5, 31); + insertpcodebefore(setup_caller_sp, align_instr1); + align_instr2 = makepcode(PC_STWUX, 1, 1, 12); + insertpcodeafter(setup_caller_sp, align_instr2); + } + } else { + dynamic_align_stack = 0; + if (setup_caller_sp && setup_caller_sp->block) { + pc = makepcode(PC_MR, _CALLER_SP_, _FP_); + insertpcodebefore(setup_caller_sp, pc); + deletepcode(setup_caller_sp); + setup_caller_sp = pc; + } + _CALLER_SP_ = _FP_; + } + + vrsave_mask = 0; + if (copts.altivec_model) { + vrsave_mask = colored_vrs_as_vrsave(pcbasicblocks); + if (!requires_frame && vrsave_mask) { + vrsave_register = 11; + loadvrsave = makepcode(PC_LWZ, 11, 1, 0, -4); + appendpcode(prologue, loadvrsave); + storevrsave = makepcode(PC_STW, 11, 1, 0, -4); + appendpcode(epilogue, storevrsave); + } + } +} + +void move_varargs_to_memory(void) { + short reg; + + has_varargs = 1; + dummyvaparam = galloc(sizeof(Object)); + memclrw(dummyvaparam, sizeof(Object)); + + dummyvaparam->type = (Type *) &stvoid; + dummyvaparam->otype = OT_OBJECT; + dummyvaparam->name = GetHashNameNode("<vaparam>"); + dummyvaparam->datatype = DLOCAL; + dummyvaparam->u.var.info = CodeGen_GetNewVarInfo(); + dummyvaparam->u.var.uid = 0; + dummyvaparam->u.var.info->noregister = 1; + Registers_GetVarInfo(dummyvaparam)->flags = (Registers_GetVarInfo(dummyvaparam)->flags & ~VarInfoFlag1) | VarInfoFlag1; + + for (reg = last_argument_register[RegClass_GPR] + 1; (int)reg <= 10; reg++) { + emitpcode(PC_STW, reg, local_base_register(dummyvaparam), dummyvaparam, (reg - 3) * 4); + setpcodeflags(fPCodeFlag20 | fPCodeFlag8000); + } +} + +void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs) { + // almost matches except for the not/andc issue + SInt32 pos; + ObjectList *list; + Object *obj; + Type *type; + short reg; + SInt32 chk; + Boolean flag; + + pos = 0; + reg = 2; + + for (list = arguments; list; list = list->next) { + obj = list->object; + type = obj->type; + if (!IS_TYPE_VECTOR(type)) { + obj->datatype = DLOCAL; + obj->u.var.info = CodeGen_GetNewVarInfo(); + if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || + IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + chk = CMach_ArgumentAlignment(type); + if (chk > 4) { + pos = ALIGN(pos, chk); + update_in_param_align(chk); + } + } + obj->u.var.uid = pos; + Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; + if (!copts.little_endian && (IS_TYPE_INT(obj->type) || IS_TYPE_ENUM(obj->type)) && obj->type->size < 4) + obj->u.var.uid += 4 - obj->type->size; + pos += type->size; + pos = ALIGN(pos, 4); + } else { + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 0; + obj->datatype = DLOCAL; + flag = 1; + if (reg <= 13) + flag = hasVarargs; + if (flag) { + pos = ALIGN(pos + 24, 16) - 24; + obj->u.var.offset = pos; + pos += 16; + update_in_param_align(16); + Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; + } else { + assign_local_memory(obj); + Registers_GetVarInfo(obj)->flags = Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1; + } + reg++; + } + } + + in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size; +#line 2408 + CError_ASSERT(!dummyvaparam); +} + +SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) { + // does not match due to errant andc + SInt32 argAlign; + + if (!flag && !b) { + *outvar = 0; + return a; + } + + if (IS_TYPE_VECTOR(type)) { + update_out_param_align(16); + a = ALIGN(a + 16 + 24, 16) - 24; + } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + argAlign = CMach_ArgumentAlignment(type); + if (argAlign > 4) { + a = ALIGN(a + 24, argAlign) - 24; + update_in_param_align(argAlign); + } + } + + *outvar = a; + a = ALIGN(a + b, 4); + return a; +} + +SInt32 out_param_displ_to_offset(SInt32 displ) { + return displ + 24; +} + +Boolean needs_frame(void) { + return (frame_size > 224) || requires_frame; +} + +void update_out_param_size(SInt32 size) { + if (size < 32) + size = 32; + if (parameter_area_size < size) + parameter_area_size = size; +} + +void estimate_out_param_size(SInt32 size) { + if (parameter_area_size_estimate < size) + parameter_area_size_estimate = size; +} + +void update_out_param_align(SInt32 align) { + if (out_param_alignment < align) + out_param_alignment = align; + update_frame_align(align); +} + +void update_in_param_align(SInt32 align) { + if (in_param_alignment < align) + in_param_alignment = align; +} + +void update_frame_align(SInt32 align) { + if (frame_alignment < align) + frame_alignment = align; +} + +SInt32 local_offset_32(Object *obj) { + short align; + SInt32 offset; + + if (obj->u.var.info->flags & VarInfoFlag1) + align = CMach_ArgumentAlignment(obj->type); + else + align = CMach_AllocationAlignment(obj->type, obj->qual); + + offset = obj->u.var.uid; + if (offset > 0x7FFF) + offset = 0x8000 - offset - ALIGN(obj->type->size, align); + + if (obj->u.var.info->flags & VarInfoFlag1) + return offset + parametersbase(local_base_register(obj) != _FP_); + else + return offset + localsbase(); +} + +SInt16 local_offset_lo(Object *obj, SInt32 offset) { + SInt32 combo = offset + local_offset_32(obj); + return LOW_PART(combo); + //return (SInt16) (offset + local_offset_32(obj)); +} + +SInt16 local_offset_ha(Object *obj, SInt32 offset) { + SInt32 combo = offset + local_offset_32(obj); + return HIGH_PART(combo); + //return (SInt16) ((combo >> 16) + ((combo & 0x8000) >> 15)); +} + +SInt16 local_offset_16(Object *obj) { + SInt32 offset32 = local_offset_32(obj); + SInt16 offset16 = (SInt16) offset32; +#line 2662 + CError_ASSERT(offset32 == offset16); + return offset16; +} + +Boolean local_is_16bit_offset(Object *obj) { + SInt32 offset32 = local_offset_32(obj); + SInt16 offset16 = (SInt16) offset32; + return offset32 == offset16; +} + +int local_base_register(Object *obj) { + PCode *pc; + + if (obj->u.var.info->flags & VarInfoFlag1) { + if (coloring && _CALLER_SP_ == -1) { + _CALLER_SP_ = used_virtual_registers[RegClass_GPR]++; + pc = makepcode(PC_LWZ, _CALLER_SP_, 1, 0, 0); + setup_caller_sp = pc; + appendpcode(prologue, pc); + } + return _CALLER_SP_; + } else { + return _FP_; + } +} + +static UInt32 align_bits(UInt32 value, UInt8 bitcount) { + UInt32 base = bitcount != 0; + switch (value) { + case 0x0002: return base + 30; + case 0x0004: return base + 29; + case 0x0008: return base + 28; + case 0x0010: return base + 27; + case 0x0020: return base + 26; + case 0x0040: return base + 25; + case 0x0080: return base + 24; + case 0x0100: return base + 23; + case 0x0200: return base + 22; + case 0x0400: return base + 21; + case 0x0800: return base + 20; + case 0x1000: return base + 19; + case 0x2000: return base + 18; + default: + #line 2754 + CError_FATAL(); + return base + 27; + } +} + +Boolean is_large_frame(void) { +#line 2769 + CError_ASSERT(frame_size != -1); + return large_stack; +} + +void no_frame_for_asm(void) { + frame_size = 0; +} + +Boolean can_add_displ_to_local(Object *obj, SInt32 displ) { + if (obj->datatype != DLOCAL) + return 0; + + if (local_offset_32(obj) == (short) local_offset_32(obj)) + if ((displ + local_offset_32(obj)) == (short) (displ + local_offset_32(obj))) + return 1; + + return 0; +} + +SInt32 get_alloca_alignment(void) { + SInt32 align = frame_alignment; + if (copts.altivec_model) + align = ALIGN(align, 16); + + if (!alloca_alignment) { + alloca_alignment = align; + } else { +#line 2825 + CError_ASSERT(alloca_alignment == align); + } + + return align_bits(align, 0); +} + +static Boolean use_helper_function(char rclass) { + if (copts.no_register_save_helpers) + return 0; + + switch (rclass) { + case RegClass_GPR: + if (copts.use_lmw_stmw) + return 0; + return (used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_GPR] > 2); + case RegClass_FPR: + return (used_nonvolatile_registers[RegClass_FPR] > 3) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_FPR] > 2); + case RegClass_VR: + return (used_nonvolatile_registers[RegClass_VR] > 3) || (copts.optimize_for_size && used_nonvolatile_registers[RegClass_VR] > 2); + default: +#line 2862 + CError_FATAL(); + return 0; + } +} + +static Boolean need_link_register(void) { + if (copts.codegen_pic && uses_globals) + return 1; + + if (makes_call) + return 1; + + return use_helper_function(RegClass_FPR) || use_helper_function(RegClass_GPR) || use_helper_function(RegClass_VR); +} + +static void call_helper_function(char *name, char rclass, short effect) { + char str[32]; + Object *func; + NameSpace *save_scope; + PCode *pc; + int extra_args; + PCodeArg *arg; + short i; + + extra_args = 1; + if (rclass == RegClass_VR) + extra_args = 2; + + sprintf(str, name, 32 - used_nonvolatile_registers[rclass]); + + save_scope = cscope_current; + cscope_current = cscope_root; + func = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + cscope_current = save_scope; + + func->name = GetHashNameNodeExport(str); + + pc = makepcode(PC_BL, extra_args + used_nonvolatile_registers[rclass], func, 0); + for (i = 1, arg = &pc->args[1]; i <= used_nonvolatile_registers[rclass]; i++, arg++) { + arg->kind = PCOp_REGISTER; + arg->arg = rclass; + arg->data.reg.reg = n_real_registers[rclass] - i; + arg->data.reg.effect = effect; + } + + if (rclass == RegClass_VR) { + arg[1].kind = PCOp_REGISTER; + arg[1].arg = RegClass_GPR; + arg[1].data.reg.reg = 12; + arg[1].data.reg.effect = EffectWrite; + arg[2].kind = PCOp_REGISTER; + arg[2].arg = RegClass_GPR; + arg[2].data.reg.reg = 0; + arg[2].data.reg.effect = EffectRead; + } else { + arg[1].kind = PCOp_REGISTER; + arg[1].arg = RegClass_GPR; + arg[1].data.reg.reg = 11; + arg[1].data.reg.effect = EffectRead; + } + + appendpcode(pclastblock, pc); + setpcodeflags(fSideEffects); +} + +static SInt32 nearest_power_of_two(SInt32 n) { + SInt32 power = 1; + do { + power <<= 1; + } while (power && power < n); + +#line 2933 + CError_ASSERT(power != 0); + return power; +} + +static void compress_data_area(void) { + // doesn't quite match + SInt32 r0; + SInt32 r7; + ObjectList *list; + Object *obj; + PCodeBlock *block; + PCode *pc; + int i; + + compressing_data_area = 1; + + if (large_stack) { + r0 = 0; + } else { + r0 = parameter_area_size; + if (r0 < 32) + r0 = 32; + } + r7 = ALIGN(r0 + 24, frame_alignment) - 24; + local_data_limit = 0x8000 - ALIGN(24 + in_parameter_size + nonvolatile_save_size + r7, frame_alignment); + + if (local_objects_tail[ObjClass0]) { + if (local_objects[ObjClass1]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass1]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; + } + if (local_objects[ObjClass2]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + } else if (local_objects_tail[ObjClass1]) { + local_objects[ObjClass0] = local_objects[ObjClass1]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; + if (local_objects[ObjClass2]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + } else { + local_objects[ObjClass0] = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + + for (list = local_objects[ObjClass0]; list; list = list->next) + Registers_GetVarInfo(list->object)->used = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pc = block->firstPCode; pc; pc = pc->nextPCode) { + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_MEMORY && pc->args[i].data.mem.obj && pc->args[i].data.mem.obj->datatype == DLOCAL) + Registers_GetVarInfo(pc->args[i].data.mem.obj)->used = 1; + } + } + } + + local_data_size = 0; + large_data_near_size = 0; + large_data_far_size = 0; + + for (list = local_objects[ObjClass0]; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) + assign_local_memory(obj); + } +} + +static void insert_local_object(UInt8 oclass, Object *obj) { + ObjectList *list; + + if (!compressing_data_area) { + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + if (!local_objects[oclass]) + local_objects[oclass] = list; + if (local_objects_tail[oclass]) + local_objects_tail[oclass]->next = list; + local_objects_tail[oclass] = list; + } +} diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c new file mode 100644 index 0000000..65dc39b --- /dev/null +++ b/compiler_and_linker/unsorted/TOC.c @@ -0,0 +1,2041 @@ +#include "cos.h" +#include "compiler/TOC.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler.h" + +ObjectList *toclist; +ObjectList *exceptionlist; +void *descriptorlist; +void *floatconstpool; +void *doubleconstpool; +ObjectList *floatconstlist; +void *vectorconstpool; +ObjectList *vectorconstlist; +Object toc0; +Boolean no_descriptors; +Object pic_base; +VarInfo pic_base_varinfo; +short pic_base_reg; +CodeLabelList *codelabellist; + +UInt8 lvslBytes[16][16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E +}; + +UInt8 lvsrBytes[16][16] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 +}; + +// forward decls +static void estimate_func_param_size(ENode *node); + +static int disables_optimizer(ENode *node) { + ENode *funcref = node->data.funccall.funcref; + if (ENODE_IS(funcref, EOBJREF)) { + if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___setjmp")) + return 1; + if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___vec_setjmp")) + return 1; + } + return 0; +} + +void setupaddressing(void) { + floatconstlist = NULL; + descriptorlist = NULL; + toclist = NULL; + exceptionlist = NULL; + vectorconstlist = NULL; + vectorconstpool = NULL; + floatconstpool = NULL; + doubleconstpool = NULL; + + no_descriptors = 1; + memclrw(&toc0, sizeof(toc0)); + + pic_base_reg = 0; + memclrw(&pic_base, sizeof(pic_base)); + memclrw(&pic_base_varinfo, sizeof(pic_base_varinfo)); + pic_base.otype = OT_OBJECT; + pic_base.type = (Type *) &void_ptr; + pic_base.datatype = DNONLAZYPTR; + pic_base.u.toc.info = &pic_base_varinfo; +} + +void createNonLazyPointer(Object *obj) { + Object *toc; + ObjectList *list; + + toc = galloc(sizeof(Object)); + obj->toc = toc; + memclrw(toc, sizeof(Object)); + + toc->otype = OT_OBJECT; + toc->name = CParser_GetUniqueName(); + toc->toc = NULL; + toc->section = SECT_NONLAZY_PTRS; + toc->u.toc.info = CodeGen_GetNewVarInfo(); + toc->sclass = OBJECT_SCLASS_102; + toc->qual = Q_CONST; + toc->datatype = DNONLAZYPTR; + toc->flags |= OBJECT_FLAGS_2; + toc->type = CDecl_NewPointerType(obj->type); + toc->u.toc.over_load = obj; + toc->u.toc.linkname = CMangler_GetLinkName(obj); + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = toc; + list->next = toclist; + toclist = list; +} + +void referenceIndirectPointer(Object *obj) { + VarInfo *vi = obj->toc->u.toc.info; + vi->used = 1; + vi->usage += copts.optimize_for_size ? 1 : curstmtvalue; +} + +Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) { +#line 622 + CError_ASSERT(!copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000)); + + if (CParser_HasInternalLinkage(obj)) + return NULL; + if (ObjGen_IsExported(obj)) + return NULL; + + if (!copts.no_common && obj->datatype == DDATA && obj->section == SECT_DEFAULT && (obj->qual & Q_1000000)) + obj->section = SECT_COMMON_VARS; + + if (copts.codegen_dynamic && (!copts.no_common || !(obj->qual & Q_1000000))) { + if (!obj->toc) + createNonLazyPointer(obj); + else if (flag1) + obj->toc->u.toc.info = CodeGen_GetNewVarInfo(); + + if (flag2) + referenceIndirectPointer(obj); + + return obj->toc; + } else { + return NULL; + } +} + +Object *createfloatconstant(Type *type, Float *data) { + ObjectList *list; + Object *obj; + UInt32 *check; + + for (list = floatconstlist; list; list = list->next) { + obj = list->object; + check = (UInt32 *) obj->u.data.u.floatconst; + if (obj->type == type && check[0] == ((UInt32 *) data)[0] && check[1] == ((UInt32 *) data)[1]) + return obj; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->u.data.info = NULL; + obj->u.data.linkname = obj->name; + obj->sclass = OBJECT_SCLASS_102; + obj->qual = Q_CONST | Q_10000; + obj->datatype = DDATA; + if (type->size == 8) { + obj->section = SECT_8BYTE_LITERALS; + } else if (type->size == 4) { + obj->section = SECT_4BYTE_LITERALS; + } else { +#line 807 + CError_FATAL(); + } + + obj->flags |= OBJECT_FLAGS_2; + + obj->u.data.u.floatconst = galloc(sizeof(Float)); + *obj->u.data.u.floatconst = *data; + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = floatconstlist; + floatconstlist = list; + + ObjGen_DeclareFloatConst(obj); + return obj; +} + +Object *createvectorconstant(Type *type, MWVector128 *data) { + ObjectList *list; + Object *obj; + MWVector128 *check; + + for (list = vectorconstlist; list; list = list->next) { + obj = list->object; + check = obj->u.data.u.vector128const; + if (check->ul[0] == data->ul[0] && check->ul[1] == data->ul[1] && check->ul[2] == data->ul[2] && check->ul[3] == data->ul[3]) + return obj; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->u.data.info = NULL; + obj->u.data.linkname = obj->name; + obj->sclass = OBJECT_SCLASS_102; + obj->qual = Q_CONST | Q_10000; + obj->datatype = DDATA; + if (type->size == 16) { + obj->section = SECT_16BYTE_LITERALS; + } else { +#line 900 + CError_FATAL(); + } + + obj->flags |= OBJECT_FLAGS_2; + + obj->u.data.u.vector128const = galloc(sizeof(MWVector128)); + *obj->u.data.u.vector128const = *data; + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = vectorconstlist; + vectorconstlist = list; + + ObjGen_DeclareVectorConst(obj); + return obj; +} + +void DeclarePooledConstants() { + // TODO CInit +} + +static Object *CreatePooledFloatConst(Type *type, Float *data, SInt32 *unkptr) { + // TODO CDecl +} + +Object *CreateFloatConst(Type *type, Float *data, SInt32 *unkptr) { + *unkptr = 0; + return createfloatconstant(type, data); +} + +static void RewriteFloatConst(ENode *expr) { + Object *obj; + SInt32 n; + ENode *subexpr; + + obj = CreateFloatConst(expr->rtype, &expr->data.floatval, &n); + if (n) { + subexpr = makediadicnode(create_objectrefnode(obj), intconstnode(&stunsignedlong, n), EADD); + } else { + subexpr = create_objectrefnode(obj); + } + + expr->type = EINDIRECT; + expr->cost = 1; + expr->flags |= Q_CONST; + expr->data.monadic = subexpr; +} + +static void RewriteVectorConst(ENode *expr) { + UInt8 data[16]; + // TODO +} + +static Object *createcodelabel(CLabel *label) { + CodeLabelList *list; + Object *obj; + + for (list = codelabellist; list; list = list->next) { + if (list->label == label) + return list->object; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = (Type *) &void_ptr; + obj->name = label->uniquename; + obj->toc = NULL; + obj->u.data.info = NULL; // not sure if this is the right union! + obj->sclass = OBJECT_SCLASS_102; + obj->qual = Q_CONST; + obj->datatype = DDATA; + obj->flags |= OBJECT_FLAGS_2 | OBJECT_FLAGS_4; + + list = galloc(sizeof(CodeLabelList)); + memclrw(list, sizeof(CodeLabelList)); + list->object = obj; + list->label = label; + list->next = codelabellist; + codelabellist = list; + + return obj; +} + +void dumpcodelabels(Object *func) { + CodeLabelList *list; + + for (list = codelabellist; list; list = list->next) + ObjGen_DeclareCodeLabel(list->object, list->label->pclabel->block->codeOffset, func); +} + +static void referenceexception(Object *obj) { + ObjectList *list; + + if (obj && obj->otype == OT_OBJECT && obj->datatype == DLOCAL) { + for (list = exceptionlist; list; list = list->next) { + if (list->object == obj) + return; + } + + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = exceptionlist; + exceptionlist = list; + } +} + +static ENodeType invert_relop(ENodeType nodetype) { + switch (nodetype) { + case ELESS: return EGREATEREQU; + case EGREATER: return ELESSEQU; + case ELESSEQU: return EGREATER; + case EGREATEREQU: return ELESS; + case EEQU: return ENOTEQU; + case ENOTEQU: return EEQU; + default: return nodetype; + } +} + +static ENode *COND_to_COMPARE(ENode *cond, ENode *expr1, ENode *expr2) { + SInt32 val1; + SInt32 val2; + SInt32 condval; + ENodeType invop; + + while (expr1->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr1->rtype)) + expr1 = expr1->data.monadic; + while (expr2->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr2->rtype)) + expr2 = expr2->data.monadic; + + if (expr1->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr1->rtype) || !CInt64_IsInRange(expr1->data.intval, 4)) + return NULL; + if (expr2->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr2->rtype) || !CInt64_IsInRange(expr2->data.intval, 4)) + return NULL; + + val1 = expr1->data.intval.lo; + val2 = expr2->data.intval.lo; + condval = 0; + switch (val1) { + case 1: + if (val2 != 0) + return NULL; + break; + case 0: + condval = 1; + if (val2 != 1) + return NULL; + break; + default: + return NULL; + } + + while (cond->type == ELOGNOT) { + condval = (condval + 1) & 1; + cond = cond->data.monadic; + } + + if (condval) { + invop = invert_relop(cond->type); + if (invop == cond->type) + return NULL; + cond->type = invop; + } + + return cond; +} + +static ENode *comparewithzero(ENode *expr) { + ENode *expr1; + ENode *expr2; + ENode *tmp; + + expr1 = lalloc(sizeof(ENode)); + memclrw(expr1, sizeof(ENode)); + expr2 = lalloc(sizeof(ENode)); + memclrw(expr2, sizeof(ENode)); + + while (expr->type == EFORCELOAD || expr->type == ETYPCON || expr->type == ECOMMA) { + if (!TYPE_FITS_IN_REGISTER(expr->rtype)) + break; + if (expr->type == ECOMMA) { + expr->data.diadic.right = comparewithzero(expr->data.diadic.right); + return expr; + } + expr = expr->data.monadic; + } + + if (expr->type == ECOND && TYPE_FITS_IN_REGISTER(expr->rtype)) { + tmp = COND_to_COMPARE(expr->data.cond.cond, expr->data.cond.expr1, expr->data.cond.expr2); + if (tmp) + expr = tmp; + } + + if (expr->type >= ELESS && expr->type <= ENOTEQU) + return expr; + + if (IS_TYPE_FLOAT(expr->rtype)) { + static Float float0 = {0.0}; + + expr2->type = EFLOATCONST; + expr2->cost = 0; + expr2->rtype = (expr->rtype->size == 4) ? (Type *) &stfloat : (Type *) &stdouble; + expr2->data.floatval = float0; + } else { + expr2->type = EINTCONST; + expr2->cost = 0; + if (TYPE_IS_8BYTES(expr->rtype)) + expr2->rtype = (Type *) &stsignedlonglong; + else + expr2->rtype = (Type *) &stsignedint; + expr2->data.intval.lo = 0; + expr2->data.intval.hi = 0; + } + + expr1->type = ENOTEQU; + expr1->cost = expr->cost; + expr1->rtype = (Type *) &stsignedint; + expr1->data.diadic.left = expr; + expr1->data.diadic.right = expr2; + return expr1; +} + +static void rewritefunctioncallreturningstruct(ENode *expr) { + ENode *ret_expr; + ENode *copy; + + ret_expr = expr->data.funccall.args->node; + + copy = lalloc(sizeof(ENode)); + memclrw(copy, sizeof(ENode)); + + *copy = *expr; + expr->type = ECOMMA; + expr->data.diadic.left = copy; + expr->data.diadic.right = ret_expr; +} + +static void rewritestrcpy(ENode *expr) { + ENode *int_expr; + ENodeList *list; + + int_expr = lalloc(sizeof(ENode)); + memclrw(int_expr, sizeof(ENode)); + int_expr->type = EINTCONST; + int_expr->cost = 0; + int_expr->flags = 0; + int_expr->rtype = (Type *) &stunsignedlong; + CInt64_SetLong(&int_expr->data.intval, expr->data.funccall.args->next->node->data.string.size); + + list = lalloc(sizeof(ENodeList)); + memclrw(list, sizeof(ENodeList)); + list->next = NULL; + list->node = int_expr; + expr->data.funccall.args->next->next = list; + expr->data.funccall.funcref->data.objref = __memcpy_object; +} + +static SInt32 magnitude(Type *type) { + if (IS_TYPE_FLOAT(type)) + return type->size * 4; + else if (is_unsigned(type)) + return (type->size * 2) + 1; + else + return type->size * 2; +} + +static Type *promote_type(Type *type) { + if (IS_TYPE_ENUM(type)) + type = TYPE_ENUM(type)->enumtype; + if (TYPE_INTEGRAL(type)->integral > stsignedint.integral) + return type; + else + return (Type *) &stsignedint; +} + +static Type *common_type(Type *type1, Type *type2) { + Type *tmp; + + if (IS_TYPE_FLOAT(type1) || IS_TYPE_FLOAT(type2)) { + if (TYPE_INTEGRAL(type1)->integral > TYPE_INTEGRAL(type2)->integral) + return type1; + else + return type2; + } + + type1 = promote_type(type1); + type2 = promote_type(type2); + if (type1 != type2) { + if (TYPE_INTEGRAL(type1)->integral < TYPE_INTEGRAL(type2)->integral) { + tmp = type1; + type1 = type2; + type2 = tmp; + } + + if (type1->size == type2->size && !is_unsigned(type1) && is_unsigned(type2)) { + if (type1 == (Type *) &stsignedlong) { + type1 = (Type *) &stunsignedlong; + } else { +#line 1789 + CError_ASSERT(type1 == (Type *) &stsignedlonglong); + type1 = (Type *) &stunsignedlonglong; + } + } + } + + return type1; +} + +static void rewrite_opassign(ENode *expr, ENodeType exprtype) { + ENode *left_sub; + ENode *right; + Type *left_type; + Type *right_type; + ENode *new_expr; + ENode *tmp; + Type *commontype; + Type *promo_left; + Type *promo_right; + + left_sub = expr->data.diadic.left->data.monadic; + right = expr->data.diadic.right; + left_type = expr->data.diadic.left->rtype; + right_type = expr->data.diadic.right->rtype; + + new_expr = lalloc(sizeof(ENode)); + memclrw(new_expr, sizeof(ENode)); + new_expr->type = exprtype; + new_expr->rtype = left_type; + new_expr->data.diadic.left = expr->data.diadic.left; + new_expr->data.diadic.right = right; + + expr->type = EASS; + expr->data.diadic.left = left_sub; + expr->data.diadic.right = new_expr; + + if (left_sub->type != EOBJREF) { + ENode *define; + ENode *reuse; + + define = lalloc(sizeof(ENode)); + memclrw(define, sizeof(ENode)); + define->type = EDEFINE; + define->rtype = left_type; + + reuse = lalloc(sizeof(ENode)); + memclrw(reuse, sizeof(ENode)); + reuse->type = EREUSE; + reuse->rtype = left_type; + reuse->data.monadic = define; + + if (left_sub->type != EBITFIELD) { + define->data.monadic = expr->data.diadic.left; + expr->data.diadic.left = define; + new_expr->data.diadic.left->data.diadic.left = reuse; + } else { + ENode *copy; + define->data.monadic = left_sub->data.diadic.left; + left_sub->data.diadic.left = define; + + copy = lalloc(sizeof(ENode)); + *copy = *left_sub; + copy->data.diadic.left = reuse; + new_expr->data.diadic.left->data.diadic.left = copy; + } + } + + switch (exprtype) { + case EADD: + case ESUB: + if (IS_TYPE_POINTER(left_type)) + break; + if (right->type == EINTCONST && TYPE_FITS_IN_REGISTER(left_type)) + break; + case EAND: + case EXOR: + case EOR: + if (left_type == right_type) + break; + case EMUL: + case EDIV: + case EMODULO: + commontype = common_type(left_type, right_type); + if (left_type != commontype) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = left_type; + tmp->data.monadic = expr->data.diadic.right; + expr->data.diadic.right = tmp; + + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = commontype; + tmp->data.monadic = new_expr->data.diadic.left; + new_expr->data.diadic.left = tmp; + } + if (right_type != commontype) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = commontype; + tmp->data.monadic = new_expr->data.diadic.right; + new_expr->data.diadic.right = tmp; + } + new_expr->rtype = commontype; + break; + + case ESHL: + case ESHR: + promo_left = promote_type(left_type); + promo_right = promote_type(right_type); + if (left_type != promo_left) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = left_type; + tmp->data.monadic = expr->data.diadic.right; + expr->data.diadic.right = tmp; + + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = promo_left; + tmp->data.monadic = new_expr->data.diadic.left; + new_expr->data.diadic.left = tmp; + } + if (right_type != promo_right) { + if (new_expr->data.diadic.right->type == EINTCONST && promo_right == (Type *) &stsignedint) { + new_expr->data.diadic.right->rtype = (Type *) &stsignedint; + } else { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = promo_right; + tmp->data.monadic = new_expr->data.diadic.right; + new_expr->data.diadic.right = tmp; + } + } + new_expr->rtype = promo_left; + break; + } +} + +static void rewrite_preincdec(ENode *expr) { + ENode *subexpr; // r31 + Type *type; // r28 + ENode *new_expr; // r29 + + subexpr = expr->data.monadic; + type = expr->rtype; + + new_expr = lalloc(sizeof(ENode)); + memclrw(new_expr, sizeof(ENode)); + + if (IS_TYPE_FLOAT(type)) { + new_expr->type = EFLOATCONST; + new_expr->cost = 0; + new_expr->rtype = type; + new_expr->data.floatval = one_point_zero; + } else if (IS_TYPE_POINTER(type)) { + new_expr->type = EINTCONST; + new_expr->cost = 0; + new_expr->rtype = (Type *) &stunsignedlong; + new_expr->data.intval.hi = 0; + new_expr->data.intval.lo = TYPE_POINTER(type)->target->size; + } else { + new_expr->type = EINTCONST; + new_expr->cost = 0; + new_expr->rtype = type; + new_expr->data.intval.hi = 0; + new_expr->data.intval.lo = 1; + } + + expr->type = (expr->type == EPREDEC) ? ESUBASS : EADDASS; + expr->data.diadic.left = subexpr; + expr->data.diadic.right = new_expr; +} + +// Don't know what this would be called in the original, but weh +typedef union signed_vec { + SInt8 sc[16]; + SInt16 ss[8]; + SInt32 sl[4]; +} signed_vec; + +Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result) { + // this function is very broken + signed_vec vec; + union { SInt32 lg; SInt8 ch[4]; } conv32; + union { SInt16 sh; SInt8 ch[2]; } conv16; + char flag; + SInt8 first8; + SInt16 first16; + SInt32 first32; + int i; + char ci; + UInt32 l0, l1, l2, l3; + + if (IS_TYPE_VECTOR(type)) { + vec = *((signed_vec *) vecp); + + first8 = vec.sc[0]; + flag = 1; + for (i = 0; flag && i < 16; i++) { + flag = first8 == vec.sc[i]; + } + + if (flag && first8 < 16 && first8 > -17) { + if (result) { + result->op1 = PC_VSPLTISB; + result->op2 = -1; + result->arg = first8; + } + return 1; + } + + first16 = vec.ss[0]; + flag = 1; + for (i = 1; flag && i < 8; i++) { + flag = vec.ss[i] == first16; + } + + conv16.sh = first16; + if (flag && conv16.ch[0] == 0 && conv16.ch[1] < 16 && conv16.ch[1] >= 0) { + if (result) { + result->op1 = PC_VSPLTISH; + result->op2 = -1; + result->arg = conv16.ch[1]; + } + return 1; + } + + if (flag && conv16.ch[0] == -1 && (conv16.ch[1] & 0xF0) == 0xF0) { + if (result) { + result->op1 = PC_VSPLTISH; + result->op2 = -1; + result->arg = conv16.ch[1]; + } + return 1; + } + + first32 = vec.sl[0]; + flag = 1; + for (i = 1; flag && i < 4; i++) { + flag = vec.sl[i] == first32; + } + + conv32.lg = first32; + if (flag && conv32.ch[0] == 0 && conv32.ch[1] == 0 && conv32.ch[2] == 0 && conv32.ch[3] < 16 && conv32.ch[3] >= 0) { + if (result) { + result->op1 = PC_VSPLTISW; + result->op2 = -1; + result->arg = conv32.ch[3]; + } + return 1; + } + + if (flag && conv32.ch[0] == -1 && conv32.ch[1] == -1 && conv32.ch[2] == -1 && (conv32.ch[3] & 0xF0) == 0xF0) { + if (result) { + result->op1 = PC_VSPLTISW; + result->op2 = -1; + result->arg = conv32.ch[3]; + } + return 1; + } + + l0 = vec.sl[0]; + l1 = vec.sl[1]; + l2 = vec.sl[2]; + l3 = vec.sl[3]; + for (ci = 0; ci < 16; ci++) { + UInt32 *l; + UInt32 *r; + + l = (UInt32 *) lvslBytes[(char) ci]; + r = (UInt32 *) lvsrBytes[(char) ci]; + if (l0 == l[0] && l1 == l[1] && l2 == l[2] && l3 == l[3]) { + if (result) { + result->op1 = -1; + result->op2 = PC_LVSL; + result->arg = ci; + } + return 1; + } + if (l0 == r[0] && l1 == r[1] && l2 == r[2] && l3 == r[3]) { + if (result) { + result->op1 = -1; + result->op2 = PC_LVSR; + result->arg = ci; + } + return 1; + } + } + } + + return 0; +} + +static SInt32 countindirects(ENode *expr) { + SInt32 tmp1; + SInt32 tmp2; + + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + return 0; + case ECOND: + if (expr->data.cond.cond->hascall || expr->data.cond.expr1->hascall || expr->data.cond.expr2->hascall) + return 2; + + if ((tmp1 = countindirects(expr->data.cond.cond)) >= 2) + return 2; + if ((tmp2 = countindirects(expr->data.cond.expr1)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + if ((tmp2 = countindirects(expr->data.cond.expr2)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + return tmp1; + case EFUNCCALL: + case EFUNCCALLP: + return 2; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + if ((tmp1 = countindirects(expr->data.diadic.left)) >= 2) + return 2; + if ((tmp2 = countindirects(expr->data.diadic.right)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + return tmp1; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + if (expr->type == EINDIRECT) + return countindirects(expr->data.monadic) + 1; + else + return countindirects(expr->data.monadic); + default: + return 2; + } +} + +static Boolean DetectCondSideAffect(ENode *expr) { + switch (expr->type) { + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case EAND: + case EXOR: + case EOR: + case ECOMMA: + if (DetectCondSideAffect(expr->data.diadic.left)) + return 1; + return DetectCondSideAffect(expr->data.diadic.right); + case EINDIRECT: + if (expr->data.monadic->type == EINDIRECT) + return 1; + if (expr->data.monadic->type == EOBJREF) { + if (expr->data.monadic->data.objref->datatype != DDATA && expr->data.monadic->data.objref->datatype != DLOCAL) + return 1; + if (IS_TYPE_POINTER(expr->data.monadic->data.objref->type)) + return 1; + return Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister != 0; + } + return 1; + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + return DetectCondSideAffect(expr->data.monadic); + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + return 0; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOND: + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case EDEFINE: + case EREUSE: + case EASSBLK: + case ECONDASS: + return 1; + default: +#line 2523 + CError_FATAL(); + return 1; + } +} + +static UInt8 WeightandSumOps(ENode *expr) { + UInt32 score; + + switch (expr->type) { + case ECOND: + case ECONDASS: + score = WeightandSumOps(expr->data.cond.cond); + score += WeightandSumOps(expr->data.cond.expr1); + score += WeightandSumOps(expr->data.cond.expr2); + break; + case EMUL: + case EMULV: + case EMULASS: + score = WeightandSumOps(expr->data.diadic.left) + 10; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EDIV: + case EMODULO: + case EDIVASS: + case EMODASS: + score = WeightandSumOps(expr->data.diadic.left) + 20; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + score = WeightandSumOps(expr->data.diadic.left) + 1; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + score = WeightandSumOps(expr->data.monadic) + 1; + break; + case EINDIRECT: + if (expr->data.monadic->type == EOBJREF && expr->data.monadic->data.objref->datatype == DLOCAL) + if (!Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister) + return 0; + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + score = WeightandSumOps(expr->data.monadic); + break; + case EOBJREF: + score = 0; + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EVECTOR128CONST: + score = 0; + break; + case EFUNCCALL: + case EFUNCCALLP: + score = 5; + break; + default: + score = 255; + } + + if (score >= 255) + score = 255; + return (UInt8) score; +} + +Boolean TOC_use_fsel(ENode *expr) { + ENode *left; + ENode *right; + Type *rtype; + int score1; + int score2; + + left = expr->data.cond.expr1; + right = expr->data.cond.expr2; + rtype = expr->rtype; + + if (!copts.peephole) return 0; + if (!copts.gen_fsel) return 0; + if (left->hascall) return 0; + if (right->hascall) return 0; + if (!IS_TYPE_FLOAT(rtype)) return 0; + if (!IS_TYPE_FLOAT(left->rtype)) return 0; + if (!IS_TYPE_FLOAT(right->rtype)) return 0; + + if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) + return 0; + if (!IS_TYPE_FLOAT(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + if (expr->data.cond.cond->type == ELOGNOT || expr->data.cond.cond->type == ELAND || expr->data.cond.cond->type == ELOR) + return 0; + + if (expr->type == ECONDASS) { + if (left->type != EINDIRECT) + return 0; + if (left->data.monadic->type != EOBJREF) + return 0; + } + + if (DetectCondSideAffect(left)) + return 0; + if (DetectCondSideAffect(right)) + return 0; + + if (expr->type == ECONDASS) + score1 = 1; + else + score1 = WeightandSumOps(left); + score2 = WeightandSumOps(right); + + if (score1 > copts.gen_fsel) + return 0; + else if (score2 > copts.gen_fsel) + return 0; + else + return 1; +} + +Boolean TOC_use_isel(ENode *expr, Boolean flag) { + int opt; + ENode *left; + ENode *right; + Type *rtype; + Object *obj; + int score1; + int score2; + + left = expr->data.cond.expr1; + right = expr->data.cond.expr2; + rtype = expr->rtype; + if (flag) + opt = 10; + else + opt = copts.x1E; + + if (!opt) return 0; + if (!copts.peephole) return 0; + if (left->hascall) return 0; + if (right->hascall) return 0; + if (!TYPE_FITS_IN_REGISTER(rtype)) return 0; + if (!TYPE_FITS_IN_REGISTER(left->rtype)) return 0; + if (!TYPE_FITS_IN_REGISTER(right->rtype)) return 0; + + if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) + return 0; + if (TYPE_IS_8BYTES(rtype)) + return 0; + + if (flag) { + if (!TYPE_FITS_IN_REGISTER(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + if (TYPE_IS_8BYTES(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + } + + if (expr->type == ECONDASS) { + if (left->type != EINDIRECT) + return 0; + if (left->data.monadic->type != EOBJREF) + return 0; + if (flag) { + obj = left->data.monadic->data.objref; + if (obj->datatype != DLOCAL) + return 0; + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) + return 0; + if (obj->u.var.info->rclass != RegClass_GPR) + return 0; + } + } + + if (DetectCondSideAffect(left)) + return 0; + if (DetectCondSideAffect(right)) + return 0; + + if (expr->type == ECONDASS) + score1 = 1; + else + score1 = WeightandSumOps(left); + score2 = WeightandSumOps(right); + + if (score1 > opt) + return 0; + else if (score2 > opt) + return 0; + else + return 1; +} + +SInt32 GetSizeSkip(ENode *expr) { + if (expr->type == EASS) + expr = expr->data.diadic.right; + if (expr->type == ETYPCON && expr->data.monadic->rtype->size < expr->rtype->size) + return expr->data.monadic->rtype->size; + else + return expr->rtype->size; +} + +void Optimize64bitMath(ENode *expr) { + ENode *left; // r23 + ENode *right; // r28 + SInt32 leftsize; // r24 + SInt32 rightsize; // r25 + SInt32 totalsize; // r22 + int unsignedflag; // r4 + +#line 2886 + CError_ASSERT(TYPE_IS_8BYTES(expr->rtype)); + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + leftsize = GetSizeSkip(left); + totalsize = (leftsize + (rightsize = GetSizeSkip(right))); + unsignedflag = is_unsigned(expr->rtype) != 0; + + switch (totalsize) { + case 2: + case 3: + case 4: + if (unsignedflag) { + left->rtype = (Type *) &stunsignedint; + right->rtype = (Type *) &stunsignedint; + } else { + left->rtype = (Type *) &stsignedint; + right->rtype = (Type *) &stsignedint; + } + break; + case 5: + case 6: + case 8: + case 9: + case 10: + case 12: + if (expr->type != ESUB || leftsize >= rightsize) { + if (leftsize < 4) { + if (unsignedflag) + left->rtype = (Type *) &stunsignedint; + else + left->rtype = (Type *) &stsignedint; + } else { + if (left->type == ETYPCON && left->data.monadic->rtype != (Type *) &stfloat) + expr->data.diadic.left = left->data.monadic; + } + if (rightsize < 4) { + if (unsignedflag) + right->rtype = (Type *) &stunsignedint; + else + right->rtype = (Type *) &stsignedint; + } else { + if (right->type == ETYPCON && right->data.monadic->rtype != (Type *) &stfloat) + expr->data.diadic.right = right->data.monadic; + } + } + break; + case 16: + break; + default: +#line 2975 + CError_FATAL(); + } +} + +static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) { + ENode *expr; + Boolean success1; + Boolean success2; + + expr = *pexpr; + switch (expr->type) { + case EOBJREF: + return check != expr->data.objref; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + switch (expr->type) { + case EASS: + if (ENODE_IS(expr->data.diadic.left, EOBJREF) && expr->data.diadic.left->data.objref == check) { + *pexpr = expr->data.diadic.right; + return OptimizeNestedAssginments(pexpr, check); + } + break; + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: +#line 3033 + CError_FATAL(); + return 0; + } + if (OptimizeNestedAssginments(&expr->data.diadic.right, check)) + return OptimizeNestedAssginments(&expr->data.diadic.left, check); + else + return 0; + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + return OptimizeNestedAssginments(&expr->data.monadic, check); + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EVECTOR128CONST: + return 1; + case ECOND: + success2 = OptimizeNestedAssginments(&expr->data.cond.expr2, check); + success1 = OptimizeNestedAssginments(&expr->data.cond.expr1, check); + if (!success2 || !success1) + return 0; + return OptimizeNestedAssginments(&expr->data.cond.cond, check) == 0; + case ECONDASS: + if (!OptimizeNestedAssginments(&expr->data.cond.expr2, check)) + return 0; + if (OptimizeNestedAssginments(&expr->data.cond.cond, check)) + return OptimizeNestedAssginments(&expr->data.cond.expr1, check) == 0; + else + return 0; + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case EDEFINE: + case EREUSE: + case EASSBLK: + return 0; + default: +#line 3083 + CError_FATAL(); + return 0; + } +} + +static void expandTOCexpression(ENode *expr, Type *type, int ignored) { + Object *obj; + Object *tmpobj; + ENode *cond; + ENode *tmpexpr; + ENode *newexpr; + ENodeList *list; + + expr->ignored = ignored; + switch (expr->type) { + case EINTCONST: + expr->hascall = 0; + break; + case EFLOATCONST: + uses_globals = 1; + RewriteFloatConst(expr); + expandTOCexpression(expr, NULL, 0); + break; + case EVECTOR128CONST: + if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, NULL)) { + uses_globals = 1; + RewriteVectorConst(expr); + expandTOCexpression(expr, NULL, 0); + } + break; + case ESTRINGCONST: + uses_globals = 1; + CInit_RewriteString(expr, 1); + expandTOCexpression(expr, NULL, 0); + break; + case EOBJREF: + obj = expr->data.objref; +#line 3203 + CError_ASSERT(obj->datatype != DALIAS); + if (obj->datatype == DFUNC || obj->datatype == DVFUNC) + uses_globals = 1; + if (obj->datatype == DDATA) { + uses_globals = 1; + if (createIndirect(obj, 0, 1)) { + tmpexpr = lalloc(sizeof(ENode)); + memclrw(tmpexpr, sizeof(ENode)); + tmpexpr->type = EOBJREF; + tmpexpr->cost = 0; + tmpexpr->data.objref = obj->toc; + tmpexpr->rtype = CDecl_NewPointerType(expr->rtype); + + expr->type = EINDIRECT; + expr->cost = 1; + expr->data.monadic = tmpexpr; + } + } + expr->hascall = 0; + break; + case ECONDASS: + expr->ignored = 0; + case ECOND: + if (!ENODE_IS_RANGE(expr->data.cond.cond, ELESS, ENOTEQU)) + expr->data.cond.cond = comparewithzero(expr->data.cond.cond); + expandTOCexpression(expr->data.cond.expr1, NULL, ignored); + expandTOCexpression(expr->data.cond.expr2, NULL, ignored); + if (TOC_use_fsel(expr)) { + cond = expr->data.cond.cond; + if (ENODE_IS(cond->data.diadic.right, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.right->data.floatval)) { + expandTOCexpression(cond->data.diadic.left, NULL, 0); + } else if (ENODE_IS(cond->data.diadic.left, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.left->data.floatval)) { + expandTOCexpression(cond->data.diadic.right, NULL, 0); + } else { + expandTOCexpression(expr->data.cond.cond, NULL, 0); + } + } else { + expandTOCexpression(expr->data.cond.cond, NULL, 0); + } + expr->hascall = expr->data.cond.cond->hascall | expr->data.cond.expr1->hascall | expr->data.cond.expr2->hascall; + break; + case EFUNCCALL: + case EFUNCCALLP: + if (is_intrinsic_function_call(expr)) { + expr->hascall = 0; + if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_8) { + if (copts.altivec_model) + update_frame_align(16); + dynamic_stack = 1; + requires_frame = 1; + } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_35) { + if (expr->data.funccall.args->next->node->type == ESTRINGCONST) { + rewritestrcpy(expr); + } else { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == INTRINSIC_36) { + if (expr->data.funccall.args->next->next->node->type != EINTCONST) { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + } + } else { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + + if (disables_optimizer(expr)) { + disable_optimizer |= 1; + if (copts.disable_registers) + disable_optimizer |= 2; + } + + if (ENODE_IS(expr->data.funccall.funcref, EINDIRECT) && IS_TYPE_FUNC(expr->data.funccall.funcref->rtype)) + *expr->data.funccall.funcref = *expr->data.funccall.funcref->data.monadic; + + if (ENODE_IS(expr->data.funccall.funcref, EOBJREF)) { + expr->data.funccall.funcref->hascall = 0; + if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC && (expr->data.funccall.funcref->flags & ENODE_FLAG_80)) { + tmpobj = galloc(sizeof(Object)); + *tmpobj = *expr->data.funccall.funcref->data.objref; + tmpobj->datatype = DFUNC; + expr->data.funccall.funcref->data.objref = tmpobj; + } + } else { + expandTOCexpression(expr->data.funccall.funcref, NULL, 0); + } + + for (list = expr->data.funccall.args; list; list = list->next) + expandTOCexpression(list->node, NULL, 0); + + if (expr->hascall) + estimate_func_param_size(expr); + + if (is_intrinsic_function_call(expr)) { + for (list = expr->data.funccall.args; list; list = list->next) + expr->hascall |= list->node->hascall; + } + + if (CMach_PassResultInHiddenArg(TYPE_FUNC(expr->data.funccall.functype)->functype)) + rewritefunctioncallreturningstruct(expr); + + break; + case ECOMMA: + expandTOCexpression(expr->data.diadic.left, NULL, 1); + expandTOCexpression(expr->data.diadic.right, NULL, ignored); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case ELAND: + case ELOR: + if (!ENODE_IS(expr->data.diadic.left, ELOGNOT) && !ENODE_IS2(expr->data.diadic.left, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.left, ELESS, ENOTEQU)) + expr->data.diadic.left = comparewithzero(expr->data.diadic.left); + if (!ENODE_IS(expr->data.diadic.right, ELOGNOT) && !ENODE_IS2(expr->data.diadic.right, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.right, ELESS, ENOTEQU)) + expr->data.diadic.right = comparewithzero(expr->data.diadic.right); + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case EDIVASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EDIV); + goto opassign_common; + case EMULASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EMUL); + goto opassign_common; + case EADDASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EADD); + goto opassign_common; + case ESUBASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, ESUB); + goto opassign_common; + case EMODASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EMODULO); + goto opassign_common; + case ESHLASS: + rewrite_opassign(expr, ESHL); + goto opassign_common; + case ESHRASS: + rewrite_opassign(expr, ESHR); + goto opassign_common; + case EANDASS: + rewrite_opassign(expr, EAND); + goto opassign_common; + case EXORASS: + rewrite_opassign(expr, EXOR); + goto opassign_common; + case EORASS: + rewrite_opassign(expr, EOR); + goto opassign_common; + case EASS: + if (ENODE_IS(expr->data.diadic.left, EINDIRECT)) + expr->data.diadic.left = expr->data.diadic.left->data.monadic; + opassign_common: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case EEQU: + case ENOTEQU: + if (ENODE_IS(expr->data.diadic.right, EINTCONST) && expr->data.diadic.right->data.intval.lo == 0 && expr->data.diadic.right->data.intval.hi == 0) { + for (tmpexpr = expr->data.diadic.left; ENODE_IS2(tmpexpr, EFORCELOAD, ETYPCON); tmpexpr = tmpexpr->data.monadic) { + if (!TYPE_FITS_IN_REGISTER(tmpexpr->rtype)) + break; + } + if (ENODE_IS(tmpexpr, ELOGNOT) && TYPE_FITS_IN_REGISTER(tmpexpr->data.monadic->rtype)) { + if (ENODE_IS(expr, EEQU)) + expr->type = ENOTEQU; + else + expr->type = EEQU; + expr->data.diadic.left = tmpexpr->data.monadic; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, EEQU)) { + if (ENODE_IS(expr, EEQU)) + tmpexpr->type = ENOTEQU; + *expr = *tmpexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, ENOTEQU)) { + if (ENODE_IS(expr, EEQU)) + tmpexpr->type = EEQU; + *expr = *tmpexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, ECOND)) { + newexpr = COND_to_COMPARE(tmpexpr->data.cond.cond, tmpexpr->data.cond.expr1, tmpexpr->data.cond.expr2); + if (newexpr) { + *tmpexpr = *newexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + } + } + case EDIV: + if (ENODE_IS(expr, EDIV) && ENODE_IS(expr->data.diadic.right, EFLOATCONST) && CMach_FloatIsPowerOf2(expr->data.diadic.right->data.floatval)) { + expr->type = EMUL; + expr->data.diadic.right->data.floatval = CMach_FloatReciprocal(expr->data.diadic.right->data.floatval); + } + case EMODULO: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + if (TYPE_IS_8BYTES(expr->rtype)) { + if (ENODE_IS2(expr, ESHL, ESHR) && !ENODE_IS(expr->data.diadic.right, EINTCONST)) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + if (ENODE_IS2(expr, EDIV, EMODULO)) { + if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { + if (I8_log2n(((SInt64) expr->data.diadic.right->data.intval.hi << 32) + expr->data.diadic.right->data.intval.lo) <= 0) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + } else { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + } + } + break; + case ESUB: + if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { + expr->type = EADD; + expr->data.diadic.right->data.intval = CInt64_Neg(expr->data.diadic.right->data.intval); + } + case EMUL: + case EADD: + case EAND: + case EXOR: + case EOR: + expandTOCexpression(expr->data.diadic.left, type, 0); + expandTOCexpression(expr->data.diadic.right, type, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + if (ENODE_IS3(expr, EMUL, EADD, ESUB) && TYPE_IS_8BYTES(expr->rtype)) + Optimize64bitMath(expr); + if (type) { + if ( + ENODE_IS(expr->data.diadic.left, ETYPCON) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->rtype) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->data.monadic->rtype) && + expr->data.diadic.left->data.monadic->rtype->size >= type->size && + !TYPE_IS_8BYTES(expr->data.diadic.left->data.monadic->rtype) + ) + expr->data.diadic.left = expr->data.diadic.left->data.monadic; + + if ( + ENODE_IS(expr->data.diadic.right, ETYPCON) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->rtype) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->data.monadic->rtype) && + expr->data.diadic.right->data.monadic->rtype->size >= type->size && + !TYPE_IS_8BYTES(expr->data.diadic.right->data.monadic->rtype) + ) + expr->data.diadic.right = expr->data.diadic.right->data.monadic; + + expr->rtype = type; + } + break; + + case ETYPCON: + tmpexpr = expr->data.monadic; + if ((IS_TYPE_INT_OR_ENUM(expr->rtype) && expr->rtype->size < 4) && IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && !TYPE_IS_8BYTES(tmpexpr->rtype)) { + expandTOCexpression(tmpexpr, expr->rtype, 0); + } else { + expandTOCexpression(tmpexpr, NULL, expr->rtype->type == TYPEVOID); + } + + expr->hascall = tmpexpr->hascall; + if (IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) + uses_globals = 1; + + if ((TYPE_IS_8BYTES(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) || (TYPE_IS_8BYTES(expr->rtype) && IS_TYPE_FLOAT(tmpexpr->rtype))) { + uses_globals = 1; + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + + if (IS_TYPE_FLOAT(tmpexpr->rtype)) { + if (is_unsigned(expr->rtype) && expr->rtype->size == 4) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } else { + uses_globals = 1; + } + } + + if (IS_TYPE_VECTOR(expr->rtype) && !IS_TYPE_VECTOR(tmpexpr->rtype)) + PPCError_Error(114); + break; + + case EPOSTINC: + if (!expr->ignored) { + if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) + uses_globals = 1; + expandTOCexpression(expr->data.monadic, NULL, 0); + expr->hascall = expr->data.monadic->hascall; + break; + } + expr->type = EPREINC; + case EPREINC: + rewrite_preincdec(expr); + rewrite_opassign(expr, EADD); + goto opassign_common; + + case EPOSTDEC: + if (!expr->ignored) { + if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) + uses_globals = 1; + expandTOCexpression(expr->data.monadic, NULL, 0); + expr->hascall = expr->data.monadic->hascall; + break; + } + expr->type = EPREDEC; + case EPREDEC: + rewrite_preincdec(expr); + rewrite_opassign(expr, ESUB); + goto opassign_common; + + case ELOGNOT: + if (!ENODE_IS(expr->data.monadic, ELOGNOT) && !ENODE_IS2(expr->data.monadic, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.monadic, ELESS, ENOTEQU)) + expr->data.monadic = comparewithzero(expr->data.monadic); + case EMONMIN: + case EBINNOT: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, type, 0); + expr->hascall = tmpexpr->hascall; + if (type && ENODE_IS(expr->data.monadic, ETYPCON)) { + if (IS_TYPE_INT_OR_ENUM(expr->data.monadic->rtype) && IS_TYPE_INT_OR_ENUM(expr->data.monadic->data.monadic->rtype)) { + if (expr->data.monadic->data.monadic->rtype->size >= type->size) { + expr->data.monadic = expr->data.monadic->data.monadic; + expr->rtype = type; + } + } + } + break; + + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, NULL, 0); + expr->hascall = tmpexpr->hascall; + break; + + case EDEFINE: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, NULL, 0); + expr->hascall = tmpexpr->hascall; + break; + + case EREUSE: + expr->hascall = expr->data.monadic->hascall; + break; + + case ENULLCHECK: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + + case EPRECOMP: + expr->hascall = 0; + break; + + case ELABEL: + obj = createcodelabel(expr->data.label); + newexpr = lalloc(sizeof(ENode)); + memclrw(newexpr, sizeof(ENode)); + newexpr->type = EOBJREF; + newexpr->cost = 0; + newexpr->data.objref = obj; + newexpr->rtype = CDecl_NewPointerType(obj->type); + + expr->type = EINDIRECT; + expr->cost = 1; + expr->data.monadic = newexpr; + expr->hascall = 0; + break; + } +} + +static void checkexceptionreferences(ExceptionAction *action) { + for (; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYLOCAL: + referenceexception(action->data.destroy_local.local); + break; + case EAT_DESTROYLOCALCOND: + referenceexception(action->data.destroy_local_cond.local); + referenceexception(action->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + referenceexception(action->data.destroy_local_offset.local); + break; + case EAT_DESTROYLOCALPOINTER: + referenceexception(action->data.destroy_local_pointer.pointer); + break; + case EAT_DESTROYLOCALARRAY: + referenceexception(action->data.destroy_local_array.localarray); + break; + case EAT_DESTROYBASE: + referenceexception(action->data.destroy_member.objectptr); // wrong union? + break; + case EAT_DESTROYPARTIALARRAY: + referenceexception(action->data.destroy_partial_array.arraypointer); + referenceexception(action->data.destroy_partial_array.arraycounter); + referenceexception(action->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYMEMBER: + referenceexception(action->data.destroy_member.objectptr); + break; + case EAT_DESTROYMEMBERCOND: + referenceexception(action->data.destroy_member_cond.objectptr); + referenceexception(action->data.destroy_member_cond.cond); + break; + case EAT_DESTROYMEMBERARRAY: + referenceexception(action->data.destroy_member_array.objectptr); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + referenceexception(action->data.delete_pointer.pointerobject); + break; + case EAT_DELETEPOINTERCOND: + referenceexception(action->data.delete_pointer_cond.pointerobject); + referenceexception(action->data.delete_pointer_cond.cond); + break; + case EAT_CATCHBLOCK: + referenceexception(action->data.catch_block.catch_object); + referenceexception(action->data.catch_block.catch_info_object); + break; + case EAT_ACTIVECATCHBLOCK: + referenceexception(action->data.active_catch_block.catch_info_object); + break; + } + } +} + +void expandTOCreferences(Statement **stmts) { + Statement *stmt; + + codelabellist = NULL; + exceptionlist = NULL; + + for (stmt = *stmts; stmt; stmt = stmt->next) { + curstmtvalue = stmt->value; + if (stmt->flags & StmtFlag_1) { + has_catch_blocks = 1; + dynamic_stack = 1; + requires_frame = 1; + } + + switch (stmt->type) { + case ST_EXPRESSION: + expandTOCexpression(stmt->expr, NULL, 1); + if (stmt->expr->type == ETYPCON && IS_TYPE_VOID(stmt->expr->rtype)) + stmt->expr = stmt->expr->data.monadic; + break; + case ST_GOTOEXPR: + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + if (stmt->expr->type >= ELESS && stmt->expr->type <= ENOTEQU) + stmt->expr = comparewithzero(stmt->expr); + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_RETURN: + if (!stmt->expr) + continue; + expandTOCexpression( + stmt->expr, NULL, + IS_TYPE_ARRAY(stmt->expr->rtype) || IS_TYPE_NONVECTOR_STRUCT(stmt->expr->rtype) || IS_TYPE_CLASS(stmt->expr->rtype) || + IS_TYPE_12BYTES_MEMBERPOINTER(stmt->expr->rtype)); + break; + case ST_SWITCH: + uses_globals = 1; + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_ENDCATCHDTOR: + requires_frame = 1; + makes_call = 1; + break; + case ST_ASM: + if (stmt->expr) { + // TODO - ASM weirdness here + } + break; + } + + checkexceptionreferences(stmt->dobjstack); + } +} + +void resetTOCvarinfo(void) { + ObjectList *list; + + for (list = toclist; list; list = list->next) + list->object->u.toc.info = CodeGen_GetNewVarInfo(); +} + +Boolean needdescriptor(void) { + // completely unused, dunno what args this might take + return 0; +} + +Object *createstaticinitobject(void) { + char buf[100]; + char *p; + Str255 fname; + TypeFunc *tfunc; + Object *obj; + + COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, NULL, NULL, fname); + sprintf(buf, "__sinit_%*.*s", -fname[0], fname[0], &fname[1]); + for (p = &buf[1]; *p; p++) { + if (*p == '.') + *p = '_'; + } + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + tfunc->args = NULL; + tfunc->flags = FUNC_FLAGS_2; + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = (Type *) tfunc; + obj->name = GetHashNameNodeExport(buf); + obj->sclass = OBJECT_SCLASS_102; + obj->datatype = DFUNC; + + return obj; +} + +static void estimate_func_param_size(ENode *node) { + SInt32 work; + ENodeList *list; + SInt32 align; + + work = 0; + for (list = node->data.funccall.args; list; list = list->next) { + align = ~7 & (CMach_ArgumentAlignment(list->node->rtype) + 7); + work += ~(align - 1) & (list->node->rtype->size + align - 1); + } + + estimate_out_param_size(work); +} |