From fcfbafff31869ed808bff0639532db1828660e92 Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Thu, 29 Dec 2022 12:32:55 +0000 Subject: dump lots more code --- .../FrontEnd/Common/CompilerTools.c | 53 +- compiler_and_linker/unsorted/AddPropagation.c | 12 +- compiler_and_linker/unsorted/Alias.c | 30 +- compiler_and_linker/unsorted/CABI.c | 2 +- compiler_and_linker/unsorted/CBrowse.c | 737 +++ compiler_and_linker/unsorted/CDecl.c | 8 +- compiler_and_linker/unsorted/CError.c | 39 +- compiler_and_linker/unsorted/CException.c | 2187 +++++++++ compiler_and_linker/unsorted/CExpr.c | 14 +- compiler_and_linker/unsorted/CExpr2.c | 6 +- compiler_and_linker/unsorted/CExprConvMatch.c | 1 + compiler_and_linker/unsorted/CFunc.c | 2 +- compiler_and_linker/unsorted/CIRTransform.c | 534 +++ compiler_and_linker/unsorted/CInit.c | 54 +- compiler_and_linker/unsorted/CInline.c | 4270 ++++++++++++++++- compiler_and_linker/unsorted/CMachine.c | 78 +- compiler_and_linker/unsorted/CMangler.c | 33 +- compiler_and_linker/unsorted/CObjC.c | 3102 +++++++++++++ compiler_and_linker/unsorted/CObjCModern.c | 181 + compiler_and_linker/unsorted/COptimizer.c | 64 +- compiler_and_linker/unsorted/CPrec.c | 12 +- compiler_and_linker/unsorted/CPreprocess.c | 676 +++ compiler_and_linker/unsorted/CRTTI.c | 940 ++++ compiler_and_linker/unsorted/CSOM.c | 2074 +++++++++ compiler_and_linker/unsorted/CTemplateClass.c | 1632 +++++++ compiler_and_linker/unsorted/CTemplateFunc.c | 1383 ++++++ compiler_and_linker/unsorted/CTemplateNew.c | 1881 ++++++++ compiler_and_linker/unsorted/CTemplateTools.c | 1962 ++++++++ compiler_and_linker/unsorted/CodeGen.c | 80 +- compiler_and_linker/unsorted/CodeMotion.c | 30 +- compiler_and_linker/unsorted/Exceptions.c | 857 ++++ compiler_and_linker/unsorted/FuncLevelAsmPPC.c | 385 +- compiler_and_linker/unsorted/FunctionCalls.c | 642 +++ compiler_and_linker/unsorted/GenStabs.c | 1191 +++++ compiler_and_linker/unsorted/GlobalOptimizer.c | 224 + compiler_and_linker/unsorted/IROUseDef.c | 54 +- compiler_and_linker/unsorted/InlineAsm.c | 3 +- compiler_and_linker/unsorted/InlineAsmPPC.c | 117 +- compiler_and_linker/unsorted/InterferenceGraph.c | 12 +- compiler_and_linker/unsorted/Intrinsics.c | 4894 ++++++++++++++++++++ compiler_and_linker/unsorted/IroBitVect.c | 8 +- compiler_and_linker/unsorted/IroCSE.c | 42 +- compiler_and_linker/unsorted/IroEmptyLoop.c | 21 +- compiler_and_linker/unsorted/IroFlowgraph.c | 3 +- compiler_and_linker/unsorted/IroLinearForm.c | 126 +- compiler_and_linker/unsorted/IroLoop.c | 33 +- compiler_and_linker/unsorted/IroPropagate.c | 10 +- compiler_and_linker/unsorted/IroRangePropagation.c | 6 +- compiler_and_linker/unsorted/IroUtil.c | 51 +- compiler_and_linker/unsorted/IroVars.c | 63 +- compiler_and_linker/unsorted/LoopDetection.c | 9 +- compiler_and_linker/unsorted/LoopOptimization.c | 39 +- compiler_and_linker/unsorted/MachO.c | 878 ++++ compiler_and_linker/unsorted/ObjGenMachO.c | 1810 ++++++++ compiler_and_linker/unsorted/Operands.c | 101 +- compiler_and_linker/unsorted/PCodeAssembly.c | 1603 ++++++- compiler_and_linker/unsorted/PCodeInfo.c | 185 +- compiler_and_linker/unsorted/PCodeListing.c | 30 +- compiler_and_linker/unsorted/PCodeUtilities.c | 46 +- compiler_and_linker/unsorted/PPCError.c | 3 +- compiler_and_linker/unsorted/Peephole.c | 2753 +++++++++++ compiler_and_linker/unsorted/RegisterInfo.c | 28 +- compiler_and_linker/unsorted/ScanFloat.c | 9 + compiler_and_linker/unsorted/Scheduler.c | 3 +- compiler_and_linker/unsorted/SpillCode.c | 36 +- compiler_and_linker/unsorted/StackFrame.c | 91 +- compiler_and_linker/unsorted/StrengthReduction.c | 6 +- compiler_and_linker/unsorted/StructMoves.c | 792 ++++ compiler_and_linker/unsorted/Switch.c | 15 +- compiler_and_linker/unsorted/TOC.c | 48 +- compiler_and_linker/unsorted/Unmangle.c | 1022 ++++ compiler_and_linker/unsorted/ValueNumbering.c | 9 +- compiler_and_linker/unsorted/VectorArraysToRegs.c | 3 +- compiler_and_linker/unsorted/uDump.c | 639 +++ 74 files changed, 39819 insertions(+), 1158 deletions(-) create mode 100644 compiler_and_linker/unsorted/CExprConvMatch.c create mode 100644 compiler_and_linker/unsorted/ScanFloat.c create mode 100644 compiler_and_linker/unsorted/uDump.c (limited to 'compiler_and_linker') diff --git a/compiler_and_linker/FrontEnd/Common/CompilerTools.c b/compiler_and_linker/FrontEnd/Common/CompilerTools.c index 3eae51d..131aa8e 100644 --- a/compiler_and_linker/FrontEnd/Common/CompilerTools.c +++ b/compiler_and_linker/FrontEnd/Common/CompilerTools.c @@ -1,4 +1,5 @@ #include "compiler/CompilerTools.h" +#include "compiler/CInt64.h" #include "cos.h" extern Boolean systemHandles; @@ -140,6 +141,7 @@ void AppendGListTargetEndianWord(GList *gl, SInt16 theword) { ptr = *gl->data + gl->size; gl->size += 2; + theword = CTool_EndianConvertWord16(theword); *(ptr++) = ((unsigned char *) &theword)[0]; *(ptr++) = ((unsigned char *) &theword)[1]; } @@ -170,6 +172,7 @@ void AppendGListTargetEndianLong(GList *gl, SInt32 theword) { ptr = *gl->data + gl->size; gl->size += 4; + theword = CTool_EndianConvertWord32(theword); *(ptr++) = ((unsigned char *) &theword)[0]; *(ptr++) = ((unsigned char *) &theword)[1]; *(ptr++) = ((unsigned char *) &theword)[2]; @@ -1157,26 +1160,56 @@ short getbit(SInt32 l) { } } +#ifdef ENDIAN_CONVERSION +UInt16 CTool_EndianConvertWord16(UInt16 theword) { + UInt16 conv; + ((UInt8 *) &conv)[0] = ((UInt8 *) &theword)[1]; + ((UInt8 *) &conv)[1] = ((UInt8 *) &theword)[0]; + return conv; +} + +UInt32 CTool_EndianConvertWord32(UInt32 theword) { + UInt32 conv; + ((UInt8 *) &conv)[0] = ((UInt8 *) &theword)[3]; + ((UInt8 *) &conv)[1] = ((UInt8 *) &theword)[2]; + ((UInt8 *) &conv)[2] = ((UInt8 *) &theword)[1]; + ((UInt8 *) &conv)[3] = ((UInt8 *) &theword)[0]; + return conv; +} + +void CTool_EndianConvertMem(UInt8 *data, short len) { + UInt8 *a = data; + UInt8 *b = data + len; + while (--b > a) { + UInt8 val = *b; + *b = *a; + *a++ = val; + } +} +#endif + void CTool_EndianConvertWord64(CInt64 ci, char *result) { UInt32 buf[2]; - buf[0] = ci.hi; - buf[1] = ci.lo; + buf[0] = CTool_EndianConvertWord32(CTool_EndianReadWord32(&ci.hi)); + buf[1] = CTool_EndianConvertWord32(CInt64_GetULong(&ci)); memcpy(result, buf, 8); } +#ifdef ENDIAN_CONVERSION +UInt32 CTool_EndianReadWord32(void *ptr) { + return *((UInt32 *) ptr); +} +#endif + UInt16 CTool_EndianConvertInPlaceWord16Ptr(UInt16 *x) { - unsigned short v; - v = *x; - // this probably has a conversion on non-ppc - *x = v; + UInt16 v; + *x = v = CTool_EndianConvertWord16(*x); return v; } UInt32 CTool_EndianConvertInPlaceWord32Ptr(UInt32 *x) { - unsigned long v; - v = *x; - // this probably has a conversion on non-ppc - *x = v; + UInt32 v; + *x = v = CTool_EndianConvertWord32(*x); return v; } diff --git a/compiler_and_linker/unsorted/AddPropagation.c b/compiler_and_linker/unsorted/AddPropagation.c index bf058d4..2084f75 100644 --- a/compiler_and_linker/unsorted/AddPropagation.c +++ b/compiler_and_linker/unsorted/AddPropagation.c @@ -119,8 +119,7 @@ static int addpropagatestouse(int candidateID, int useID) { return 0; } } else { -#line 225 - CError_FATAL(); + CError_FATAL(225); return 0; } @@ -200,8 +199,7 @@ static void propagateandremoveadd(int id) { useInstr->args[2] = instr->args[2]; useInstr->alias = instr->alias; } else if (useInstr->op == PC_ADDI) { -#line 338 - CError_ASSERT(useInstr->args[2].data.imm.value == 0); + CError_ASSERT(338, useInstr->args[2].data.imm.value == 0); change_opcode(useInstr, PC_ADD); useInstr->args[1] = instr->args[1]; useInstr->args[2] = instr->args[2]; @@ -214,8 +212,7 @@ static void propagateandremoveadd(int id) { useInstr->args[2] = instr->args[2]; useInstr->alias = instr->alias; } else { -#line 352 - CError_FATAL(); + CError_FATAL(352); } } else if (useInstr->op == PC_MR) { change_opcode(useInstr, PC_ADDI); @@ -242,8 +239,7 @@ static void propagateandremoveadd(int id) { useInstr->args[2].data.mem.offset, nbytes_loaded_or_stored_by(useInstr)); } else { -#line 382 - CError_FATAL(); + CError_FATAL(382); } } } diff --git a/compiler_and_linker/unsorted/Alias.c b/compiler_and_linker/unsorted/Alias.c index 521421d..4a2f176 100644 --- a/compiler_and_linker/unsorted/Alias.c +++ b/compiler_and_linker/unsorted/Alias.c @@ -164,8 +164,7 @@ void add_alias_member(Alias *parent, Alias *child) { } Alias *make_alias_set_from_IR(void) { -#line 333 - CError_FATAL(); + CError_FATAL(333); return NULL; } @@ -256,8 +255,7 @@ static int addresspropagatestouse(int candidateID, int useID) { return 0; } -#line 478 - CError_ASSERT(object->otype == OT_OBJECT); + CError_ASSERT(478, object->otype == OT_OBJECT); if ((candidate_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (candidate_pcode->flags & fPCodeFlag2000000)) { reg = candidate_pcode->args[1].data.reg.reg; @@ -268,8 +266,7 @@ static int addresspropagatestouse(int candidateID, int useID) { return 0; object = object->u.var.realObj; -#line 495 - CError_ASSERT(object->otype == OT_OBJECT); + CError_ASSERT(495, object->otype == OT_OBJECT); offset = 0; } else if (candidate_pcode->op == PC_ADDI) { if (!candidate_pcode->alias && object) @@ -281,8 +278,7 @@ static int addresspropagatestouse(int candidateID, int useID) { offset = 0; flag24 = 1; } else { -#line 509 - CError_FATAL(); + CError_FATAL(509); } if ( @@ -309,8 +305,7 @@ static int addresspropagatestouse(int candidateID, int useID) { if (use_pcode->argCount < 3) return 1; -#line 543 - CError_ASSERT(use_pcode->args[1].kind == PCOp_REGISTER); + CError_ASSERT(543, use_pcode->args[1].kind == PCOp_REGISTER); if (candidate_pcode->block == use_pcode->block && precedes(candidate_pcode, use_pcode)) { for (scan = candidate_pcode->nextPCode; scan && scan != use_pcode; scan = scan->nextPCode) { @@ -361,8 +356,7 @@ static int addresspropagatestouse(int candidateID, int useID) { } } -#line 598 - CError_ASSERT(object != NULL); + CError_ASSERT(598, object != NULL); if (use_pcode->op == PC_ADDI || use_pcode->op == PC_ADD || use_pcode->op == PC_ADDIS) { if (use_pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR] && !is_safe_const(object)) @@ -653,8 +647,7 @@ static Boolean may_alias_alias(Alias *a, Alias *b) { case (AliasType2 * 3) + AliasType2: return (a == b) || !bitvectorintersectionisempty(a->vec24, b->vec24, n_aliases); default: -#line 1054 - CError_FATAL(); + CError_FATAL(1054); return 1; } } @@ -705,18 +698,15 @@ void update_alias_value(Alias *alias, PCode *pcode) { case AliasType0: killmemory(alias, pcode); for (member = alias->children; member; member = member->nextChild) { -#line 1152 - CError_ASSERT(member->parent->type == AliasType2); + CError_ASSERT(1152, member->parent->type == AliasType2); killmemory(member->parent, NULL); } for (member = alias->parents; member; member = member->nextParent) { -#line 1157 - CError_ASSERT(member->child->type == AliasType1); + CError_ASSERT(1157, member->child->type == AliasType1); killmemory(member->child, NULL); for (member2 = member->child->children; member2; member2 = member2->nextChild) { if (member2->parent != alias) { -#line 1163 - CError_ASSERT(member2->parent->type == AliasType2); + CError_ASSERT(1163, member2->parent->type == AliasType2); killmemory(member2->parent, NULL); } } diff --git a/compiler_and_linker/unsorted/CABI.c b/compiler_and_linker/unsorted/CABI.c index e903797..3e99ca0 100644 --- a/compiler_and_linker/unsorted/CABI.c +++ b/compiler_and_linker/unsorted/CABI.c @@ -50,7 +50,7 @@ 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) {} +void CABI_MakeDefaultArgConstructor(TypeClass *tclass, Object *obj) {} static void CABI_ThisArg() {} ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset) {} static void CABI_VArg() {} diff --git a/compiler_and_linker/unsorted/CBrowse.c b/compiler_and_linker/unsorted/CBrowse.c index e69de29..1e12b91 100644 --- a/compiler_and_linker/unsorted/CBrowse.c +++ b/compiler_and_linker/unsorted/CBrowse.c @@ -0,0 +1,737 @@ +#include "compiler/CBrowse.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CompilerTools.h" +#include "compiler/Unmangle.h" +#include "compiler/objects.h" +#include "compiler/templates.h" +#include "cos.h" +#include "plugin.h" + +Boolean gUseTokenStreamSource; +Boolean gForceSourceLoc; +Boolean gUseNameTable; +static GList gBrowseData; +static GList gClassData; +static GList gMemberFuncList; +static int gNextMemberFuncID; + +enum ELanguage { + langUnknown, + langC, + langCPlus, + langPascal, + langObjectPascal, + langJava, + langAssembler, + langFortran, + langRez +}; + +enum EBrowserItem { + browseFunction, + browseGlobal, + browseClass, + browseMacro, + browseEnum, + browseTypedef, + browseConstant, + browseTemplate, + browsePackage, + browseCompSymbolStart = 0x70, + browseEnd = 0xFF +}; + +enum { + kAbstract = 1, + kStatic = 2, + kFinal = 4, + kMember = 8, + + kInterface = 0x80, + kPublic = 0x100, + + kInline = 0x80, + kPascal = 0x100, + kAsm = 0x200, + kVirtual = 0x400, + kCtor = 0x800, + kDtor = 0x1000, + kNative = 0x2000, + kSynch = 0x4000, + kIntrinsic = 0x8000, + kConst = 0x10000, + + kTransient = 0x80, + kVolatile = 0x100 +}; + +enum EAccess { + accessNone = 0, + accessPrivate = 1, + accessProtected = 2, + accessPublic = 4 +}; + +enum EMember { + memberFunction, + memberData, + memberEnd = 0xFF +}; + +enum ETemplateType { + templateClass, + templateFunction +}; + +static enum EAccess gFromAccessType[] = { + accessPublic, + accessPrivate, + accessProtected, + accessNone +}; + +typedef struct BrowseHeader { + SInt32 browse_header; + SInt32 browse_version; + SInt16 browse_language; + SInt16 uses_name_table; + SInt32 earliest_compatible_version; + SInt32 reserved[15]; +} BrowseHeader; + +// forward decls +static void RecordUndefinedMemberFunctions(void); + +void CBrowse_Setup(CParams *params) { + BrowseHeader hdr; + + CError_ASSERT(123, params != NULL); + + params->objectdata.browsedata = NULL; + + InitGList(&gBrowseData, 0x10000); + InitGList(&gMemberFuncList, 1024); + + gNextMemberFuncID = 1; + gForceSourceLoc = 0; + gUseNameTable = 0; + + memclrw(&hdr, sizeof(hdr)); + hdr.browse_header = 0xBEABBAEB; + hdr.browse_version = 2; + hdr.earliest_compatible_version = 2; + hdr.browse_language = copts.cplusplus ? langCPlus : langC; + hdr.uses_name_table = gUseNameTable; + + AppendGListData(&gBrowseData, &hdr, sizeof(hdr)); +} + +void CBrowse_Finish(CParams *params) { + CWMemHandle hnd; + + CError_ASSERT(151, params != NULL); + + if (gBrowseData.size >= sizeof(BrowseHeader)) { + RecordUndefinedMemberFunctions(); + AppendGListByte(&gBrowseData, -1); + + COS_ResizeHandle(gBrowseData.data, gBrowseData.size); + + if (CWSecretAttachHandle(params->context, gBrowseData.data, &hnd) == cwNoErr) { + params->objectdata.browsedata = hnd; + gBrowseData.data = NULL; + } + } +} + +void CBrowse_Cleanup(CParams *params) { + FreeGList(&gBrowseData); + FreeGList(&gClassData); + FreeGList(&gMemberFuncList); +} + +static void AppendGList(GList *dst, GList *src) { + SInt32 offset = dst->size; + + AppendGListNoData(dst, src->size); + memcpy(*dst->data + offset, *src->data, src->size); +} + +static void RecordName(GList *gl, const char *str, SInt32 id) { + HashNameNode *name; + + CError_ASSERT(190, gl && str && *str); + + if (id < 0 && gUseNameTable) { + for (name = name_hash_nodes[CHash(str)]; name; name = name->next) { + if (!strcmp(str, name->name)) { + id = name->id; + break; + } + } + } + + if (id >= 0 && gUseNameTable) { + AppendGListWord(gl, -1); + AppendGListLong(gl, id); + } else { + int len = strlen(str); + AppendGListWord(gl, len); + if (len) + AppendGListData(gl, str, len + 1); + } +} + +void CBrowse_BeginClass(DeclInfo *di, GList *gl) { + char *buf; + ClassList *base; + SInt32 i; + TypeClass *tclass; + + CError_ASSERT(227, di && di->thetype && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->x60 <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + if (IsTempName(TYPE_CLASS(di->thetype)->classname)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->x60 - 1); + CError_ASSERT(270, gClassData.size == 9); + AppendGListLong(&gClassData, di->x60 - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, TYPE_CLASS(di->thetype)->classname->name, TYPE_CLASS(di->thetype)->classname->id); + + CMangler_MangleType(di->thetype, 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + if (strcmp(TYPE_CLASS(di->thetype)->classname->name, buf)) + RecordName(&gClassData, buf, -1); + else + AppendGListWord(&gClassData, 0); + + AppendGListLong(&gClassData, 0); + + i = 0; + base = TYPE_CLASS(di->thetype)->bases; + while (base) { + base = base->next; + i++; + } + + AppendGListByte(&gClassData, i); + + for (base = TYPE_CLASS(di->thetype)->bases; base; base = base->next) { + AppendGListByte(&gClassData, gFromAccessType[base->access]); + AppendGListByte(&gClassData, base->is_virtual); + + tclass = base->base; + if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->is_specialized) + tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ); + + CMangler_MangleType(TYPE(tclass), 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + i = base->base->classname->id; + while (*buf && *buf >= '0' && *buf <= '9') { + i = -1; + buf++; + } + + RecordName(&gClassData, buf, i); + } +} + +void CBrowse_AddClassMemberVar(ObjMemberVar *ivar, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(360, ivar); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[ivar->access]); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(ivar->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, ivar->name->name, len + 1); + } +} + +void CBrowse_AddClassMemberFunction(Object *object, SInt32 startOffset, SInt32 endOffset) { + SInt32 flags; + SInt32 id; + TypeMethod *tfunc; + + CError_ASSERT(380, object); + + if ( + !IsTempName(object->name) && + gClassData.data && + startOffset > 0 && + endOffset >= startOffset + ) + { + flags = 0; + CError_ASSERT(391, object->type && IS_TYPE_FUNC(object->type)); + tfunc = TYPE_METHOD(object->type); + + if (tfunc->flags & FUNC_FLAGS_100) + return; + + if (object->datatype == DVFUNC) + flags |= kVirtual; + if (tfunc->flags & FUNC_FLAGS_8) + flags |= kAbstract; + if (tfunc->x26) + flags |= kStatic; + if (tfunc->flags & FUNC_FLAGS_1000) + flags |= kCtor; + if (tfunc->flags & FUNC_FLAGS_2000) + flags |= kDtor; + + AppendGListByte(&gClassData, memberFunction); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, flags); + + id = tfunc->x22; + if (id <= 0) { + // TODO: this is not 64-bit safe + if (!(tfunc->flags & FUNC_FLAGS_2) || id == -1) + AppendGListLong(&gMemberFuncList, (SInt32) object); + tfunc->x22 = id = gNextMemberFuncID++; + } + + AppendGListLong(&gClassData, id); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset); + } +} + +void CBrowse_AddClassMemberData(Object *object, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(435, object); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset && object->datatype == DDATA) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, kStatic); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(object->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, object->name->name, len + 1); + } +} + +void CBrowse_EndClass(SInt32 offset, GList *gl) { + CError_ASSERT(453, gl); + + if (gClassData.data) { + if (gClassData.size > 0) { + if (tk == ';') + offset++; + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +void CBrowse_BeginStruct(DeclInfo *di, TypeStruct *tstruct, GList *gl) { + HashNameNode *name; + + CError_ASSERT(480, di && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->x60 <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + name = tstruct->name; + if (!name || IsTempName(name)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->x60 - 1); + CError_ASSERT(521, gClassData.size == 9); + AppendGListLong(&gClassData, di->x60 - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, name->name, name->id); + AppendGListWord(&gClassData, 0); + AppendGListLong(&gClassData, 0); + AppendGListByte(&gClassData, 0); +} + +void CBrowse_AddStructMember(StructMember *member, SInt32 startOffset, SInt32 endOffset) { + short len; + + if (tk == ';') + endOffset++; + + if (gClassData.data && member && startOffset > 0 && endOffset >= startOffset) { + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, accessPublic); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(member->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, member->name->name, len + 1); + } +} + +void CBrowse_EndStruct(SInt32 offset, GList *gl) { + CError_ASSERT(558, gl); + + if (gClassData.data) { + if (offset > 0 && gClassData.size > 0) { + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +static void EmitStandardData(int item, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset, const char *str, SInt32 id, const char *str2, SInt32 id2) { + CError_ASSERT(584, str); + + AppendGListByte(&gBrowseData, item); + AppendGListWord(&gBrowseData, fileID1); + AppendGListWord(&gBrowseData, fileID2); + AppendGListLong(&gBrowseData, startOffset - 1); + AppendGListLong(&gBrowseData, endOffset - 1); + AppendGListLong(&gBrowseData, 0); + + RecordName(&gBrowseData, str, id); + if (str2 && str2 != str) + RecordName(&gBrowseData, str2, id2); + else + AppendGListWord(&gBrowseData, 0); +} + +void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(618, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseTypedef, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(632, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseEnum, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(646, file1 && file1->recordbrowseinfo); + + if (tk == ',') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseConstant, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +static HashNameNode *CBrowse_GetLinkName(Object *object) { + return CMangler_GetLinkName(object); +} + +static void RecordFunction(Object *object, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset) { + TypeFunc *tfunc; + char *tmp; + Boolean flag; + char *str29; + HashNameNode *linkname; + SInt32 flags; + char *namestr; + SInt32 nameid; + char *namestr2; + SInt32 nameid2; + int funcid; + char buf[2048]; + char buf2[256]; + + CError_ASSERT(740, object->type && IS_TYPE_FUNC(object->type)); + + if (IsTempName(object->name)) + return; + + tfunc = TYPE_FUNC(object->type); + if ((tfunc->flags & (FUNC_FLAGS_100 | FUNC_FLAGS_200)) && (!fileID2 || startOffset < 0)) + return; + + linkname = object->name; + tmp = linkname->name; + if (!(linkname->name[0] == '_' && linkname->name[1] == '_')) { + namestr = tmp; + nameid = linkname->id; + switch (tmp[0]) { + case '.': + nameid = -1; + namestr += 1; + break; + case '_': + switch (tmp[1]) { + case '#': + case '%': + case '@': + nameid = -1; + namestr += 2; + break; + } + break; + } + } else { + flag = 1; + if (tfunc->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)) { + tmp = TYPE_METHOD(tfunc)->theclass->classname->name; + while (*tmp >= '0' && *tmp <= '9') + tmp++; + MWUnmangleClassName(tmp, buf, sizeof(buf)); + + str29 = buf; + if ((tmp = strrchr(str29, ':'))) + str29 = tmp + 1; + + if (tfunc->flags & FUNC_FLAGS_2000) { + buf2[0] = '~'; + strncpy(&buf2[1], str29, sizeof(buf2) - 1); + namestr = buf2; + } else { + namestr = str29; + } + + flag = 0; + } + + if (flag) { + MWUnmangle(object->name->name, buf, sizeof(buf)); + namestr = buf; + } + + nameid = -1; + } + + while (*namestr >= '0' && *namestr <= '9') { + nameid = -1; + namestr++; + } + + namestr2 = NULL; + nameid2 = -1; + + linkname = CBrowse_GetLinkName(object); + if (object->name != linkname) { + namestr2 = linkname->name; + if (linkname->name[0] == '.') + namestr2++; + else + nameid2 = linkname->id; + } + + EmitStandardData(browseFunction, fileID1, fileID2, startOffset, endOffset, namestr, nameid, namestr2, nameid2); + + flags = 0; + if (object->qual & Q_INLINE) + flags |= kInline; + if (object->qual & Q_PASCAL) + flags |= kPascal; + if (object->qual & Q_ASM) + flags |= kAsm; + if (object->sclass == TK_STATIC) + flags |= kStatic; + if (tfunc->flags & FUNC_FLAGS_METHOD) + flags |= kMember; + AppendGListLong(&gBrowseData, flags); + + funcid = 0; + if (tfunc->flags & FUNC_FLAGS_METHOD) { + funcid = TYPE_METHOD(tfunc)->x22; + if (funcid <= 0) { + TYPE_METHOD(tfunc)->x22 = funcid = gNextMemberFuncID++; + } + } + AppendGListLong(&gBrowseData, funcid); +} + +void CBrowse_NewFunction(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(890, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && (endOffset + 1) >= startOffset) + RecordFunction(object, file1->fileID, file2->fileID, startOffset, endOffset + 1); +} + +void CBrowse_NewData(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + char *namestr = NULL; + SInt32 flags = 0; + Boolean is_const = is_const_object(object); + + CError_ASSERT(912, file1 && file1->recordbrowseinfo); + CError_ASSERT(913, object); + + if (tk == ';') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + HashNameNode *name = CBrowse_GetLinkName(object); + if (object->name != name) + namestr = name->name; + + EmitStandardData( + is_const ? browseConstant : browseGlobal, + file1->fileID, file2->fileID, + startOffset, endOffset, + object->name->name, object->name->id, + namestr, name->id + ); + + if (!is_const) { + if (object->sclass == TK_STATIC) + flags |= kStatic; + AppendGListLong(&gBrowseData, flags); + } + } +} + +void CBrowse_NewMacro(Macro *macro, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(951, !file || (file->recordbrowseinfo && !macro->is_special)); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) + EmitStandardData( + browseMacro, + file->fileID, file->fileID, + startOffset, endOffset, + macro->name->name, macro->name->id, + NULL, -1 + ); +} + +void CBrowse_NewTemplateClass(TemplClass *tmclass, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(965, !file || file->recordbrowseinfo); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData( + browseTemplate, + file->fileID, file->fileID, + startOffset, endOffset, + tmclass->theclass.classname->name, tmclass->theclass.classname->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateClass); + } +} + +void CBrowse_NewTemplateFunc(TemplateFunction *tmfunc) { + CError_ASSERT(979, !tmfunc->srcfile || tmfunc->srcfile->recordbrowseinfo); + + if (tmfunc->srcfile && tmfunc->srcfile->fileID && tmfunc->startoffset > 0 && tmfunc->endoffset >= tmfunc->startoffset) { + EmitStandardData( + browseTemplate, + tmfunc->srcfile->fileID, tmfunc->srcfile->fileID, + tmfunc->startoffset, tmfunc->endoffset, + tmfunc->name->name, tmfunc->name->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateFunction); + } +} + +static void RecordUndefinedMemberFunctions(void) { + int i; + int count; + Object **array; + + COS_LockHandleHi(gMemberFuncList.data); + + count = gMemberFuncList.size / sizeof(Object *); + array = (Object **) *gMemberFuncList.data; + for (i = 0; i < count; i++, array++) { + if (IS_TYPE_FUNC((*array)->type) && !(TYPE_FUNC((*array)->type)->flags & FUNC_FLAGS_2)) + RecordFunction(*array, 0, 0, -1, -1); + } + + COS_UnlockHandle(gMemberFuncList.data); +} diff --git a/compiler_and_linker/unsorted/CDecl.c b/compiler_and_linker/unsorted/CDecl.c index d6665a6..63f2d0f 100644 --- a/compiler_and_linker/unsorted/CDecl.c +++ b/compiler_and_linker/unsorted/CDecl.c @@ -36,7 +36,7 @@ extern void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *baseclass, 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_CompleteClass(TemplClass *templ, 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); @@ -4647,7 +4647,7 @@ void CDecl_CompleteClass(DeclE *decle, TypeClass *tclass) { if (tclass->sominfo) CSOM_ClassComplete(tclass); - if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->x47) + if ((tclass->flags & CLASS_FLAGS_800) && !TEMPL_CLASS_INST(tclass)->is_specialized) tclass->action = CLASS_ACTION_0; if (!tclass->action) @@ -4860,9 +4860,9 @@ void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class is_templ = (tclass->flags & CLASS_FLAGS_100) ? 1 : 0; if (tclass->flags & CLASS_FLAGS_800) { - TEMPL_CLASS_INST(tclass)->x46 = 1; + TEMPL_CLASS_INST(tclass)->is_instantiated = 1; if (!declinfo->x28) - TEMPL_CLASS_INST(tclass)->x47 = 1; + TEMPL_CLASS_INST(tclass)->is_specialized = 1; } #line 6853 diff --git a/compiler_and_linker/unsorted/CError.c b/compiler_and_linker/unsorted/CError.c index e7493f3..40e237a 100644 --- a/compiler_and_linker/unsorted/CError.c +++ b/compiler_and_linker/unsorted/CError.c @@ -1,14 +1,22 @@ #include "cos.h" +#include "compiler/CClass.h" #include "compiler/CError.h" +#include "compiler/CFunc.h" #include "compiler/CInt64.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CTemplateNew.h" #include "compiler/CompilerTools.h" +#include "compiler/InlineAsm.h" +#include "compiler/Unmangle.h" #include "compiler/enode.h" #include "compiler/objc.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/templates.h" #include "compiler/tokens.h" -#include "compiler.h" TStreamElement *cerror_locktoken; static TStreamElement *cerror_token; @@ -49,8 +57,7 @@ void CError_ResetErrorSkip() { } void CError_GetErrorString(char *buf, short code) { -#line 142 - CError_ASSERT(code >= CErrorStr100 && code < CErrorStrMAX); + CError_ASSERT(142, code >= CErrorStr100 && code < CErrorStrMAX); COS_GetString(buf, 10000, code - 99); } @@ -143,8 +150,7 @@ void CError_BufferAppendTemplArg(CErrorBuffer *eb, TemplArg *targ) { CError_BufferAppendType(eb, targ->data.ttargtype, 0); break; default: -#line 300 - CError_FATAL(); + CError_FATAL(300); } } @@ -238,8 +244,7 @@ void CError_BufferAppendTemplDepType(CErrorBuffer *eb, TypeTemplDep *type) { CError_BufferAppendChar(eb, ']'); break; default: -#line 463 - CError_FATAL(); + CError_FATAL(463); } } @@ -350,8 +355,7 @@ void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual) { CError_BufferAppendString(eb, "long double"); break; default: -#line 584 - CError_FATAL(); + CError_FATAL(584); } break; case TYPEENUM: @@ -384,8 +388,7 @@ void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual) { case STRUCT_TYPE_E: break; default: -#line 618 - CError_FATAL(); + CError_FATAL(618); } if (TYPE_STRUCT(ty)->name) CError_BufferAppendString(eb, TYPE_STRUCT(ty)->name->name); @@ -482,8 +485,7 @@ void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual) { CError_BufferAppendString(eb, buf); break; default: -#line 752 - CError_FATAL(); + CError_FATAL(752); } } @@ -625,8 +627,7 @@ char *CError_GetNameString(NameSpace *nspace, HashNameNode *operatorName) { char *ptr; char *opStr; -#line 973 - CError_ASSERT(operatorName); + CError_ASSERT(973, operatorName); opStr = CMangler_GetOperator(operatorName); if (!opStr) @@ -784,8 +785,7 @@ void CError_ErrorMessageVA(int code, const char *format, va_list list, Boolean f format += 2; continue; default: -#line 1174 - CError_FATAL(); + CError_FATAL(1174); } break; default: @@ -855,8 +855,7 @@ void CError_ErrorFuncCall(short code, NameSpaceObjectList *args, ENodeList *argN while (args && args->object->otype != OT_OBJECT) args = args->next; -#line 1268 - CError_ASSERT(args); + CError_ASSERT(1268, args); p = string; do { @@ -956,7 +955,7 @@ void CError_OverloadedFunctionError(Object *obj, ObjectList *olst) { } void CError_AbstractClassError(TypeClass *tclass) { - int result = CClass_CheckPures(tclass); + Object *result = CClass_CheckPures(tclass); if (!result) CError_Error(372, tclass, 0); else diff --git a/compiler_and_linker/unsorted/CException.c b/compiler_and_linker/unsorted/CException.c index e69de29..2fdd2d3 100644 --- a/compiler_and_linker/unsorted/CException.c +++ b/compiler_and_linker/unsorted/CException.c @@ -0,0 +1,2187 @@ +#include "compiler/CException.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/CInline.h" +#include "compiler/CInit.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +typedef struct UniqueObj { + struct UniqueObj *next; + Object *object; + SInt32 uniqueid; +} UniqueObj; + +typedef struct DtorTemp { + struct DtorTemp *next; + Object *object; + Object *dtor; + Object *temp; +} DtorTemp; + +ExceptionAction *cexcept_dobjstack; +Boolean cexcept_hasdobjects; +Boolean cexcept_magic; +static UniqueObj *cexcept_uniqueobjs; +static Boolean cexcept_canthrow; +static DtorTemp *cexcept_dtortemps; +static Statement *cexcept_prevstmt; +static ExceptionAction *cexcept_eabefore; +static ExceptionAction *cexcept_eaafter; +static Boolean cexcept_expandtrycatch; +static Boolean cexcept_hastrycatch; +static Boolean cexcept_serialize; + +// forward decls +static ENode *CExcept_TempTransExprCond(ENode *expr); +static ENode *CExcept_TempTransExpr(ENode *expr); + +void CExcept_Setup(void) { + cexcept_dobjstack = NULL; + cexcept_uniqueobjs = NULL; + cexcept_hasdobjects = 0; + cexcept_magic = 0; +} + +Boolean CExcept_CanThrowException(Object *object, Boolean flag) { + if (copts.optEH && IS_TYPE_FUNC(object->type)) { + if (flag) + return 1; + + if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_NOTHROW) + return 0; + + if ( + !flag && + TYPE_FUNC(object->type)->exspecs && + TYPE_FUNC(object->type)->exspecs && + !TYPE_FUNC(object->type)->exspecs->type + ) + return 0; + + if ( + copts.optEH2 && + !(object->qual & Q_80000) && + object != rt_ptmf_call && + object != rt_ptmf_scall && + object != Rdync_func && + 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 != Xthrw_func + ) + return 0; + } + + return 1; +} + +void CExcept_CheckStackRefs(ExceptionAction *actions) { + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCAL: + CInline_ObjectAddrRef(actions->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_ObjectAddrRef(actions->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_ObjectAddrRef(actions->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_ObjectAddrRef(actions->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_ObjectAddrRef(actions->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + CInline_ObjectAddrRef(actions->data.destroy_partial_array.dtor); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_ObjectAddrRef(actions->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_ObjectAddrRef(actions->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_ObjectAddrRef(actions->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_ObjectAddrRef(actions->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_ObjectAddrRef(actions->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(192); + } + actions = actions->prev; + } +} + +void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b) { + ExceptSpecList *aa; + ExceptSpecList *bb; + + aa = a; + bb = b; + while (1) { + if (!aa) { + if (!bb) + break; + CError_Error(CErrorStr265); + return; + } + + if (!bb) { + CError_Error(CErrorStr265); + return; + } + + aa = aa->next; + bb = bb->next; + } + + if (a->type == NULL) { + if (b->type != NULL) + CError_Error(CErrorStr265); + } else if (b->type == NULL) { + CError_Error(CErrorStr265); + } else { + for (aa = a; aa; aa = aa->next) { + for (bb = b; bb; bb = bb->next) { + if (is_typesame(aa->type, bb->type) && aa->qual == bb->qual) + break; + } + + if (bb == NULL) { + CError_Error(CErrorStr265); + return; + } + } + } +} + +Boolean CExcept_ActionCompare(ExceptionAction *a, ExceptionAction *b) { + if (a->type == b->type) { + switch (a->type) { + case EAT_DESTROYLOCAL: + return a->data.destroy_local.local == b->data.destroy_local.local; + case EAT_DESTROYLOCALCOND: + return a->data.destroy_local_cond.local == b->data.destroy_local_cond.local; + case EAT_DESTROYLOCALOFFSET: + return a->data.destroy_local_offset.local == b->data.destroy_local_offset.local && + a->data.destroy_local_offset.offset == b->data.destroy_local_offset.offset; + case EAT_DESTROYLOCALPOINTER: + return a->data.destroy_local_pointer.pointer == b->data.destroy_local_pointer.pointer; + case EAT_DESTROYLOCALARRAY: + return a->data.destroy_local_array.localarray == b->data.destroy_local_array.localarray; + case EAT_DESTROYPARTIALARRAY: + return a->data.destroy_partial_array.arraypointer == b->data.destroy_partial_array.arraypointer; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + return a->data.destroy_member.objectptr == b->data.destroy_member.objectptr && + a->data.destroy_member.offset == b->data.destroy_member.offset; + case EAT_DESTROYMEMBERCOND: + return a->data.destroy_member_cond.objectptr == b->data.destroy_member_cond.objectptr && + a->data.destroy_member_cond.offset == b->data.destroy_member_cond.offset; + case EAT_DESTROYMEMBERARRAY: + return a->data.destroy_member_array.objectptr == b->data.destroy_member_array.objectptr && + a->data.destroy_member_array.offset == b->data.destroy_member_array.offset; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + return a->data.delete_pointer.pointerobject == b->data.delete_pointer.pointerobject && + a->data.delete_pointer.deletefunc == b->data.delete_pointer.deletefunc; + case EAT_DELETEPOINTERCOND: + return a->data.delete_pointer_cond.cond == b->data.delete_pointer_cond.cond; + case EAT_CATCHBLOCK: + return a->data.catch_block.catch_label == b->data.catch_block.catch_label; + case EAT_ACTIVECATCHBLOCK: + return a->data.active_catch_block.catch_info_object == b->data.active_catch_block.catch_info_object; + case EAT_TERMINATE: + return 1; + case EAT_SPECIFICATION: + return a->data.specification.unexp_id == b->data.specification.unexp_id; + default: + CError_FATAL(314); + } + } + + return 0; +} + +int CExcept_IsSubList(ExceptionAction *a, ExceptionAction *b) { + int diff; + int i; + int count1; + int count2; + ExceptionAction *scan; + + if (a == b) + return 0; + + count1 = 0; + scan = a; + while (scan) { + scan = scan->prev; + count1++; + } + + scan = b; + count2 = 0; + while (scan) { + scan = scan->prev; + count2++; + } + + diff = count2 - count1; + if (diff < 0) + return -1; + + for (i = 0; i < diff; i++) + b = b->prev; + + while (a != b) { + if (!a || !b || !CExcept_ActionCompare(a, b)) + return -1; + a = a->prev; + b = b->prev; + } + + return diff; +} + +Boolean CExcept_ActionNeedsDestruction(ExceptionAction *action) { + switch (action->type) { + case EAT_CATCHBLOCK: + return 0; + case EAT_DESTROYLOCAL: + case EAT_DESTROYLOCALOFFSET: + case EAT_DESTROYLOCALARRAY: + case EAT_DELETELOCALPOINTER: + case EAT_ACTIVECATCHBLOCK: + return 1; + case EAT_NOP: + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_DESTROYBASE: + break; + default: + CError_FATAL(363); + } + + return 0; +} + +ENode *CExcept_RegisterDestructorObject(Object *local, SInt32 offset, Object *dtor, Boolean flag) { + ExceptionAction *action; + ENode *expr; + Object *dtorObject; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + expr = create_objectrefnode(local); + dtorObject = CABI_GetDestructorObject(dtor, 1); + + if (offset == 0) { + action->type = EAT_DESTROYLOCAL; + action->data.destroy_local.local = local; + action->data.destroy_local.dtor = dtorObject; + } else { + action->type = EAT_DESTROYLOCALOFFSET; + action->data.destroy_local_offset.local = local; + action->data.destroy_local_offset.dtor = dtorObject; + action->data.destroy_local_offset.offset = offset; + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + } + + cexcept_hasdobjects = 1; + return expr; +} + +void CExcept_RegisterLocalArray(Statement *stmt, Object *localarray, Object *dtor, SInt32 elements, SInt32 element_size) { + ExceptionAction *action; + Object *dtorObject; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + dtorObject = CABI_GetDestructorObject(dtor, 1); + + action->type = EAT_DESTROYLOCALARRAY; + action->data.destroy_local_array.localarray = localarray; + action->data.destroy_local_array.dtor = dtorObject; + action->data.destroy_local_array.elements = elements; + action->data.destroy_local_array.element_size = element_size; + + cexcept_hasdobjects = 1; +} + +void CExcept_RegisterDeleteObject(Statement *stmt, Object *pointerobject, Object *deletefunc) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + action->type = EAT_DELETELOCALPOINTER; + action->data.delete_pointer.pointerobject = pointerobject; + action->data.delete_pointer.deletefunc = deletefunc; + + cexcept_hasdobjects = 1; +} + +static void CExcept_PatchConstructorAction(Statement *stmt, ExceptionAction *actionArg) { + ExceptionAction *action30; + ExceptionAction *action; + ExceptionAction *scan; + + for (action = stmt->dobjstack; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_SPECIFICATION: + case EAT_DESTROYBASE: + goto exitFirstLoop; + case EAT_CATCHBLOCK: + action30 = action; + while (1) { + if (!action30->prev) + goto exitFirstLoop; + action30 = action30->prev; + if (action30->type != EAT_CATCHBLOCK) { + CError_FATAL(481); + } + } + } + } + exitFirstLoop: + if (action == NULL) { + while (stmt) { + if ((scan = stmt->dobjstack)) { + while (1) { + if (scan == actionArg) + break; + if (scan->prev == NULL) { + scan->prev = actionArg; + break; + } + scan = scan->prev; + } + } else { + stmt->dobjstack = actionArg; + } + stmt = stmt->next; + } + } else { + actionArg->prev = action; + while (stmt) { + if (stmt->dobjstack != action) { + scan = stmt->dobjstack; + do { + if (scan == actionArg) + goto nextStmt; + if (scan->prev == action) { + scan->prev = actionArg; + goto nextStmt; + } + } while ((scan = scan->prev)); + + while (1) { + if (action->type == EAT_CATCHBLOCK && action->prev == NULL) + return; + + action = action->prev; + if (!action) + CError_FATAL(531); + } + } else { + stmt->dobjstack = actionArg; + } + nextStmt: + stmt = stmt->next; + } + } +} + +void CExcept_Terminate(void) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_TERMINATE; + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; +} + +void CExcept_Magic(void) { + cexcept_magic = 1; +} + +static Object *CExcept_FindLocalObject(char *name) { + CScopeParseResult result; + NameSpaceObjectList *list; + + list = CScope_FindObjectList(&result, GetHashNameNodeExport(name)); + if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) + return OBJECT(list->object); + + CError_FATAL(580); + return NULL; +} + +void CExcept_ArrayInit(void) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_DESTROYPARTIALARRAY; + action->data.destroy_partial_array.arraypointer = CExcept_FindLocalObject("ptr"); + action->data.destroy_partial_array.arraycounter = CExcept_FindLocalObject("i"); + action->data.destroy_partial_array.dtor = CExcept_FindLocalObject("dtor"); + action->data.destroy_partial_array.element_size = CExcept_FindLocalObject("size"); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; +} + +void CExcept_RegisterMember(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, Object *cond, Boolean isMember) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + if (cond == NULL) { + if (isMember) { + action->type = EAT_DESTROYMEMBER; + action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, 1); + } else { + action->type = EAT_DESTROYBASE; + action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, 0); + } + action->data.destroy_member.objectptr = objectptr; + action->data.destroy_member.offset = offset; + } else { + CError_ASSERT(632, cond->type == TYPE(&stsignedshort)); + action->type = EAT_DESTROYMEMBERCOND; + action->data.destroy_member_cond.objectptr = objectptr; + action->data.destroy_member_cond.cond = cond; + action->data.destroy_member_cond.dtor = CABI_GetDestructorObject(dtor, 1); + action->data.destroy_member_cond.offset = offset; + } + + CExcept_PatchConstructorAction(stmt, action); + stmt->flags |= StmtFlag_2; +} + +void CExcept_RegisterMemberArray(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, SInt32 elements, SInt32 element_size) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_DESTROYMEMBERARRAY; + action->data.destroy_member_array.objectptr = objectptr; + action->data.destroy_member_array.dtor = CABI_GetDestructorObject(dtor, 1); + action->data.destroy_member_array.offset = offset; + action->data.destroy_member_array.elements = elements; + action->data.destroy_member_array.element_size = element_size; + + CExcept_PatchConstructorAction(stmt, action); + stmt->flags |= StmtFlag_2; +} + +static Statement *CExcept_DestroyLocal(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 offset) { + ENode *expr; + + expr = create_objectrefnode(object); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + expr = CABI_DestroyObject(dtor, expr, 1, 1, 0); + + CError_ASSERT(687, expr->type == EFUNCCALL && expr->data.funccall.funcref->type == EOBJREF); + if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC) + expr->data.funccall.funcref->flags |= ENODE_FLAG_80; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + stmt->dobjstack = ea->prev; + return stmt; +} + +static Statement *CExcept_DestroyLocalPointer(ExceptionAction *ea, Statement *stmt, Object *object, Object *deletefunc) { + Statement *newStmt; + + newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + newStmt->expr = funccallexpr(deletefunc, create_objectnode2(object), NULL, NULL, NULL); + newStmt->dobjstack = ea->prev; + return newStmt; +} + +static Statement *CExcept_DestroyLocalArray(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 elements, SInt32 element_size) { + Statement *newStmt; + ENode *dtorExpr; + + newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + + if (dtor) + dtorExpr = create_objectrefnode(CABI_GetDestructorObject(dtor, 1)); + else + dtorExpr = nullnode(); + + newStmt->expr = funccallexpr( + darr_func, + create_objectrefnode(object), + dtorExpr, + intconstnode(TYPE(&stunsignedlong), element_size), + intconstnode(TYPE(&stunsignedlong), elements) + ); + + newStmt->dobjstack = ea->prev; + return newStmt; +} + +static Statement *CExcept_EndCatch(ExceptionAction *ea, Statement *stmt) { + stmt = CFunc_InsertStatement(ST_ENDCATCHDTOR, stmt); + stmt->expr = create_objectrefnode(ea->data.active_catch_block.catch_info_object); + stmt->dobjstack = ea->prev; + if (!ea->data.active_catch_block.call_dtor) + stmt->type = ST_ENDCATCH; + return stmt; +} + +Statement *CExcept_ActionCleanup(ExceptionAction *ea, Statement *stmt) { + switch (ea->type) { + case EAT_DESTROYLOCALCOND: + case EAT_DESTROYLOCALPOINTER: + case EAT_DESTROYPARTIALARRAY: + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_DELETEPOINTER: + case EAT_DELETEPOINTERCOND: + case EAT_CATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + case EAT_DESTROYBASE: + break; + case EAT_DESTROYLOCAL: + stmt = CExcept_DestroyLocal( + ea, stmt, + ea->data.destroy_local.local, + ea->data.destroy_local.dtor, + 0); + break; + case EAT_DESTROYLOCALOFFSET: + stmt = CExcept_DestroyLocal( + ea, stmt, + ea->data.destroy_local.local, + ea->data.destroy_local.dtor, + ea->data.destroy_local_offset.offset); + break; + case EAT_DELETELOCALPOINTER: + stmt = CExcept_DestroyLocalPointer( + ea, stmt, + ea->data.delete_pointer.pointerobject, + ea->data.delete_pointer.deletefunc); + break; + case EAT_DESTROYLOCALARRAY: + stmt = CExcept_DestroyLocalArray( + ea, stmt, + ea->data.destroy_local_array.localarray, + ea->data.destroy_local_array.dtor, + ea->data.destroy_local_array.elements, + ea->data.destroy_local_array.element_size); + break; + case EAT_ACTIVECATCHBLOCK: + stmt = CExcept_EndCatch(ea, stmt); + break; + default: + CError_FATAL(827); + } + + return stmt; +} + +static void CExcept_MangleNameSpaceName(NameSpace *nspace) { + while (nspace) { + if (nspace->name) { + CExcept_MangleNameSpaceName(nspace->parent); + AppendGListName(&name_mangle_list, nspace->name->name); + AppendGListName(&name_mangle_list, "::"); + break; + } + nspace = nspace->parent; + } +} + +static void CExcept_MangleClassName(TypeClass *tclass) { + NameSpace *nspace; + char buf[64]; + + CExcept_MangleNameSpaceName(tclass->nspace->parent); + AppendGListName(&name_mangle_list, tclass->classname->name); + + for (nspace = tclass->nspace->parent; nspace; nspace = nspace->parent) { + if (!nspace->is_global && !nspace->is_templ && !nspace->name) { + CError_ASSERT(868, cscope_currentfunc != NULL); + + sprintf(buf, "*%lx*%lx*", &cscope_currentfunc, &nspace); + AppendGListName(&name_mangle_list, buf); + break; + } + } +} + +typedef struct BCL { + struct BCL *next; + TypeClass *tclass; + SInt32 offset; + Boolean is_virtual; + Boolean is_public; + Boolean is_ambig; +} BCL; + +static void CExcept_MakeBaseClassListAmbig(BCL *bcl, TypeClass *tclass) { + BCL *scan; + ClassList *list; + + for (scan = bcl; scan; scan = scan->next) { + if (scan->tclass == tclass) + scan->is_ambig = 1; + } + + for (list = tclass->bases; list; list = list->next) + CExcept_MakeBaseClassListAmbig(bcl, list->base); +} + +static BCL *CExcept_GetBaseClassList(BCL *bcl, TypeClass *tclass1, TypeClass *tclass2, SInt32 offset, Boolean is_virtual, Boolean is_public) { + BCL *node; + ClassList *base; + Boolean new_is_public; + + for (node = bcl; node; node = node->next) { + if (node->tclass == tclass2) { + if (is_virtual && node->is_virtual) { + if (is_public) + node->is_public = 1; + } else { + CExcept_MakeBaseClassListAmbig(bcl, tclass2); + } + return bcl; + } + } + + node = lalloc(sizeof(BCL)); + node->tclass = tclass2; + node->offset = offset; + node->is_virtual = is_virtual; + node->is_public = is_public; + node->is_ambig = 0; + node->next = bcl; + bcl = node; + + for (base = tclass2->bases; base; base = base->next) { + new_is_public = is_public && (base->access == ACCESSPUBLIC); + bcl = base->is_virtual + ? CExcept_GetBaseClassList(bcl, tclass1, base->base, CClass_VirtualBaseOffset(tclass1, base->base), 1, new_is_public) + : CExcept_GetBaseClassList(bcl, tclass1, base->base, offset + base->offset, 0, new_is_public); + } + + return bcl; +} + +static void CExcept_MangleClass(TypeClass *tclass) { + BCL *bcl; + char buf[20]; + + for (bcl = CExcept_GetBaseClassList(NULL, tclass, tclass, 0, 0, 1); bcl; bcl = bcl->next) { + if (bcl->is_public && !bcl->is_ambig) { + CExcept_MangleClassName(bcl->tclass); + AppendGListByte(&name_mangle_list, '!'); + + if (bcl->offset) { + sprintf(buf, "%ld!", bcl->offset); + AppendGListName(&name_mangle_list, buf); + } else { + AppendGListByte(&name_mangle_list, '!'); + } + } + } +} + +static ENode *CExcept_GetTypeID(Type *type, UInt32 qual, Boolean flag) { + ENode *expr; + TypePointer my_tptr; + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) || (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_CLASS(TPTR_TARGET(type)))) { + name_mangle_list.size = 0; + if (IS_TYPE_POINTER_ONLY(type)) { + AppendGListByte(&name_mangle_list, '*'); + type = TPTR_TARGET(type); + } else { + AppendGListByte(&name_mangle_list, '!'); + } + + if (flag) { + CExcept_MangleClass(TYPE_CLASS(type)); + } else { + CExcept_MangleClassName(TYPE_CLASS(type)); + AppendGListByte(&name_mangle_list, '!'); + } + } else { + if (IS_TYPE_POINTER_ONLY(type)) { + if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { + my_tptr = *TYPE_POINTER(type); + my_tptr.qual = 0; + type = TYPE(&my_tptr); + } + } else { + qual = 0; + } + CMangler_MangleType(type, qual); + } + + AppendGListByte(&name_mangle_list, 0); + + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewPointerType(TYPE(&stchar)); + expr->data.string.size = name_mangle_list.size; + expr->data.string.data = galloc(name_mangle_list.size); + memcpy(expr->data.string.data, *name_mangle_list.data, name_mangle_list.size); + return expr; +} + +static Object *CExcept_TypeID(Type *type, UInt32 qual) { + ENode *expr = CExcept_GetTypeID(type, qual, 0); + CError_ASSERT(1086, expr->type == ESTRINGCONST); + return CInit_DeclareString(expr->data.string.data, expr->data.string.size, 0, 0); +} + +void CExcept_ScanExceptionSpecification(TypeFunc *tfunc) { + ExceptSpecList *exspecs; + ExceptSpecList *exspec; + DeclInfo di; + + exspecs = NULL; + + if (lex() != '(') { + CError_Error(CErrorStr114); + return; + } + + if ((tk = lex()) != ')') { + while (1) { + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); + + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr146); + + if (IS_TYPE_POINTER_ONLY(di.thetype)) { + if (TPTR_QUAL(di.thetype) & (Q_CONST | Q_VOLATILE)) { + TypePointer *newtype = galloc(sizeof(TypePointer)); + *newtype = *TYPE_POINTER(di.thetype); + newtype->qual = 0; + di.thetype = TYPE(newtype); + } + } else { + di.qual = 0; + } + + for (exspec = exspecs; exspec; exspec = exspec->next) { + if (is_typesame(exspec->type, di.thetype) && exspec->qual == di.qual) + break; + } + + if (!exspec) { + exspec = galloc(sizeof(ExceptSpecList)); + memclrw(exspec, sizeof(ExceptSpecList)); + exspec->next = exspecs; + exspec->type = di.thetype; + exspec->qual = di.qual; + exspecs = exspec; + } + + if (tk == ')') + break; + + if (tk != ',') { + CError_Error(CErrorStr115); + break; + } + + tk = lex(); + } + } + + if (!exspecs) { + exspecs = galloc(sizeof(ExceptSpecList)); + memclrw(exspecs, sizeof(ExceptSpecList)); + } + tfunc->exspecs = exspecs; + tk = lex(); +} + +static ENode *CExcept_CallCopyCtor(Object *object, Type *type, ENode *expr1, ENode *expr2) { + ENodeList *list; + ENode *expr; + FuncArg *arg; + + if ( + !IS_TYPE_FUNC(object->type) || + !(arg = TYPE_FUNC(object->type)->args) || + !(arg = arg->next) + ) + CError_FATAL(1169); + + expr = funccallexpr(object, expr1, NULL, NULL, NULL); + list = expr->data.funccall.args; + + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_20) { + CError_ASSERT(1179, arg = arg->next); + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = intconstnode(TYPE(&stsignedshort), 1); + } + + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = expr2; + + while ((arg = arg->next)) { + CError_ASSERT(1195, arg->dexpr); + + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg); + } + + return expr; +} + +ENode *CExcept_ScanThrowExpression(void) { + ENode *expr; + Object *func; + ENode *resultExpr; + Object *obj; + ENode *thrownExpr; + ENode *tempExpr; + + if (!copts.exceptions) + CError_Error(CErrorStr252); + + switch ((tk = lex())) { + case ')': + case ',': + case ':': + case ';': + expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + break; + default: + thrownExpr = pointer_generation(assignment_expression()); + obj = create_temp_object(thrownExpr->rtype); + if (!IS_TYPE_CLASS(thrownExpr->rtype) || !(resultExpr = CExpr_IsTempConstruction(thrownExpr, thrownExpr->rtype, &expr))) { + tempExpr = create_objectrefnode(obj); + if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_CopyConstructor(TYPE_CLASS(thrownExpr->rtype)))) { + resultExpr = CExcept_CallCopyCtor(func, thrownExpr->rtype, tempExpr, getnodeaddress(thrownExpr, 0)); + } else { + if (thrownExpr->rtype->size == 0) + CError_Error(CErrorStr146); + + tempExpr = makemonadicnode(tempExpr, EINDIRECT); + tempExpr->rtype = thrownExpr->rtype; + resultExpr = makediadicnode(tempExpr, thrownExpr, EASS); + resultExpr = makediadicnode(resultExpr, create_objectrefnode(obj), ECOMMA); + resultExpr->rtype = TYPE(&void_ptr); + } + } else { + *expr = *create_objectrefnode(obj); + } + + expr = CExcept_GetTypeID(thrownExpr->rtype, ENODE_QUALS(thrownExpr), 1); + if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_Destructor(TYPE_CLASS(thrownExpr->rtype)))) { + expr = funccallexpr( + Xthrw_func, + expr, + resultExpr, + create_objectrefnode(CABI_GetDestructorObject(func, 1)), + NULL); + } else { + expr = funccallexpr( + Xthrw_func, + expr, + resultExpr, + nullnode(), + NULL); + } + } + + expr->flags |= ENODE_FLAG_VOLATILE; + return expr; +} + +static Boolean CExcept_MightNeedDtor(Type *type) { + if (type) { + if (IS_TYPE_CLASS(type)) { + if (!CClass_Destructor(TYPE_CLASS(type))) + return 0; + } else if (IS_TYPE_POINTER_ONLY(type)) { + if (!(TPTR_QUAL(type) & Q_REFERENCE) || !IS_TYPE_CLASS(TPTR_TARGET(type))) + return 0; + } else { + return 0; + } + } + + return 1; +} + +typedef struct CatchBlock { + struct CatchBlock *next; + Object *catch_object; + Object *catch_info_object; + Statement *stmt; + Statement *anotherStmt; + Type *type; + UInt32 qual; +} CatchBlock; + +static void CExcept_PatchDObjStack(Statement *beginCatchStmt, Statement *tryEndStmt, Statement *endStmt, CatchBlock *catchBlock) { + ExceptionAction *ea; + ExceptionAction *stackHead; + ExceptionAction *stackTail; + ExceptionAction *firstEA; + Statement *stmt; + Object *catch_info_object; + Boolean call_dtor; + + catch_info_object = catchBlock->catch_info_object; + call_dtor = 0; + stackHead = stackTail = beginCatchStmt->dobjstack; + firstEA = NULL; + + while (catchBlock) { + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + + ea->prev = stackTail; + stackTail = ea; + + if (!firstEA) + firstEA = ea; + + ea->type = EAT_CATCHBLOCK; + ea->data.catch_block.catch_object = catchBlock->catch_object; + ea->data.catch_block.catch_label = catchBlock->stmt->label; + if (catchBlock->type) + ea->data.catch_block.catch_typeid = CExcept_TypeID(catchBlock->type, catchBlock->qual); + ea->data.catch_block.catch_info_object = catch_info_object; + + if (!call_dtor && CExcept_MightNeedDtor(catchBlock->type)) + call_dtor = 1; + + ea->data.catch_block.catch_type = catchBlock->type; + ea->data.catch_block.catch_qual = catchBlock->qual; + catchBlock = catchBlock->next; + } + + stmt = beginCatchStmt; + while (1) { + if ((ea = stmt->dobjstack) != stackHead) { + while (1) { + CError_ASSERT(1404, ea); + if (ea->prev == stackTail) + break; + if (ea->prev == stackHead) { + ea->prev = stackTail; + break; + } + ea = ea->prev; + } + } else { + stmt->dobjstack = stackTail; + } + + if (stmt == endStmt) + break; + + if (stmt == tryEndStmt) { + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->prev = stackHead; + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->data.active_catch_block.call_dtor = call_dtor; + stackTail = ea; + } + + stmt = stmt->next; + CError_ASSERT(1426, stmt); + } + + cexcept_hasdobjects = 1; +} + +static void CExcept_CheckTryObjects(ENode *expr) { + if (expr->data.objref->datatype == DLOCAL && expr->data.objref->u.var.info) + expr->data.objref->u.var.info->noregister = 1; +} + +static ENode *CExcept_CatchExpressionInit(DeclInfo *di, CatchBlock *catchBlock) { + Object *catch_object; + Object *copyCtor; + Object *dtor; + ENode *expr; + + if (CScope_FindName(cscope_current, di->name)) + CError_Error(CErrorStr122, di->name->name); + + catch_object = CParser_NewLocalDataObject(di, 1); + CFunc_SetupLocalVarInfo(catch_object); + CScope_AddObject(cscope_current, di->name, OBJ_BASE(catch_object)); + catchBlock->catch_object = catch_object; + + expr = makediadicnode( + create_objectrefnode(catchBlock->catch_info_object), + intconstnode(TYPE(&stunsignedlong), 12), + EADD); + expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(di->thetype)); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = CDecl_NewPointerType(di->thetype); + + if (IS_TYPE_REFERENCE(di->thetype)) + return makediadicnode(create_objectnode2(catch_object), expr, EASS); + + if (IS_TYPE_CLASS(di->thetype) && (copyCtor = CClass_CopyConstructor(TYPE_CLASS(di->thetype)))) { + dtor = CClass_Destructor(TYPE_CLASS(di->thetype)); + return CExcept_CallCopyCtor( + copyCtor, + di->thetype, + (dtor == NULL) ? create_objectrefnode(catch_object) : CExcept_RegisterDestructorObject(catch_object, 0, dtor, 0), + expr); + } + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = di->thetype; + return makediadicnode(create_objectnode(catch_object), expr, EASS); +} + +void CExcept_ScanTryBlock(DeclThing *dt, Boolean flag) { + Object *catch_info_object; // r27 + Statement *beginCatchStmt; // r14 + Statement *tryEndStmt; // r16 + Statement *endStmt; // r17 + Statement *stmt; // r14 + CLabel *catchEndLabel; // r19 + CLabel *endLabel; // r24 + CatchBlock *catchStack; // r23 + CatchBlock *catchBlock; // r22 + DeclBlock *declBlock; // r20 + DeclInfo di; + + if (!copts.exceptions) + CError_Error(CErrorStr252); + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + if (cexcept_magic) { + catch_info_object->name = GetHashNameNodeExport("__exception_magic"); + CScope_AddObject(cscope_current, catch_info_object->name, OBJ_BASE(catch_info_object)); + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->flags = StmtFlag_1; + stmt->label = newlabel(); + stmt->label->stmt = stmt; + + beginCatchStmt = CFunc_AppendStatement(ST_BEGINCATCH); + beginCatchStmt->expr = create_objectrefnode(catch_info_object); + + if (tk != '{') { + CError_Error(CErrorStr135); + return; + } + + CFunc_CompoundStatement(dt); + + if (tk != TK_CATCH) { + CError_Error(CErrorStr242); + return; + } + + stmt = CFunc_AppendStatement(ST_GOTO); + catchEndLabel = stmt->label = newlabel(); + tryEndStmt = stmt; + + endLabel = newlabel(); + catchStack = NULL; + + while (1) { + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->flags = StmtFlag_1; + stmt->label = newlabel(); + stmt->label->stmt = stmt; + + declBlock = NULL; + + catchBlock = lalloc(sizeof(ExceptionAction)); + memclrw(catchBlock, sizeof(ExceptionAction)); + catchBlock->next = catchStack; + catchStack = catchBlock; + + catchBlock->stmt = stmt; + catchBlock->catch_info_object = catch_info_object; + + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + break; + } + + if ((tk = lex()) == TK_ELLIPSIS) { + tk = lex(); + } else { + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.x48) + CError_Error(CErrorStr121); + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); + + scandeclarator(&di); + + if (IS_TYPE_FUNC(di.thetype)) + di.thetype = CDecl_NewPointerType(di.thetype); + else if (IS_TYPE_ARRAY(di.thetype)) + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + + IsCompleteType(di.thetype); + if (IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_ABSTRACT)) + CError_AbstractClassError(TYPE_CLASS(di.thetype)); + + catchBlock->type = di.thetype; + catchBlock->qual = di.qual; + + if (di.name) { + ENode *expr; + declBlock = CFunc_NewDeclBlock(); + expr = CExcept_CatchExpressionInit(&di, catchBlock); + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + } + } + + if (tk != ')') { + CError_Error(CErrorStr115); + break; + } + + if ((tk = lex()) != '{') { + CError_Error(CErrorStr123); + break; + } + + CFunc_CompoundStatement(dt); + if (flag) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + } + + catchBlock->anotherStmt = stmt; + + if (declBlock) + CFunc_RestoreBlock(declBlock); + + if (tk != TK_CATCH) + break; + + CFunc_AppendStatement(ST_GOTO)->label = endLabel; + } + + endStmt = CFunc_AppendStatement(ST_LABEL); + endStmt->label = endLabel; + endLabel->stmt = endStmt; + + CExcept_PatchDObjStack(beginCatchStmt, tryEndStmt, endStmt, catchBlock); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = catchEndLabel; + catchEndLabel->stmt = stmt; +} + +static Statement *CExcept_InsertPrevStatement(StatementType sttype) { + Statement *stmt = CFunc_InsertStatement(sttype, cexcept_prevstmt); + stmt->sourceoffset = stmt->next->sourceoffset; + stmt->sourcefilepath = stmt->next->sourcefilepath; + stmt->dobjstack = cexcept_eabefore; + return stmt; +} + +static Object *CExcept_GetETEMPObject(ENode *expr) { + UniqueObj *uobj; + SInt32 id; + + if ((id = expr->data.temp.uniqueid)) { + for (uobj = cexcept_uniqueobjs; uobj; uobj = uobj->next) { + if (uobj->uniqueid == id) + return uobj->object; + } + + uobj = galloc(sizeof(UniqueObj)); + uobj->next = cexcept_uniqueobjs; + cexcept_uniqueobjs = uobj; + uobj->uniqueid = id; + return (uobj->object = create_temp_object(expr->data.temp.type)); + } else { + return create_temp_object(expr->data.temp.type); + } +} + +static ENode *CExcept_TempTrans_ETEMP(ENode *expr) { + Object *object; + ExceptionAction *ea; + DtorTemp *dtorTemp; + Object *dtor; + + object = CExcept_GetETEMPObject(expr); + if (expr->data.temp.needs_dtor) { + dtorTemp = lalloc(sizeof(DtorTemp)); + dtorTemp->next = cexcept_dtortemps; + cexcept_dtortemps = dtorTemp; + dtorTemp->object = object; + dtorTemp->temp = NULL; + + if ( + !IS_TYPE_CLASS(expr->data.temp.type) || + !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(expr->data.temp.type))) + ) + CError_FATAL(1749); + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + ea->type = EAT_DESTROYLOCAL; + ea->data.destroy_local.local = dtorTemp->object; + ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, 1); + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + } + + expr->type = EOBJREF; + expr->data.objref = object; + return expr; +} + +static ENode *CExcept_TransNewException(ENode *expr, Boolean isCond) { + Object *tempObj; + CLabel *label; + Boolean isArray; + Statement *stmt; + ExceptionAction *ea; + ENode *result; + + isArray = expr->type == ENEWEXCEPTIONARRAY; + + if (isCond) { + expr->data.newexception.initexpr = CExcept_TempTransExprCond(expr->data.newexception.initexpr); + expr->data.newexception.tryexpr = CExcept_TempTransExprCond(expr->data.newexception.tryexpr); + tempObj = create_temp_object(TYPE(&stchar)); + + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS); + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DELETEPOINTERCOND; + ea->data.delete_pointer_cond.pointerobject = expr->data.newexception.pointertemp; + ea->data.delete_pointer_cond.deletefunc = expr->data.newexception.deletefunc; + ea->data.delete_pointer_cond.cond = tempObj; + + if (isArray) { + result = makediadicnode( + makediadicnode( + expr->data.newexception.initexpr, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), + ECOMMA + ), + expr->data.newexception.tryexpr, + ECOMMA + ); + + result = makediadicnode( + result, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), + ECOMMA + ); + + result = makediadicnode( + result, + create_objectnode(expr->data.newexception.pointertemp), + ECOMMA + ); + } else { + result = makediadicnode( + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), + expr->data.newexception.tryexpr, + ECOMMA + ); + + result = makediadicnode( + expr->data.newexception.initexpr, + makediadicnode( + result, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), + ECOMMA + ), + ELAND + ); + + result = makediadicnode( + result, + create_objectnode(expr->data.newexception.pointertemp), + ECOMMA + ); + } + } else { + expr->data.newexception.initexpr = CExcept_TempTransExpr(expr->data.newexception.initexpr); + expr->data.newexception.tryexpr = CExcept_TempTransExpr(expr->data.newexception.tryexpr); + + if (isArray) { + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = expr->data.newexception.initexpr; + } else { + stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); + stmt->expr = expr->data.newexception.initexpr; + label = newlabel(); + stmt->label = label; + } + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.newexception.tryexpr; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + ea->type = EAT_DELETEPOINTER; + ea->data.delete_pointer.pointerobject = expr->data.newexception.pointertemp; + ea->data.delete_pointer.deletefunc = expr->data.newexception.deletefunc; + stmt->dobjstack = ea; + + if (!isArray) { + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label; + label->stmt = stmt; + stmt->dobjstack = cexcept_eabefore; + } + + cexcept_prevstmt = stmt; + result = create_objectnode(expr->data.newexception.pointertemp); + } + + result->rtype = expr->rtype; + return result; +} + +static ENode *CExcept_TransInitTryCatch(ENode *expr, Boolean isCond) { + CLabel *label1; + CLabel *label2; + CLabel *label3; + Object *catch_info_object; + Statement *stmt; + ExceptionAction *ea; + + cexcept_hastrycatch = 1; + + if (isCond) { + CError_ASSERT(1877, !cexcept_expandtrycatch); + + cexcept_serialize = 1; + expr->data.itc.initexpr = CExcept_TempTransExprCond(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CExcept_TempTransExprCond(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CExcept_TempTransExprCond(expr->data.itc.catchexpr); + expr->data.itc.result = CExcept_TempTransExprCond(expr->data.itc.result); + return expr; + } + + expr->data.itc.initexpr = CExcept_TempTransExpr(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CExcept_TempTransExpr(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CExcept_TempTransExpr(expr->data.itc.catchexpr); + expr->data.itc.result = CExcept_TempTransExpr(expr->data.itc.result); + + if (!cexcept_expandtrycatch) + return expr; + + label1 = newlabel(); + label2 = newlabel(); + label3 = newlabel(); + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + + stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); + stmt->expr = expr->data.itc.initexpr; + stmt->label = label3; + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_CATCHBLOCK; + ea->data.catch_block.catch_label = label2; + ea->data.catch_block.catch_info_object = catch_info_object; + ea->prev = stmt->dobjstack; + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->flags = StmtFlag_1; + stmt->label = label1; + label1->stmt = stmt; + stmt->dobjstack = ea; + + stmt = CFunc_InsertStatement(ST_BEGINCATCH, stmt); + stmt->expr = create_objectrefnode(catch_info_object); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.itc.tryexpr; + + stmt = CFunc_InsertStatement(ST_GOTO, stmt); + stmt->label = label3; + + CError_ASSERT(1928, stmt->dobjstack == ea); + + stmt->dobjstack = ea->prev; + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->prev = stmt->dobjstack; + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->flags = StmtFlag_1; + stmt->label = label2; + label2->stmt = stmt; + stmt->dobjstack = ea; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.itc.catchexpr; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label3; + label3->stmt = stmt; + + CError_ASSERT(1968, stmt->dobjstack == ea); + + stmt->dobjstack = ea->prev; + + cexcept_prevstmt = stmt; + return expr->data.itc.result; +} + +static ENode *CExcept_TempTransFuncCall(ENode *expr, Boolean isCond) { + ENodeList *tempArg; + ENodeList **argArray; + ENodeList *args; + ExceptionAction *ea; + Statement *stmt; + DtorTemp *dtorTemp; + ENode *tempNode; + + tempArg = NULL; + if ((args = expr->data.funccall.args)) { + tempNode = args->node; + if (tempNode->type == ETEMP) { + if (tempNode->data.temp.needs_dtor) + tempArg = args; + } else if (args->next) { + tempNode = args->next->node; + if (tempNode->type == ETEMP) { + if (tempNode->data.temp.needs_dtor) + tempArg = args->next; + } + } + } + + if (tempArg) { + if (isCond) { + ENodeList *arg = args; + SInt32 i = 0; + while (arg) { + arg = arg->next; + i++; + } + + argArray = lalloc(sizeof(ENodeList *) * i); + for (args = expr->data.funccall.args, i = 0; args; args = args->next) + argArray[i++] = args; + + while (i > 0) { + i--; + if (argArray[i] != tempArg) + argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); + } + } else { + while (args) { + if (args != tempArg) + args->node = CExcept_TempTransExpr(args->node); + args = args->next; + } + } + + dtorTemp = lalloc(sizeof(DtorTemp)); + dtorTemp->next = cexcept_dtortemps; + cexcept_dtortemps = dtorTemp; + + dtorTemp->object = CExcept_GetETEMPObject(tempNode); + dtorTemp->temp = NULL; + + if ( + !IS_TYPE_CLASS(tempNode->data.temp.type) || + !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(tempNode->data.temp.type))) + ) + CError_FATAL(2046); + + tempNode->type = EOBJREF; + tempNode->data.objref = dtorTemp->object; + + if (isCond) { + Type *type24 = expr->rtype; + dtorTemp->temp = create_temp_object(TYPE(&stchar)); + + expr = makediadicnode( + expr, + makediadicnode(create_objectnode(dtorTemp->temp), intconstnode(TYPE(&stchar), 1), EASS), + ECOMMA + ); + + expr = makediadicnode( + expr, + create_objectrefnode(dtorTemp->object), + ECOMMA + ); + expr->rtype = type24; + + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = makediadicnode( + create_objectnode(dtorTemp->temp), + intconstnode(TYPE(&stchar), 0), + EASS + ); + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DESTROYLOCALCOND; + ea->data.destroy_local_cond.local = dtorTemp->object; + ea->data.destroy_local_cond.dtor = CABI_GetDestructorObject(dtorTemp->dtor, 1); + ea->data.destroy_local_cond.cond = dtorTemp->temp; + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + } else { + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = expr; + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DESTROYLOCAL; + ea->data.destroy_local.local = dtorTemp->object; + ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, 1); + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + + expr = lalloc(sizeof(ENode)); + *expr = *stmt->expr; + expr->type = EOBJREF; + expr->data.objref = tempArg->node->data.objref; + } + return expr; + } else { + if (isCond) { + SInt32 i = 0; + while (args) { + args = args->next; + i++; + } + + argArray = lalloc(sizeof(ENodeList *) * i); + for (args = expr->data.funccall.args, i = 0; args; args = args->next) + argArray[i++] = args; + + while (i > 0) { + i--; + argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); + } + + expr->data.funccall.funcref = CExcept_TempTransExprCond(expr->data.funccall.funcref); + } else { + while (args) { + args->node = CExcept_TempTransExpr(args->node); + args = args->next; + } + + expr->data.funccall.funcref = CExcept_TempTransExpr(expr->data.funccall.funcref); + } + + return expr; + } +} + +static ENode *CExcept_TempTransExprCond(ENode *expr) { + switch (expr->type) { + case ETEMP: + return CExcept_TempTrans_ETEMP(expr); + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + return CExcept_TransNewException(expr, 1); + case EINITTRYCATCH: + return CExcept_TransInitTryCatch(expr, 1); + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExprCond(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); + return expr; + case ECOND: + expr->data.cond.cond = CExcept_TempTransExprCond(expr->data.cond.cond); + expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); + expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); + return expr; + case ELAND: + case ELOR: + expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EFUNCCALL: + case EFUNCCALLP: + return CExcept_TempTransFuncCall(expr, 1); + case EMUL: + case EDIV: + case EMODULO: + 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 EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EROTL: + case EROTR: + expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExcept_TempTransExprCond(expr->data.monadic); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ELABEL: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + default: + CError_FATAL(2236); + return expr; + } +} + +static ENode *CExcept_TempTransExpr(ENode *expr) { + switch (expr->type) { + case ETEMP: + return CExcept_TempTrans_ETEMP(expr); + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + return CExcept_TransNewException(expr, 0); + case EINITTRYCATCH: + return CExcept_TransInitTryCatch(expr, 0); + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExpr(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); + return expr; + case ECOND: + expr->data.cond.cond = CExcept_TempTransExpr(expr->data.cond.cond); + expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); + expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); + return expr; + case ELAND: + case ELOR: + expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EFUNCCALL: + case EFUNCCALLP: + return CExcept_TempTransFuncCall(expr, 0); + case EMUL: + case EDIV: + case EMODULO: + 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 EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EROTL: + case EROTR: + expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExpr(expr->data.diadic.right); + return expr; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExcept_TempTransExpr(expr->data.monadic); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ELABEL: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + default: + CError_FATAL(2350); + return expr; + } +} + +static Statement *CExcept_DtorTransform(Statement *stmt) { + DtorTemp *dtorTemp; + Statement *curStmt; + CLabel *lastLabel; + + dtorTemp = cexcept_dtortemps; + curStmt = stmt; + while (dtorTemp) { + if ( + cexcept_eaafter && + (cexcept_eaafter->type == EAT_DESTROYLOCAL || cexcept_eaafter->type == EAT_DESTROYLOCALCOND) && + cexcept_eaafter->data.destroy_local.local == dtorTemp->object + ) + { + cexcept_eaafter = cexcept_eaafter->prev; + } else { + CError_FATAL(2374); + } + + if (dtorTemp->temp) { + curStmt = CFunc_InsertStatement(ST_IFNGOTO, curStmt); + curStmt->expr = create_objectnode(dtorTemp->temp); + curStmt->dobjstack = cexcept_eaafter; + lastLabel = curStmt->label = newlabel(); + } + + curStmt = CFunc_InsertStatement(ST_EXPRESSION, curStmt); + curStmt->expr = CABI_DestroyObject(dtorTemp->dtor, create_objectrefnode(dtorTemp->object), 1, 1, 0); + curStmt->dobjstack = cexcept_eaafter; + + if (dtorTemp->temp) { + curStmt = CFunc_InsertStatement(ST_LABEL, curStmt); + curStmt->label = lastLabel; + lastLabel->stmt = curStmt; + } + + dtorTemp = dtorTemp->next; + } + + return curStmt; +} + +static void CExcept_TempTransform(Statement *stmt, Boolean flag1, Boolean flag2) { + Statement *prevStmt; + Statement *iter; + Statement copy; + Object *tempObj; + + prevStmt = cexcept_prevstmt; + cexcept_dtortemps = NULL; + cexcept_serialize = 0; + cexcept_expandtrycatch = 0; + cexcept_hastrycatch = 0; + stmt->expr = CExcept_TempTransExpr(stmt->expr); + + if (cexcept_hastrycatch) { + cexcept_expandtrycatch = 1; + if (cexcept_serialize) { + CInline_SerializeStatement(stmt); + cexcept_prevstmt = stmt; + } else { + cexcept_prevstmt = prevStmt; + } + + iter = prevStmt; + while (1) { + CError_ASSERT(2425, iter); + + switch (iter->type) { + case ST_RETURN: + CError_ASSERT(2429, iter->expr != NULL); + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + iter->expr = CExcept_TempTransExpr(iter->expr); + } + + if (iter == stmt) + break; + cexcept_prevstmt = iter; + iter = iter->next; + } + } + + if (cexcept_dtortemps) { + if (!flag1) { + if (flag2) { + ENode *expr = stmt->expr; + CError_ASSERT(2456, !IS_TYPE_CLASS(expr->rtype) || !CClass_Destructor(TYPE_CLASS(expr->rtype))); + + tempObj = create_temp_object(expr->rtype); + stmt->expr = makediadicnode(create_objectnode(tempObj), expr, EASS); + } + + copy = *stmt; + stmt->type = ST_EXPRESSION; + stmt = CExcept_DtorTransform(stmt); + stmt = CFunc_InsertStatement(copy.type, stmt); + stmt->label = copy.label; + + if (flag2) + stmt->expr = create_objectnode(tempObj); + else + stmt->expr = nullnode(); + } else { + CExcept_DtorTransform(stmt); + } + } +} + +static void CExcept_CleanupExceptionActions(Statement *stmt) { + Statement *iter; + ENode *expr; + ExceptionAction *ea; + + cexcept_prevstmt = stmt; + for (iter = stmt; iter; iter = iter->next) { + cexcept_eabefore = cexcept_eaafter = ea = iter->dobjstack; + + if (iter->flags & StmtFlag_2) { + cexcept_eabefore = ea->prev; + } else if (iter->type == ST_EXPRESSION) { + expr = iter->expr; + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.left; + if (ENODE_IS(expr, EINDIRECT)) + expr = expr->data.monadic; + + if ( + ENODE_IS(expr, EFUNCCALL) && + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && + iter->dobjstack && + iter->dobjstack->type == EAT_DESTROYLOCAL && + expr->data.funccall.args && + ENODE_IS(expr->data.funccall.args->node, EOBJREF) && + expr->data.funccall.args->node->data.objref == iter->dobjstack->data.destroy_local.local + ) + cexcept_eabefore = cexcept_eabefore->prev; + } + + switch (iter->type) { + case ST_EXPRESSION: + CExcept_TempTransform(iter, 1, 0); + break; + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + CExcept_TempTransform(iter, 0, 1); + break; + case ST_RETURN: + if (iter->expr) { + CExcept_TempTransform( + iter, + 0, + CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1 + ); + } + break; + } + + iter->dobjstack = cexcept_eabefore; + cexcept_prevstmt = iter; + } +} + +static void CExcept_InsertSpecificationActions(Statement *stmt, ExceptSpecList *exspecs) { + Statement *iter; + Statement *last; + ExceptionAction *ea_spec; + ExceptionAction *ea; + ExceptSpecList *spec_iter; + SInt32 i; + Object *catch_info_object; + CLabel *label; + + ea_spec = lalloc(sizeof(ExceptionAction)); + memclrw(ea_spec, sizeof(ExceptionAction)); + ea_spec->type = EAT_SPECIFICATION; + + for (iter = stmt; iter; iter = iter->next) { + if ((ea = iter->dobjstack)) { + while (1) { + if (ea->type == EAT_SPECIFICATION) + break; + if (ea->prev == NULL) { + ea->prev = ea_spec; + break; + } + ea = ea->prev; + } + } else { + iter->dobjstack = ea_spec; + } + } + + last = stmt; + while (last->next) + last = last->next; + + if (last->type != ST_GOTO && last->type != ST_RETURN) { + last = CFunc_InsertStatement(ST_RETURN, last); + last->expr = NULL; + last->dobjstack = NULL; + if (TYPE_FUNC(cscope_currentfunc->type)->functype != &stvoid && (copts.pedantic || copts.cplusplus)) + CError_Warning(CErrorStr184); + } + + last = CFunc_InsertStatement(ST_LABEL, last); + last->label = newlabel(); + last->label->stmt = last; + last->flags = StmtFlag_1; + last->dobjstack = NULL; + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + + if (!exspecs->type) + exspecs = NULL; + + i = 0; + spec_iter = exspecs; + while (spec_iter) { + spec_iter = spec_iter->next; + i++; + } + + ea_spec->data.specification.unexp_ids = i; + ea_spec->data.specification.unexp_id = galloc(sizeof(Object *) * i); + ea_spec->data.specification.unexp_label = last->label; + ea_spec->data.specification.unexp_info_object = catch_info_object; + + i = 0; + while (exspecs) { + ea_spec->data.specification.unexp_id[i] = CExcept_TypeID(exspecs->type, exspecs->qual); + exspecs = exspecs->next; + i++; + } + + last = CFunc_InsertStatement(ST_EXPRESSION, last); + last->expr = funccallexpr(Xunex_func, create_objectrefnode(catch_info_object), NULL, NULL, NULL); + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->data.active_catch_block.call_dtor = 1; + last->dobjstack = ea; + + last = CFunc_InsertStatement(ST_LABEL, last); + last->label = label = newlabel(); + last->label->stmt = last; + last->dobjstack = NULL; + + last = CFunc_InsertStatement(ST_GOTO, last); + last->label = label; +} + +static void CExcept_HasFuncCallCallBack(ENode *expr) { + ENode *funcref = expr->data.funccall.funcref; + if (ENODE_IS(funcref, EOBJREF)) { + Object *func = funcref->data.objref; + if (CExcept_CanThrowException(func, func->datatype == DVFUNC && !(expr->flags & ENODE_FLAG_80))) + cexcept_canthrow = 1; + } else { + cexcept_canthrow = 1; + } +} + +static Boolean CExcept_CanThrowCheck(Object *func, Statement *stmt) { + cexcept_canthrow = 0; + + while (stmt) { + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + CExpr_SearchExprTree(stmt->expr, CExcept_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); + break; + default: + CError_FATAL(2687); + } + stmt = stmt->next; + } + + if (!cexcept_canthrow) { + TYPE_FUNC(cscope_currentfunc->type)->flags |= FUNC_FLAGS_NOTHROW; + return 0; + } else { + return 1; + } +} + +void CExcept_ExceptionTansform(Statement *stmt) { + cexcept_uniqueobjs = NULL; + CExcept_CleanupExceptionActions(stmt); + + if (cscope_currentfunc && CExcept_CanThrowCheck(cscope_currentfunc, stmt)) { + CError_ASSERT(2716, IS_TYPE_FUNC(cscope_currentfunc->type)); + if (TYPE_FUNC(cscope_currentfunc->type)->exspecs && copts.exceptions) + CExcept_InsertSpecificationActions(stmt, TYPE_FUNC(cscope_currentfunc->type)->exspecs); + } +} diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c index 9968bab..425a004 100644 --- a/compiler_and_linker/unsorted/CExpr.c +++ b/compiler_and_linker/unsorted/CExpr.c @@ -1053,7 +1053,7 @@ static ENode *CExpr_ParseNameResultExpr(CScopeParseResult *pr, ENode *expr, Bool switch (pr->obj_10->otype) { case OT_OBJECT: if (OBJECT(pr->obj_10)->nspace && OBJECT(pr->obj_10)->nspace->theclass && (OBJECT(pr->obj_10)->nspace->theclass->flags & CLASS_FLAGS_100)) { - result = CExpr_NewTemplDepENode(TDE_QUALTEMPL); // not sure this is right tbh + result = CExpr_NewTemplDepENode(TDE_OBJ); result->data.templdep.u.obj = OBJECT(pr->obj_10); tk = lex(); return result; @@ -2143,8 +2143,8 @@ static ENode *CExpr_ParseSizeof(void) { CError_Error(286); if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_TYPEEXPR); - expr->data.templdep.u.typeexpr.u.type = type; + expr = CExpr_NewTemplDepENode(TDE_SIZEOF); + expr->data.templdep.u.typeexpr.type = type; return expr; } @@ -2183,8 +2183,8 @@ static ENode *CExpr_ParseAlignof(void) { CError_Error(364); if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_unk2); - expr->data.templdep.u.typeexpr.u.type = type; + expr = CExpr_NewTemplDepENode(TDE_ALIGNOF); + expr->data.templdep.u.typeexpr.type = type; return expr; } @@ -2629,7 +2629,7 @@ ENode *unary_expression(void) { return expr; if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { - tmp = CExpr_NewTemplDepENode(TDE_MONAND); + tmp = CExpr_NewTemplDepENode(TDE_ADDRESS_OF); tmp->data.templdep.u.monadic = expr; return tmp; } @@ -4861,7 +4861,7 @@ static Boolean CExpr_HasSideEffect(ENode *expr) { case ELABEL: case ENEWEXCEPTION: case ENEWEXCEPTIONARRAY: - case EMYSTERY67: + case EINITTRYCATCH: case EINSTRUCTION: return 1; default: diff --git a/compiler_and_linker/unsorted/CExpr2.c b/compiler_and_linker/unsorted/CExpr2.c index 47268ac..67f4fb7 100644 --- a/compiler_and_linker/unsorted/CExpr2.c +++ b/compiler_and_linker/unsorted/CExpr2.c @@ -161,7 +161,7 @@ restart: CExpr_RecSearchExprTree(expr->data.newexception.initexpr); expr = expr->data.newexception.tryexpr; goto restart; - case EMYSTERY67: + case EINITTRYCATCH: if (expr->data.itc.initexpr) CExpr_RecSearchExprTree(expr->data.itc.initexpr); if (expr->data.itc.tryexpr) @@ -3745,7 +3745,7 @@ static ENode *CExpr_NewExceptionSafeAlloc(Type *type, ENode *node, ENodeList *ar } else { if (!catchexpr) catchexpr = CExpr_DeleteFuncCall(deletefunc, create_objectnode(obj), type, include_size); - result->type = EMYSTERY67; + result->type = EINITTRYCATCH; result->data.itc.initexpr = node; result->data.itc.tryexpr = NULL; result->data.itc.result = create_objectnode(obj); @@ -3760,7 +3760,7 @@ static ENode *CExpr_NewExceptionSafeInit(ENode *expr, ENode *tryexpr) { case ENEWEXCEPTION: expr->data.newexception.tryexpr = tryexpr; break; - case EMYSTERY67: + case EINITTRYCATCH: expr->data.itc.tryexpr = tryexpr; break; default: diff --git a/compiler_and_linker/unsorted/CExprConvMatch.c b/compiler_and_linker/unsorted/CExprConvMatch.c new file mode 100644 index 0000000..9722dcb --- /dev/null +++ b/compiler_and_linker/unsorted/CExprConvMatch.c @@ -0,0 +1 @@ +#include "compiler/CExpr.h" diff --git a/compiler_and_linker/unsorted/CFunc.c b/compiler_and_linker/unsorted/CFunc.c index 76d880a..780dbd2 100644 --- a/compiler_and_linker/unsorted/CFunc.c +++ b/compiler_and_linker/unsorted/CFunc.c @@ -89,7 +89,7 @@ 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) {} +NameSpace *CFunc_FuncGenSetup(Statement *stmt, Object *func) {} void CFunc_GetGlobalCompilerState(CFuncSave *state) {} void CFunc_SetGlobalCompilerState(CFuncSave *state) {} void CFunc_Gen(Statement *stmt, Object *obj, UInt8 unk) {} diff --git a/compiler_and_linker/unsorted/CIRTransform.c b/compiler_and_linker/unsorted/CIRTransform.c index e69de29..852d3f4 100644 --- a/compiler_and_linker/unsorted/CIRTransform.c +++ b/compiler_and_linker/unsorted/CIRTransform.c @@ -0,0 +1,534 @@ +#include "compiler/CIRTransform.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/CompilerTools.h" +#include "compiler/CDecl.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CIRTransTemp { + struct CIRTransTemp *next; + Object *object; + Boolean flag; +} CIRTransTemp; + +typedef struct MultiAccessOperand { + Object *object; + Object *tempobj; + ENode *ass; + Type *type; + Type *bitfieldType; +} MultiAccessOperand; + +// no idea what this is for... +typedef struct StrangeRuntimeFunction { + Object *object; + short unk; + char name[1]; +} StrangeRuntimeFunction; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static TypeFunc cirtrans_rtfunc8 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&void_ptr), 0, 0 +}; +static TypeFunc cirtrans_rtfunc4 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stunsignedlong), 0, 0 +}; +static TypeFunc cirtrans_rtfunc2 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stsignedshort), 0, 0 +}; + +static CIRTransTemp *cirtrans_temps; +Boolean modulo_generated; +Boolean bigswitch_generated; +Boolean alloca_called; + +// forward decls +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag); + +void CIRTrans_Setup(void) { +} + +void CIRTrans_Cleanup(void) { +} + +static Object *CIRTrans_GetRuntimeFunction(StrangeRuntimeFunction *rtfunc, Type *type) { + Object *object; + + object = rtfunc->object; + if (!object) { + object = CParser_NewFunctionObject(NULL); + rtfunc->object = object; + + object->nspace = cscope_root; + object->name = GetHashNameNodeExport(rtfunc->name); + object->flags = OBJECT_FLAGS_10; + + if (type) { + switch (type->size) { + case 2: + object->type = TYPE(&cirtrans_rtfunc2); + break; + case 4: + object->type = TYPE(&cirtrans_rtfunc4); + break; + case 8: + object->type = TYPE(&cirtrans_rtfunc8); + break; + default: + CError_FATAL(427); + } + } else { + object->type = TYPE(&cirtrans_rtfunc8); + } + } + + return object; +} + +static Object *CIRTrans_GetTemporary(Type *type) { + CIRTransTemp *temp; + + for (temp = cirtrans_temps; temp; temp = temp->next) { + if (temp->object->type->size == type->size && !temp->flag) { + temp->flag = 1; + return temp->object; + } + } + + temp = oalloc(sizeof(CIRTransTemp)); + temp->next = cirtrans_temps; + cirtrans_temps = temp; + + temp->object = create_temp_object(type); + temp->flag = 1; + return temp->object; +} + +static ENode *CIRTrans_CheckRuntimeAssign(ENode *expr) { + ENode *inner; + + if (ENODE_IS(expr->data.diadic.right, EINDIRECT)) { + inner = expr->data.diadic.right->data.monadic; + if ( + ENODE_IS(inner, EFUNCCALL) && + (inner->flags & ENODE_FLAG_80) && + inner->data.funccall.args && + ENODE_IS(inner->data.funccall.args->node, EOBJREF) + ) + { + CError_ASSERT(502, ENODE_IS(expr->data.diadic.left, EINDIRECT)); + inner->data.funccall.args->node = expr->data.diadic.left->data.monadic; + inner->flags &= ~ENODE_FLAG_80; + return expr->data.diadic.right; + } + } + + return expr; +} + +static void CIRTrans_SetupMultiAccessOperand(MultiAccessOperand *mop, ENode *expr) { + memclrw(mop, sizeof(MultiAccessOperand)); + + mop->type = expr->rtype; + + CError_ASSERT(522, ENODE_IS(expr, EINDIRECT)); + expr = expr->data.monadic; + + if (ENODE_IS(expr, EOBJREF)) { + mop->object = expr->data.objref; + } else { + if (ENODE_IS(expr, EBITFIELD)) { + mop->bitfieldType = expr->rtype; + expr = expr->data.monadic; + } + expr->rtype = CDecl_NewPointerType(mop->type); + mop->tempobj = create_temp_object(expr->rtype); + mop->ass = makediadicnode(create_objectnode(mop->tempobj), expr, EASS); + } +} + +static ENode *CIRTrans_GetMultiAccessOperand(MultiAccessOperand *mop) { + ENode *expr; + + if (mop->object == NULL) { + expr = create_objectnode(mop->tempobj); + if (mop->bitfieldType) { + expr = makemonadicnode(expr, EBITFIELD); + expr->rtype = mop->bitfieldType; + } + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = create_objectnode(mop->object); + } + + expr->rtype = mop->type; + return expr; +} + +static ENode *CIRTrans_InitMultiAccessExpression(MultiAccessOperand *mop, ENode *expr) { + if (mop->ass) { + expr = makediadicnode(mop->ass, expr, ECOMMA); + expr->rtype = expr->data.diadic.right->rtype; + } + return expr; +} + +ENode *CIRTrans_TransformOpAss(ENode *expr) { + ENodeType nt; + ENode *expr2; + MultiAccessOperand mop; + + if (!ENODE_IS(expr->data.diadic.left, EINDIRECT)) { + CError_Error(CErrorStr142); + return nullnode(); + } + + CIRTrans_SetupMultiAccessOperand(&mop, expr->data.diadic.left); + + switch (expr->type) { + case EMULASS: + nt = EMUL; + break; + case EDIVASS: + nt = EDIV; + break; + case EMODASS: + nt = EMODULO; + break; + case EADDASS: + nt = EADD; + break; + case ESUBASS: + nt = ESUB; + break; + case ESHLASS: + nt = ESHL; + break; + case ESHRASS: + nt = ESHR; + break; + case EANDASS: + nt = EAND; + break; + case EXORASS: + nt = EXOR; + break; + case EORASS: + nt = EOR; + break; + default: + CError_FATAL(622); + } + + expr2 = CIRTrans_GetMultiAccessOperand(&mop); + + if (!IS_TYPE_POINTER_ONLY(expr2->rtype)) { + expr2 = CExpr_NewDyadicNode(expr2, nt, expr->data.diadic.right); + if (expr2->rtype != expr->data.diadic.left->rtype) { + expr2 = makemonadicnode(expr2, ETYPCON); + expr2->rtype = expr->data.diadic.left->rtype; + } + } else { + expr2 = makediadicnode(expr2, expr->data.diadic.right, nt); + } + + if (IS_TYPE_FLOAT(expr2->rtype)) + expr2 = CExpr_BinaryFloatExpression(expr2); + + expr2 = makediadicnode(CIRTrans_GetMultiAccessOperand(&mop), expr2, EASS); + return CIRTrans_InitMultiAccessExpression(&mop, expr2); +} + +static void CIRTrans_TransIncDec() { + // empty, never called +} + +static ENode *CIRTrans_TransIntConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitIntMem(expr->rtype, expr->data.intval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransFloatConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitFloatMem(expr->rtype, expr->data.floatval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransUnary(ENode *expr, Type *type, StrangeRuntimeFunction *rtfunc) { + if (type->size > 4) { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + create_objectrefnode(CIRTrans_GetTemporary(type)), + expr, + NULL, + NULL); + expr->flags |= ENODE_FLAG_80; + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = type; + return expr; + } else { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + expr, + NULL, + NULL, + NULL); + expr->rtype = type; + return expr; + } +} + +static ENode *CIRTrans_TransBinary(ENode *expr, StrangeRuntimeFunction *rtfunc) { + ENode *expr2; + + if (expr->rtype->size > 4) { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + create_objectrefnode(CIRTrans_GetTemporary(expr->rtype)), + expr->data.diadic.left, + expr->data.diadic.right, + NULL); + expr2->flags |= ENODE_FLAG_80; + expr2 = makemonadicnode(expr2, EINDIRECT); + expr2->rtype = expr->rtype; + return expr2; + } else { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + expr->data.diadic.left, + expr->data.diadic.right, + NULL, + NULL); + expr2->rtype = expr->rtype; + return expr2; + } +} + +static ENodeList *CIRTrans_TransExprList(ENodeList *list) { + ENodeList *scan; + + for (scan = list; scan; scan = scan->next) + scan->node = CIRTrans_TransExpr(scan->node, 1); + + return list; +} + +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag) { + switch (expr->type) { + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EPOSTINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPOSTDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case ETYPCON: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + if (!flag) + return expr->data.monadic; + break; + case EBINNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case ELOGNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EMONMIN: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EADD: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESUB: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMUL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + case EDIV: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMODULO: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EAND: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EXOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + if (!flag) { + expr->type = ECOMMA; + expr->rtype = expr->data.diadic.right->rtype; + return expr; + } + break; + case ELAND: + case ELOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMULV: + case EADDV: + case ESUBV: + case EPMODULO: + case EBCLR: + case EBTST: + case EBSET: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMULASS: + case EDIVASS: + case EADDASS: + case ESUBASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMODASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case ECOMMA: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 0); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ECOND: + expr->data.cond.cond = CIRTrans_TransExpr(expr->data.cond.cond, 1); + expr->data.cond.expr1 = CIRTrans_TransExpr(expr->data.cond.expr1, 1); + expr->data.cond.expr2 = CIRTrans_TransExpr(expr->data.cond.expr2, 1); + break; + case EMFPOINTER: + expr->data.mfpointer.accessnode = CIRTrans_TransExpr(expr->data.mfpointer.accessnode, flag); + expr->data.mfpointer.mfpointer = CIRTrans_TransExpr(expr->data.mfpointer.mfpointer, flag); + break; + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + !strcmp(expr->data.funccall.funcref->data.objref->name->name, "__alloca") + ) + alloca_called = 1; + expr->data.funccall.funcref = CIRTrans_TransExpr(expr->data.funccall.funcref, 1); + expr->data.funccall.args = CIRTrans_TransExprList(expr->data.funccall.args); + break; + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CIRTrans_TransExpr(expr->data.nullcheck.nullcheckexpr, 1); + expr->data.nullcheck.condexpr = CIRTrans_TransExpr(expr->data.nullcheck.condexpr, 1); + break; + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + expr->data.newexception.initexpr = CIRTrans_TransExpr(expr->data.newexception.initexpr, 1); + expr->data.newexception.tryexpr = CIRTrans_TransExpr(expr->data.newexception.tryexpr, 1); + break; + case EINITTRYCATCH: + expr->data.itc.initexpr = CIRTrans_TransExpr(expr->data.itc.initexpr, 1); + expr->data.itc.tryexpr = CIRTrans_TransExpr(expr->data.itc.tryexpr, 1); + expr->data.itc.catchexpr = CIRTrans_TransExpr(expr->data.itc.catchexpr, 1); + expr->data.itc.result = CIRTrans_TransExpr(expr->data.itc.result, 1); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + default: + CError_FATAL(1947); + } + + return expr; +} + +void CIRTrans_Transform(void) { + cirtrans_temps = NULL; +} diff --git a/compiler_and_linker/unsorted/CInit.c b/compiler_and_linker/unsorted/CInit.c index a305c38..ccc534e 100644 --- a/compiler_and_linker/unsorted/CInit.c +++ b/compiler_and_linker/unsorted/CInit.c @@ -322,8 +322,7 @@ static Stage CInit_ParseNextInit(CInit_Stuff2 *s) { s->stage = Stage3; return Stage3; default: -#line 389 - CError_FATAL(); + CError_FATAL(389); } switch (tk) { @@ -417,8 +416,7 @@ static Boolean CInit_IsSimpleInit(Type *type) { static Object *CInit_GetInitObject(Object *obj) { if (obj->datatype == DALIAS) { -#line 521 - CError_ASSERT(!obj->u.alias.offset); + CError_ASSERT(521, !obj->u.alias.offset); obj = obj->u.alias.object; } return obj; @@ -870,10 +868,8 @@ static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, TypeStruct *t } count++; - if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) { -#line 1218 - CError_ASSERT(!ENODE_IS(s2->expr, EVECTOR128CONST)); - } + if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) + CError_ASSERT(1218, !ENODE_IS(s2->expr, EVECTOR128CONST)); do { member = member->next; @@ -1130,8 +1126,7 @@ static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual); break; default: -#line 1542 - CError_FATAL(); + CError_FATAL(1542); } if (flag) { @@ -1157,8 +1152,7 @@ static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag); break; default: -#line 1573 - CError_FATAL(); + CError_FATAL(1573); } } @@ -1203,8 +1197,7 @@ static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag if (s->x0) { buffer = lalloc(size); for (tmp = s; tmp; tmp = tmp->x0) { -#line 1647 - CError_ASSERT((tmp->xC + tmp->size) <= size); + CError_ASSERT(1647, (tmp->xC + tmp->size) <= size); memcpy(buffer + tmp->xC, tmp->buffer, tmp->size); } s->buffer = buffer; @@ -1522,8 +1515,7 @@ static void CInit_TypeExpr(Type *type, ENode *expr) { CError_Error(174); break; default: -#line 2082 - CError_FATAL(); + CError_FATAL(2082); } } @@ -1883,8 +1875,7 @@ static void CInit_Type(Type *type, UInt32 qual, Boolean flag) { CInit_Class(TYPE_CLASS(type), flag); break; default: -#line 2482 - CError_FATAL(); + CError_FATAL(2482); } } @@ -2020,8 +2011,7 @@ static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB exp } CInit_SetupInitInfoBuffer(type); CInit_Type(type, obj->qual, 1); -#line 2639 - CError_ASSERT(obj->type->size == (size = cinit_initinfo->size)); + CError_ASSERT(2639, 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); @@ -2098,8 +2088,7 @@ static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB exp if (!obj || (flag && copts.cplusplus)) { if (obj) { IsCompleteType(obj->type); -#line 2747 - CError_ASSERT(obj->type->size == type->size); + CError_ASSERT(2747, obj->type->size == type->size); CInit_DeclareData(obj, NULL, NULL, obj->type->size); } return expr; @@ -2107,8 +2096,7 @@ static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB exp CInit_SetupInitInfoBuffer(type); CInit_TypeExpr(type, expr); -#line 2756 - CError_ASSERT(obj->type->size == cinit_initinfo->size); + CError_ASSERT(2756, obj->type->size == cinit_initinfo->size); IsCompleteType(obj->type); CInit_AdjustObjectDataSize(obj); @@ -2127,8 +2115,7 @@ static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB exp break; default: -#line 2776 - CError_FATAL(); + CError_FATAL(2776); } return NULL; @@ -2154,8 +2141,7 @@ void CInit_ExportConst(Object *obj) { CMach_InitFloatMem(obj->type, *obj->u.data.u.floatconst, buffer); break; default: -#line 2807 - CError_FATAL(); + CError_FATAL(2807); } if (is_const_object(obj)) @@ -2414,16 +2400,14 @@ static void CInit_FindDtorTemp(ENode *expr) { static void CInit_RefTempTransform(Type *type, ENode *expr) { Object *obj; -#line 3164 - CError_ASSERT(IS_TYPE_POINTER_ONLY(type)); + CError_ASSERT(3164, 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); + CError_ASSERT(3172, !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); @@ -2448,8 +2432,7 @@ static Boolean CInit_InitReference(Object *obj, Boolean flag) { 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); + CError_ASSERT(3213, obj->type->size == cinit_initinfo->size); if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { IsCompleteType(obj->type); @@ -3000,8 +2983,7 @@ void CInit_RewriteString(ENode *expr, Boolean flag) { if (cparamblkptr->isPrecompiling == 1) CError_Error(180); -#line 4220 - CError_ASSERT(expr->rtype->type == TYPEPOINTER); + CError_ASSERT(4220, expr->rtype->type == TYPEPOINTER); is_wide = TYPE_POINTER(expr->rtype)->target->size != 1; if (copts.pool_strings) { diff --git a/compiler_and_linker/unsorted/CInline.c b/compiler_and_linker/unsorted/CInline.c index 1f11b61..2ab6568 100644 --- a/compiler_and_linker/unsorted/CInline.c +++ b/compiler_and_linker/unsorted/CInline.c @@ -1,116 +1,4206 @@ #include "compiler/CInline.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" #include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/COptimizer.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsm.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Switch.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct IDTrans { + struct IDTrans *next; + SInt32 from; + SInt32 to; +} IDTrans; + +typedef struct LabelTrans { + struct LabelTrans *next; + CLabel **labelptr; + short id; +} LabelTrans; + +typedef struct UIDTemp { + struct UIDTemp *next; + Object *object; + SInt32 uid; +} UIDTemp; + +typedef struct CI_Export { + struct CI_Export *next; + Object *object; + CI_FuncData *funcdata; + Boolean xC; +} CI_Export; + +typedef struct AObject { + Object *object; + ENode *expr1; + ENode *expr2; +} AObject; + +typedef struct CI_StmtLink { + struct CI_StmtLink *next; + Statement *stmt; + CI_Statement *ciStmt; +} CI_StmtLink; +#ifdef __MWERKS__ +#pragma options align=reset +#endif static CInlineCopyMode enode_copymode; static Boolean enode_globalcopy; -static void *enode_idtrans; // type? -static void *local_dobjects; // type? -static void *local_aobjects; // type? +static IDTrans *enode_idtrans; +static Object **local_dobjects; +static AObject *local_aobjects; 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 LabelTrans *cinline_label_trans; static Statement *cinline_first_stmt; -static void *cinline_stmtlevelexpr[16]; // type? +static ENode *cinline_stmtlevelexpr[16]; static short cinline_stmtlevelexprs; static Boolean cinline_unconditionalpart; static Boolean cinline_serialize_stmt; -static void *cinline_exportlist; // type? +static CI_Export *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 UIDTemp *cinline_uid_temps; 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) {} -SInt16 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) {} +// forward decls +static ENode *CInline_FoldConst(ENode *expr); +static ENode *CInline_CopyNodes(ENode *node); +static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level); +static ENode *CInline_SerializeExpr(ENode *expr); +static void CInline_AddFRefList_InlineFunc(CI_FuncData *data); + +void CInline_Init(void) { + cinline_exportlist = NULL; + cinline_actionlist = NULL; + cinline_tactionlist = NULL; + cinline_gendeps = 0; +} + +static ENode *CInline_MakeNotNot(ENode *expr) { + expr = CInline_FoldConst(expr); + + if (!ENODE_IS(expr, EINTCONST)) { + expr = makemonadicnode(expr, ELOGNOT); + expr->rtype = CParser_GetBoolType(); + expr = makemonadicnode(expr, ELOGNOT); + } else { + expr->data.intval = CInt64_Not(CInt64_Not(expr->data.intval)); + } + + return expr; +} + +static ENode *CInline_FoldConst(ENode *expr) { + ENode *inner; + ENode *right; + ENode *left; + ENodeList *list; + + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + inner = expr->data.monadic; + switch (inner->type) { + case EINTCONST: + if (!ENODE_IS(expr, ELOGNOT)) { + inner->data.intval = CMach_CalcIntMonadic( + expr->rtype, CParser_GetOperator(expr->type), inner->data.intval); + } else { + inner->data.intval = CInt64_Not(inner->data.intval); + } + inner->rtype = expr->rtype; + return inner; + + case EFLOATCONST: + if (ENODE_IS(expr, ELOGNOT)) { + inner->type = EINTCONST; + CInt64_SetLong(&inner->data.intval, CMach_FloatIsZero(inner->data.floatval)); + } else { + inner->data.floatval = CMach_CalcFloatMonadic( + expr->rtype, CParser_GetOperator(expr->type), inner->data.floatval); + } + inner->rtype = expr->rtype; + return inner; + } + + return expr; + + case ETYPCON: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + switch (expr->data.monadic->type) { + case EINTCONST: + switch (expr->rtype->type) { + case TYPEFLOAT: + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvertFromInt( + expr->data.monadic->rtype, expr->data.monadic->data.intval); + return expr; + + case TYPEINT: + expr->type = EINTCONST; + expr->data.intval = CExpr_IntConstConvert( + expr->rtype, expr->data.monadic->rtype, expr->data.monadic->data.intval); + break; + } + break; + + case EFLOATCONST: + switch (expr->rtype->type) { + case TYPEFLOAT: + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvert( + expr->rtype, expr->data.monadic->data.floatval); + return expr; + + case TYPEINT: + expr->type = EINTCONST; + expr->data.intval = CMach_CalcIntConvertFromFloat( + expr->rtype, expr->data.monadic->data.floatval); + return expr; + } + break; + } + + return expr; + + case EPOSTINC: + case EPOSTDEC: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + switch (expr->data.monadic->type) { + case EINTCONST: + case EFLOATCONST: + expr->data.monadic->rtype = expr->rtype; + return expr->data.monadic; + } + + return expr; + + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + return expr; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case EAND: + case EXOR: + case EOR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { + switch (left->type) { + case EINTCONST: + left->data.intval = CMach_CalcIntDiadic( + expr->rtype, + expr->data.diadic.left->data.intval, + CParser_GetOperator(expr->type), + right->data.intval); + left->rtype = expr->rtype; + return left; + + case EFLOATCONST: + left->data.floatval = CMach_CalcFloatDiadic( + expr->rtype, + expr->data.diadic.left->data.floatval, + CParser_GetOperator(expr->type), + right->data.floatval); + left->rtype = expr->rtype; + return left; + } + } + + return expr; + + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { + switch (left->type) { + case EINTCONST: + left->data.intval = CMach_CalcIntDiadic( + left->rtype, + expr->data.diadic.left->data.intval, + CParser_GetOperator(expr->type), + right->data.intval); + left->rtype = expr->rtype; + return left; + + case EFLOATCONST: + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool( + left->rtype, + expr->data.diadic.left->data.floatval, + CParser_GetOperator(expr->type), + right->data.floatval + )); + left->type = EINTCONST; + left->rtype = expr->rtype; + return left; + } + } + + return expr; + + case ELAND: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + if (iszero(expr->data.diadic.left)) + return expr->data.diadic.left; + if (isnotzero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.right); + + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if (isnotzero(expr->data.diadic.right)) + return CInline_MakeNotNot(expr->data.diadic.left); + + return expr; + + case ELOR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + if (iszero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.right); + if (isnotzero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.left); + + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if (iszero(expr->data.diadic.right)) + return CInline_MakeNotNot(expr->data.diadic.left); + + return expr; + + 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 EROTL: + case EROTR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + return expr; + + case ECOND: + expr->data.cond.cond = CInline_FoldConst(expr->data.cond.cond); + if (isnotzero(expr->data.cond.cond)) + return CInline_FoldConst(expr->data.cond.expr1); + if (iszero(expr->data.cond.cond)) + return CInline_FoldConst(expr->data.cond.expr2); + + expr->data.cond.expr1 = CInline_FoldConst(expr->data.cond.expr1); + expr->data.cond.expr2 = CInline_FoldConst(expr->data.cond.expr2); + return expr; + + case EMFPOINTER: + expr->data.mfpointer.accessnode = CInline_FoldConst(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CInline_FoldConst(expr->data.mfpointer.mfpointer); + return expr; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_FoldConst(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_FoldConst(list->node); + return expr; + + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CInline_FoldConst(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CInline_FoldConst(expr->data.nullcheck.condexpr); + return expr; + + case EMEMBER: + if (expr->data.emember->expr) + expr->data.emember->expr = CInline_FoldConst(expr->data.emember->expr); + return expr; + + default: + CError_FATAL(421); + return expr; + } +} + +// unknown name +inline SInt32 CInline_GetLocalID2(Object *object) { + ObjectList *list; + SInt32 counter; + + for (list = locals, counter = 0; list; list = list->next) { + if (list->object->datatype == DLOCAL) { + if (list->object == object) + return counter; + counter++; + } + } + + return -1; +} + +SInt32 CInline_GetLocalID(Object *object) { + ObjectList *list; + SInt32 counter; + + if (object) { + for (list = arguments, counter = 0; list; list = list->next, counter++) { + if (list->object == object) { + loc_args[counter].xD = 1; + loc_args[counter].xE = 0; + return counter - 0x7FFFFFFF; + } + } + + counter = CInline_GetLocalID2(object); + CError_ASSERT(465, counter >= 0); + loc_vars[counter].xD = 1; + return counter + 1; + } + + return 0; +} + +static Boolean CInline_IsTrivialExpression(ENode *expr) { + while (1) { + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case EOBJREF: + case EARGOBJ: + case ELOCOBJ: + case EOBJLIST: + case EVECTOR128CONST: + return 0; + + case ESTRINGCONST: + return copts.dont_reuse_strings; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_IsTrivialExpression(expr->data.emember->expr); + return 0; + + case EINDIRECT: + if (ENODE_IS(expr->data.monadic, EOBJREF)) { + if (expr->data.monadic->data.objref->datatype == DLOCAL && + !(expr->data.monadic->data.objref->flags & OBJECT_FLAGS_2)) + return 0; + + if (is_const_object(expr->data.monadic->data.objref)) + return 0; + + return 1; + } + + return 1; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EFORCELOAD: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EINSTRUCTION: + return 1; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + continue; + + case EMUL: + case EDIV: + case EMODULO: + 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 ECOMMA: + case EROTL: + case EROTR: + if (CInline_IsTrivialExpression(expr->data.diadic.left)) + return 1; + expr = expr->data.diadic.right; + continue; + + case ECOND: + if (CInline_IsTrivialExpression(expr->data.cond.cond)) + return 1; + if (CInline_IsTrivialExpression(expr->data.cond.expr1)) + return 1; + expr = expr->data.cond.expr2; + continue; + + default: + CError_FATAL(582); + } + } +} + +Boolean CInline_ExpressionHasSideEffect(ENode *expr) { + while (1) { + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EOBJLIST: + case EVECTOR128CONST: + return 0; + + case EPOSTINC: + case EPOSTDEC: + 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 EFUNCCALL: + case EFUNCCALLP: + case EINSTRUCTION: + return 1; + + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + continue; + + case EMUL: + case EDIV: + case EMODULO: + 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 ECOMMA: + case EROTL: + case EROTR: + if (CInline_ExpressionHasSideEffect(expr->data.diadic.left)) + return 1; + expr = expr->data.diadic.right; + continue; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_ExpressionHasSideEffect(expr->data.emember->expr); + return 0; + + case EMFPOINTER: + if (CInline_ExpressionHasSideEffect(expr->data.mfpointer.accessnode)) + return 1; + expr = expr->data.mfpointer.mfpointer; + continue; + + case ENULLCHECK: + if (CInline_ExpressionHasSideEffect(expr->data.nullcheck.nullcheckexpr)) + return 1; + expr = expr->data.nullcheck.condexpr; + continue; + + case ECOND: + if (CInline_ExpressionHasSideEffect(expr->data.cond.cond)) + return 1; + if (CInline_ExpressionHasSideEffect(expr->data.cond.expr1)) + return 1; + expr = expr->data.cond.expr2; + continue; + + default: + CError_FATAL(689); + } + } +} + +static ENode *CInline_CopyExpressionSave(ENode *expr) { + CInlineCopyMode save_copymode; + Boolean save_globalcopy; + IDTrans *save_idtrans; + + save_globalcopy = enode_globalcopy; + enode_globalcopy = 1; + + save_copymode = enode_copymode; + enode_copymode = CopyMode4; + + save_idtrans = enode_idtrans; + enode_idtrans = NULL; + + expr = CInline_CopyNodes(expr); + + enode_globalcopy = save_globalcopy; + enode_copymode = save_copymode; + enode_idtrans = save_idtrans; + + return expr; +} + +static SInt32 CInline_TranslateID(SInt32 id) { + IDTrans *trans; + + for (trans = enode_idtrans; trans; trans = trans->next) { + if (trans->from == id) + return trans->to; + } + + trans = lalloc(sizeof(IDTrans)); + trans->next = enode_idtrans; + enode_idtrans = trans; + + trans->from = id; + trans->to = CParser_GetUniqueID(); + + return trans->to; +} + +static short CInline_GetLabelStatementNumber(HashNameNode *name) { + Statement *stmt; + short i; + + for (stmt = cinline_first_stmt, i = 0; stmt; stmt = stmt->next, i++) { + if (stmt->type == ST_LABEL && stmt->label->uniquename == name) + return i; + } + + CError_FATAL(742); + return 0; +} + +static ENodeList *CInline_CopyNodeList(ENodeList *list) { + ENodeList *copy; + ENodeList *first; + ENodeList *last; + + first = NULL; + while (list) { + if (enode_globalcopy) + copy = galloc(sizeof(ENodeList)); + else + copy = lalloc(sizeof(ENodeList)); + + copy->node = CInline_CopyNodes(list->node); + copy->next = NULL; + + if (first) { + last->next = copy; + last = copy; + } else { + first = last = copy; + } + + list = list->next; + } + + return first; +} + +static EMemberInfo *CInline_CopyEMemberInfo(EMemberInfo *mi) { + EMemberInfo *copy; + + if (enode_globalcopy) + copy = galloc(sizeof(EMemberInfo)); + else + copy = lalloc(sizeof(EMemberInfo)); + + *copy = *mi; + if (copy->path) + copy->path = CClass_GetPathCopy(copy->path, enode_globalcopy); + if (copy->expr) + copy->expr = CInline_CopyNodes(copy->expr); + + return copy; +} + +static ENode *CInline_CopyNodes(ENode *node) { + ENode *copy; + + if (enode_globalcopy) + copy = galloc(sizeof(ENode)); + else + copy = lalloc(sizeof(ENode)); + + while (1) { + *copy = *node; + switch (copy->type) { + case ETEMPLDEP: + switch (copy->data.templdep.subtype) { + case TDE_PARAM: + case TDE_SIZEOF: + case TDE_ALIGNOF: + case TDE_QUALNAME: + case TDE_OBJ: + break; + case TDE_CAST: + copy->data.templdep.u.cast.args = CInline_CopyNodeList(copy->data.templdep.u.cast.args); + break; + case TDE_SOURCEREF: + copy->data.templdep.u.sourceref.expr = CInline_CopyNodes(copy->data.templdep.u.sourceref.expr); + break; + case TDE_ADDRESS_OF: + copy->data.templdep.u.monadic = CInline_CopyNodes(copy->data.templdep.u.monadic); + break; + default: + CError_FATAL(840); + } + break; + + case ETEMP: + if (enode_copymode == CopyMode3 && copy->data.temp.uniqueid) + copy->data.temp.uniqueid = CInline_TranslateID(copy->data.temp.uniqueid); + break; + + case ELABEL: + switch (enode_copymode) { + case CopyMode2: + copy->data.precompid = CInline_GetLabelStatementNumber(copy->data.label->uniquename); + return copy; + case CopyMode3: + case CopyMode4: { + LabelTrans *trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + trans->id = copy->data.precompid; + trans->labelptr = ©->data.label; + return copy; + } + } + break; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + copy->data.monadic = CInline_CopyNodes(copy->data.monadic); + break; + + ENODE_CASE_DIADIC_ALL: + copy->data.diadic.left = CInline_CopyNodes(copy->data.diadic.left); + copy->data.diadic.right = CInline_CopyNodes(copy->data.diadic.right); + break; + + case ECOND: + copy->data.cond.cond = CInline_CopyNodes(copy->data.cond.cond); + copy->data.cond.expr1 = CInline_CopyNodes(copy->data.cond.expr1); + copy->data.cond.expr2 = CInline_CopyNodes(copy->data.cond.expr2); + break; + + case EMFPOINTER: + copy->data.mfpointer.accessnode = CInline_CopyNodes(copy->data.mfpointer.accessnode); + copy->data.mfpointer.mfpointer = CInline_CopyNodes(copy->data.mfpointer.mfpointer); + break; + + case EFUNCCALL: + case EFUNCCALLP: + copy->data.funccall.funcref = CInline_CopyNodes(copy->data.funccall.funcref); + copy->data.funccall.args = CInline_CopyNodeList(copy->data.funccall.args); + break; + + case ENULLCHECK: + copy->data.nullcheck.precompid = CInline_TranslateID(copy->data.nullcheck.precompid); + copy->data.nullcheck.nullcheckexpr = CInline_CopyNodes(copy->data.nullcheck.nullcheckexpr); + copy->data.nullcheck.condexpr = CInline_CopyNodes(copy->data.nullcheck.condexpr); + break; + + case EPRECOMP: + copy->data.precompid = CInline_TranslateID(copy->data.precompid); + break; + + case EINDIRECT: + if ( + enode_copymode == CopyMode4 && + ENODE_IS(copy->data.monadic, EARGOBJ) && + local_aobjects[copy->data.monadic->data.longval].object == NULL + ) + { + CError_ASSERT(910, local_aobjects[copy->data.monadic->data.longval].expr1); + copy = CInline_CopyExpressionSave(local_aobjects[copy->data.monadic->data.longval].expr1); + if (copy->rtype != node->rtype) { + if (IS_TYPE_INT(copy->rtype) && IS_TYPE_INT(node->rtype)) + copy = makemonadicnode(copy, ETYPCON); + copy->rtype = node->rtype; + } + return copy; + } + + copy->data.monadic = CInline_CopyNodes(copy->data.monadic); + break; + + case EOBJREF: + if (enode_copymode == CopyMode2) { + ObjectList *list; + int i; + + if (node->data.objref->datatype == DALIAS) { + CExpr_AliasTransform(node); + continue; + } + + if (node->data.objref->datatype == DDATA) + return copy; + + for (list = arguments, i = 0; list; list = list->next, i++) { + if (list->object == copy->data.objref) { + copy->type = EARGOBJ; + copy->data.longval = i; + return copy; + } + } + + i = CInline_GetLocalID2(copy->data.objref); + if (i >= 0) { + copy->type = ELOCOBJ; + copy->data.longval = i; + return copy; + } + + if (node->data.objref->datatype == DLOCAL) + CError_FATAL(949); + } + break; + + case EARGOBJ: + switch (enode_copymode) { + case CopyMode4: + CError_ASSERT(957, local_aobjects[copy->data.longval].object); + copy->type = EOBJREF; + copy->data.objref = local_aobjects[copy->data.longval].object; + return copy; + + case CopyMode3: { + ObjectList *list; + int i; + for (list = arguments, i = 0; list; list = list->next, i++) { + if (i == copy->data.longval) { + copy->type = EOBJREF; + copy->data.objref = list->object; + CError_ASSERT(966, copy->data.objref); + return copy; + } + } + } + + default: + CError_FATAL(971); + } + + case ELOCOBJ: + switch (enode_copymode) { + case CopyMode4: + copy->type = EOBJREF; + copy->data.objref = local_dobjects[copy->data.longval]; + return copy; + + case CopyMode3: { + ObjectList *list; + int i; + for (list = locals, i = 0; list; list = list->next, i++) { + if (i == copy->data.longval) { + copy->type = EOBJREF; + copy->data.objref = list->object; + CError_ASSERT(986, copy->data.objref); + return copy; + } + } + } + + default: + CError_FATAL(991); + } + break; + + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + copy->data.newexception.initexpr = CInline_CopyNodes(copy->data.newexception.initexpr); + copy->data.newexception.tryexpr = CInline_CopyNodes(copy->data.newexception.tryexpr); + break; + + case EINITTRYCATCH: + copy->data.itc.initexpr = CInline_CopyNodes(copy->data.itc.initexpr); + copy->data.itc.tryexpr = CInline_CopyNodes(copy->data.itc.tryexpr); + copy->data.itc.catchexpr = CInline_CopyNodes(copy->data.itc.catchexpr); + copy->data.itc.result = CInline_CopyNodes(copy->data.itc.result); + break; + + case EMEMBER: + copy->data.emember = CInline_CopyEMemberInfo(copy->data.emember); + break; + + default: + CError_FATAL(1015); + } + + return copy; + } +} + +static void CInline_CheckUsage(ENode *expr, Boolean flag) { + ENodeList *list; + ENode *inner; + + while (1) { + switch (expr->type) { + case EARGOBJ: + loc_args[expr->data.longval].xD = 1; + loc_args[expr->data.longval].xE = 0; + return; + + case ELOCOBJ: + loc_vars[expr->data.longval].xD = 1; + return; + + case EINDIRECT: + if (ENODE_IS((inner = expr->data.monadic), EARGOBJ)) { + loc_args[inner->data.longval].xD = 1; + if (flag) + loc_args[inner->data.longval].xE = 0; + return; + } + expr = expr->data.monadic; + flag = 0; + continue; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + flag = 0; + continue; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = expr->data.monadic; + flag = 1; + continue; + + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + CInline_CheckUsage(expr->data.diadic.left, 1); + expr = expr->data.diadic.right; + flag = 0; + continue; + + case EMUL: + case EDIV: + case EMODULO: + 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 ECOMMA: + case EROTL: + case EROTR: + CInline_CheckUsage(expr->data.diadic.left, 0); + expr = expr->data.diadic.right; + flag = 0; + continue; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EOBJLIST: + case EVECTOR128CONST: + return; + + case EMEMBER: + if (expr->data.emember->expr) + CInline_CheckUsage(expr->data.emember->expr, 0); + return; + + case EFUNCCALL: + case EFUNCCALLP: + CInline_CheckUsage(expr->data.funccall.funcref, 0); + for (list = expr->data.funccall.args; list; list = list->next) + CInline_CheckUsage(list->node, 0); + return; + + case ENULLCHECK: + CInline_CheckUsage(expr->data.nullcheck.nullcheckexpr, 0); + expr = expr->data.nullcheck.condexpr; + flag = 0; + continue; + + case EMFPOINTER: + CInline_CheckUsage(expr->data.mfpointer.accessnode, 0); + expr = expr->data.mfpointer.mfpointer; + flag = 0; + continue; + + case ECOND: + CInline_CheckUsage(expr->data.cond.cond, 0); + CInline_CheckUsage(expr->data.cond.expr1, 0); + expr = expr->data.cond.expr2; + flag = 0; + continue; + + case EINSTRUCTION: + return; + + default: + CError_FATAL(1146); + } + } +} + +ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode) { + enode_copymode = mode; + + switch (mode) { + case CopyMode0: + case CopyMode4: + enode_idtrans = NULL; + enode_globalcopy = 0; + expr = CInline_CopyNodes(expr); + break; + case CopyMode3: + enode_globalcopy = 0; + expr = CInline_CopyNodes(expr); + break; + case CopyMode1: + enode_idtrans = NULL; + enode_globalcopy = 1; + expr = CInline_CopyNodes(expr); + break; + case CopyMode2: + enode_idtrans = NULL; + enode_globalcopy = 1; + expr = CInline_CopyNodes(expr); + CInline_CheckUsage(expr, 0); + break; + } + + return expr; +} + +static UInt8 CInline_GetObjectSFlags(Object *object) { + UInt8 flags; + + switch (object->sclass) { + case 0: + flags = CI_SFLAGS_NoClass; + break; + case TK_REGISTER: + flags = CI_SFLAGS_Register; + break; + case TK_AUTO: + flags = CI_SFLAGS_Auto; + break; + default: + CError_FATAL(1204); + } + + if (object->flags & OBJECT_FLAGS_2) + flags |= CI_SFLAGS_HasObjectFlag2; + + return flags; +} + +static void CInline_SetObjectSFlags(Object *object, UInt8 sflags) { + if (sflags & CI_SFLAGS_HasObjectFlag2) { + object->flags |= OBJECT_FLAGS_2; + sflags &= ~CI_SFLAGS_HasObjectFlag2; + } + + switch (sflags) { + case CI_SFLAGS_NoClass: + object->sclass = 0; + break; + case CI_SFLAGS_Register: + object->sclass = TK_REGISTER; + break; + case CI_SFLAGS_Auto: + object->sclass = TK_AUTO; + break; + default: + CError_FATAL(1229); + } +} + +static Object *CInline_NewLocalObject(Type *type, short qual, UInt8 sflags, int unk) { + Object *object = CParser_NewLocalDataObject(NULL, 1); + object->name = CParser_GetUniqueName(); + object->type = type; + object->qual = qual; + CInline_SetObjectSFlags(object, sflags); + CFunc_SetupLocalVarInfo(object); + return object; +} + +static ENode *CInline_FuncArgConvert(ENode *expr) { + ENode *copy; + + switch (expr->type) { + case EOBJREF: + copy = lalloc(sizeof(ENode)); + *copy = *expr; + return copy; + case ETEMP: + CError_FATAL(1272); + } + + return NULL; +} + +static ENode *CInline_RefArgTransform(ENode *expr, Boolean flag) { + ENodeList *arg; + + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + + switch (expr->type) { + case EOBJREF: + case ETEMP: + if (flag) + return CInline_FuncArgConvert(expr); + break; + + case EFUNCCALL: + if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && + expr->data.funccall.args + ) + return CInline_FuncArgConvert(expr->data.funccall.args->node); + + if ( + TPTR_TARGET(expr->rtype) == expr->data.funccall.functype->functype && + CMach_GetFunctionResultClass(expr->data.funccall.functype) == 1 && + (arg = expr->data.funccall.args) + ) + { + switch (CABI_GetStructResultArgumentIndex(expr->data.funccall.functype)) { + case 0: + break; + case 1: + if ((arg = arg->next)) + break; + CError_FATAL(1313); + default: + CError_FATAL(1314); + } + + return CInline_FuncArgConvert(arg->node); + } + } + break; + } + + return NULL; +} + +static ENode *CInline_SetupArgsExpression(Object *object, CI_FuncData *data, ENodeList *list) { + ENode *commaNodes; + CI_Var *var; + ENodeList *scan; + ENode *expr; + SInt32 i; + Boolean is_oldstyle; + + is_oldstyle = 0; + if (TYPE_FUNC(object->type)->args == &oldstyle) + is_oldstyle = 1; + + local_dobjects = lalloc(sizeof(Object *) * data->numlocals); + local_aobjects = lalloc(sizeof(AObject) * data->numarguments); + + for (i = 0, var = data->locals; i < data->numlocals; i++, var++) { + if (var->xD) { + object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); + local_dobjects[i] = object; + if (!var->xE) + object->flags |= OBJECT_FLAGS_2; + } else { + local_dobjects[i] = NULL; + } + } + + for (i = 0, var = data->arguments, scan = list; i < data->numarguments; i++, var++) { + local_aobjects[i].expr2 = NULL; + + if (!var->xD) { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = NULL; + } else if ( + scan && + var->xE && + !CInline_IsTrivialExpression(scan->node) && + (!is_oldstyle || scan->node->rtype->size == var->type->size) + ) + { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = scan->node; + } else if ( + scan && + var->xE && + IS_TYPE_REFERENCE(var->type) && + (expr = CInline_RefArgTransform(scan->node, 1)) + ) + { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = expr; + local_aobjects[i].expr2 = scan->node; + } else { + local_aobjects[i].object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); + local_aobjects[i].expr1 = NULL; + } + + if (scan) + scan = scan->next; + } + + commaNodes = NULL; + + for (i = 0, scan = list; scan; scan = scan->next, i++) { + if (i >= data->numarguments) { + if (!commaNodes) + commaNodes = scan->node; + else + commaNodes = makecommaexpression(scan->node, commaNodes); + } else if (!local_aobjects[i].object || local_aobjects[i].expr2) { + if (local_aobjects[i].expr2) { + if (!commaNodes) + commaNodes = local_aobjects[i].expr2; + else + commaNodes = makecommaexpression(local_aobjects[i].expr2, commaNodes); + } else if (!local_aobjects[i].expr1 && CInline_IsTrivialExpression(scan->node)) { + commaNodes = !commaNodes ? scan->node : makecommaexpression(scan->node, commaNodes); + CError_ASSERT(1470, !ENODE_IS(scan->node, EPRECOMP)); + } + } else { + if (is_oldstyle && scan->node->rtype->size != local_aobjects[i].object->type->size) { + scan->node = makemonadicnode(scan->node, ETYPCON); + scan->node->rtype = local_aobjects[i].object->type; + } + + expr = makediadicnode(create_objectnode2(local_aobjects[i].object), scan->node, EASS); + if (!commaNodes) + commaNodes = expr; + else + commaNodes = makecommaexpression(expr, commaNodes); + } + } + + return commaNodes; +} + +static void CInline_ReturnCheckCB(ENode *expr) { + cinline_has_sideeffect = 1; +} + +static ENode *CInline_ReturnCheck(ENode *expr) { + ENode *copy; + + if (ENODE_IS(expr, EFORCELOAD)) + return expr; + + cinline_has_sideeffect = 0; + CExpr_SearchExprTree(expr, CInline_ReturnCheckCB, 3, EINDIRECT, EFUNCCALL, EFUNCCALLP); + + if (!cinline_has_sideeffect) + return expr; + + copy = lalloc(sizeof(ENode)); + *copy = *expr; + copy->type = EFORCELOAD; + + copy->data.monadic = expr; + return copy; +} + +static ENode *CInline_ReturnMemResult(Object *object) { + int index = CABI_GetStructResultArgumentIndex(TYPE_FUNC(object->type)); + if (local_aobjects[index].object == NULL) + return CInline_CopyExpressionSave(local_aobjects[index].expr1); + else + return create_objectnode(local_aobjects[index].object); +} + +static ENode *CInline_InlineFunctionExpression(ENode *expr) { + Object *object; + CI_FuncData *funcdata; + short i; + Boolean flag26; + ENode *argsExpr; + + object = expr->data.funccall.funcref->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + funcdata = object->u.func.u.ifuncdata; + if (!funcdata) + return expr; + + if (funcdata->can_inline < CI_CanInline6) { + if (funcdata->can_inline == CI_CanInline3) { + if (cinline_unconditionalpart && cinline_stmtlevelexprs < 16) + cinline_stmtlevelexpr[cinline_stmtlevelexprs++] = expr; + cinline_serialize_stmt = 1; + } + return expr; + } + + flag26 = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)) == 1; + argsExpr = CInline_SetupArgsExpression(object, funcdata, expr->data.funccall.args); + + for (i = 0; i < funcdata->numstatements; i++) { + switch (funcdata->statements[i].type) { + case ST_RETURN: + if (funcdata->statements[i].u.expr) { + ENode *copy = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); + if (flag26) { + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, copy); + else + argsExpr = copy; + + argsExpr = makecommaexpression(argsExpr, CInline_ReturnMemResult(object)); + } else { + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, CInline_ReturnCheck(copy)); + else + argsExpr = CInline_ReturnCheck(copy); + } + } + break; + case ST_EXPRESSION: + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4)); + else + argsExpr = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); + break; + + default: + CError_FATAL(1632); + } + } + + if (!argsExpr) + argsExpr = nullnode(); + if (!IS_TYPE_VOID(expr->rtype)) + argsExpr->rtype = expr->rtype; + + inline_expanded = 1; + return CInline_FoldConst(argsExpr); +} + +static Boolean CInline_CanExpand(ENode *expr) { + TypeFunc *tfunc; + Object *object; + + object = expr->data.objref; + tfunc = TYPE_FUNC(object->type); + + if ( + IS_TYPE_FUNC(tfunc) && + ((object->qual & Q_INLINE) || (tfunc->flags & FUNC_FLAGS_800)) && + (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) + ) + return 1; + + return 0; +} + +static SInt32 CInline_EstimateSizeOfExpr(ENode *expr, SInt32 size, SInt32 level) { + ENodeList *list; + + switch (expr->type) { + ENODE_CASE_MONADIC: + size = CInline_EstimateSizeOfExpr(expr->data.monadic, size, level) + 1; + break; + + ENODE_CASE_DIADIC_ALL: + size = CInline_EstimateSizeOfExpr(expr->data.diadic.left, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.diadic.right, size, level) + 1; + break; + + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && + CInline_CanExpand(expr->data.funccall.funcref) + ) + { + recursive_inline |= expr->data.funccall.funcref->data.objref == expanding_function; + if (level == 0) { + if (!recursive_inline) + size = inline_max_size + 1; + } else { + size = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); + } + } else { + size++; + } + + for (list = expr->data.funccall.args; list; list = list->next) { + if (size > inline_max_size) + break; + + size = CInline_EstimateSizeOfExpr(list->node, size, level); + } + break; + + case ECOND: + size = CInline_EstimateSizeOfExpr(expr->data.cond.cond, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.cond.expr1, size, level) + 1; + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.cond.expr2, size, level) + 1; + break; + + case ENULLCHECK: + size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.nullcheckexpr, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.condexpr, size, level) + 1; + break; + + case EMFPOINTER: + size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.accessnode, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.mfpointer, size, level) + 1; + break; + + case EMEMBER: + if (expr->data.emember->expr) + size = CInline_EstimateSizeOfExpr(expr->data.emember->expr, size, level) + 1; + break; + + default: + size++; + } + + return size; +} + +static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level) { + CI_Statement *stmt; + SInt32 i; + + size += funcdata->numstatements; + if (size > inline_max_size) + return size; + + for (i = 0, stmt = funcdata->statements; i < funcdata->numstatements; i++, stmt++) { + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); + break; + case ST_SWITCH: + size = CInline_EstimateSizeOfExpr(stmt->u.switchdata->expr, size, level); + break; + case ST_RETURN: + if (stmt->u.expr) + size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); + break; + default: + CError_FATAL(1840); + } + + if (size > inline_max_size) + break; + } + + return size; +} + +static SInt32 EstimateExpandedSizeOfExpr(ENode *expr, SInt32 level) { + ENodeList *list; + SInt32 size; + + size = 0; + + switch (expr->type) { + ENODE_CASE_MONADIC: + size = EstimateExpandedSizeOfExpr(expr->data.monadic, level) + 1; + break; + + ENODE_CASE_DIADIC_ALL: + size = EstimateExpandedSizeOfExpr(expr->data.diadic.left, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.diadic.right, level); + break; + + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && + CInline_CanExpand(expr->data.funccall.funcref) + ) + { + if (level) { + SInt32 est = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); + if (est > inline_max_size) + size++; + else + size += est; + } else { + size++; + } + } else { + size++; + } + + for (list = expr->data.funccall.args; list; list = list->next) + size += EstimateExpandedSizeOfExpr(list->node, level); + break; + + case ECOND: + size = EstimateExpandedSizeOfExpr(expr->data.cond.cond, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.cond.expr1, level); + size += EstimateExpandedSizeOfExpr(expr->data.cond.expr2, level); + break; + + case ENULLCHECK: + size = EstimateExpandedSizeOfExpr(expr->data.nullcheck.nullcheckexpr, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.nullcheck.condexpr, level); + break; + + case EMFPOINTER: + size = EstimateExpandedSizeOfExpr(expr->data.mfpointer.accessnode, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.mfpointer.mfpointer, level); + break; + + case EMEMBER: + if (expr->data.emember->expr) + size = EstimateExpandedSizeOfExpr(expr->data.emember->expr, level); + break; + + default: + size++; + } + + return size; +} + +static SInt32 EstimateExpandedSizeOfFunction(Statement *stmt) { + SInt32 size; + SInt32 level; + + level = copts.inlinelevel; + if (!level) + level = 8; + + size = 0; + + while (stmt) { + switch (stmt->type) { + case ST_NOP: + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + size++; + size += EstimateExpandedSizeOfExpr(stmt->expr, level); + break; + case ST_RETURN: + size++; + if (stmt->expr) + size = EstimateExpandedSizeOfExpr(stmt->expr, level); + break; + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + size++; + break; + default: + CError_FATAL(2015); + } + + stmt = stmt->next; + } + + return size; +} + +static Boolean CInline_InlineFunctionCheck(ENode *expr) { + Object *object; + SInt32 level; + CI_FuncData *funcdata; + + object = expr->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + if ( + IS_TYPE_FUNC(object->type) && + ((object->qual & Q_INLINE) || (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_800)) && + (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) + ) + { + if (copts.always_inline) + return 1; + + if (copts.inline_bottom_up) { + if (!object->u.func.u.ifuncdata) + return 0; + + level = (copts.inlinelevel == 0) ? (7 - cinline_level) : (copts.inlinelevel - cinline_level - 1); + if ((object->qual & Q_INLINE) && level == 0) + return 1; + + if (CInline_EstimateSizeOfFunc(object->u.func.u.ifuncdata, 0, level) > inline_max_size) + return 0; + } else if (cinline_level > 0 && copts.inlinelevel == 0) { + funcdata = object->u.func.u.ifuncdata; + if (!funcdata) + return 0; + + if (funcdata->numstatements > 10) + return 0; + if (cinline_level > 1 && funcdata->numstatements > 7) + return 0; + if (cinline_level > 2 && funcdata->numstatements > 3) + return 0; + } + + return 1; + } else { + return 0; + } + + return 0; +} + +static ENode *CInline_ExpandExpression(ENode *expr) { + ENodeList *list; + Boolean save; + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); + break; + + case EFORCELOAD: + expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); + if (ENODE_IS(expr->data.monadic, EFORCELOAD)) + expr->data.monadic = expr->data.monadic->data.monadic; + break; + + case EMUL: + case EDIV: + case EMODULO: + 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 EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EPMODULO: + case EROTL: + case EROTR: + expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); + expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); + break; + + case ELAND: + case ELOR: + case ECOMMA: + expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); + cinline_unconditionalpart = save; + break; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_ExpandExpression(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_ExpandExpression(list->node); + + if (ENODE_IS(expr->data.funccall.funcref, EOBJREF) && CInline_InlineFunctionCheck(expr->data.funccall.funcref)) + expr = CInline_InlineFunctionExpression(expr); + break; + + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CInline_ExpandExpression(expr->data.nullcheck.nullcheckexpr); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.nullcheck.condexpr = CInline_ExpandExpression(expr->data.nullcheck.condexpr); + cinline_unconditionalpart = save; + break; + + case EMFPOINTER: + expr->data.mfpointer.accessnode = CInline_ExpandExpression(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CInline_ExpandExpression(expr->data.mfpointer.mfpointer); + break; + + case ECOND: + expr->data.cond.cond = CInline_ExpandExpression(expr->data.cond.cond); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.cond.expr1 = CInline_ExpandExpression(expr->data.cond.expr1); + expr->data.cond.expr2 = CInline_ExpandExpression(expr->data.cond.expr2); + cinline_unconditionalpart = save; + break; + + case EMEMBER: + if (expr->data.emember->expr) + expr = CInline_ExpandExpression(expr->data.emember->expr); + else + expr = nullnode(); + break; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + + default: + CError_FATAL(2235); + } + + return expr; +} + +static Statement *CInline_NewStatement(StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + memclrw(stmt, sizeof(Statement)); + + stmt->type = sttype; + if (cinline_serial_stmt) + cinline_cur_serial_stmt->next = stmt; + else + cinline_serial_stmt = stmt; + cinline_cur_serial_stmt = stmt; + + return stmt; +} + +static ENode *CInline_LoadToTemp(ENode *expr, Object **objectptr) { + Object *object; + + object = *objectptr; + if (!object) { + switch (expr->rtype->type) { + case TYPEVOID: + return expr; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + object = create_temp_object(expr->rtype); + *objectptr = object; + break; + default: + CError_FATAL(2288); + } + } + + return makediadicnode(create_objectnode(object), expr, EASS); +} + +static ENode *CInline_SerializeEFORCELOAD(ENode *expr) { + Statement *stmt; + Object *temp = NULL; + + while (ENODE_IS(expr->data.monadic, EFORCELOAD)) { + expr->data.monadic = expr->data.monadic->data.monadic; + } + + expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = CInline_LoadToTemp(expr->data.monadic, &temp); + return create_objectnode(temp); +} + +static ENode *CInline_SerializeECOMMA(ENode *expr) { + Statement *stmt; + + expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = expr->data.diadic.left; + return CInline_SerializeExpr(expr->data.diadic.right); +} + +static ENode *CInline_SerializeELOR(ENode *expr) { + ENode *n; + Statement *stmt; + CLabel *label; + Object *temp = NULL; + + label = newlabel(); + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_IFGOTO); + stmt->expr = n; + stmt->label = label; + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeELAND(ENode *expr) { + ENode *n; + Statement *stmt; + CLabel *label; + Object *temp = NULL; + + label = newlabel(); + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = n; + stmt->label = label; + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeEPRECOMP(ENode *expr) { + UIDTemp *uidtemp; + + uidtemp = cinline_uid_temps; + while (1) { + if (!uidtemp) + CError_FATAL(2449); + if (uidtemp->uid == expr->data.precompid) + return create_objectnode(uidtemp->object); + uidtemp = uidtemp->next; + } +} + +static ENode *CInline_SerializeENULLCHECK(ENode *expr) { + Statement *stmt; + CLabel *label; + ENode *n; + Object *temp = NULL; + UIDTemp uidtemp; + + label = newlabel(); + + n = CInline_SerializeExpr(expr->data.nullcheck.nullcheckexpr); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = CInline_LoadToTemp(n, &temp); + stmt->label = label; + + uidtemp.next = cinline_uid_temps; + uidtemp.object = temp; + uidtemp.uid = expr->data.nullcheck.precompid; + cinline_uid_temps = &uidtemp; + + n = CInline_SerializeExpr(expr->data.nullcheck.condexpr); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = CInline_LoadToTemp(n, &temp); + + cinline_uid_temps = uidtemp.next; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeECOND(ENode *expr) { + Statement *stmt; + CLabel *label1; + CLabel *label2; + ENode *n; + Object *temp = NULL; + + label1 = newlabel(); + label2 = newlabel(); + + n = CInline_SerializeExpr(expr->data.cond.cond); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = n; + stmt->label = label1; + + n = CInline_SerializeExpr(expr->data.cond.expr1); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_GOTO); + stmt->label = label2; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label1; + label1->stmt = stmt; + + n = CInline_SerializeExpr(expr->data.cond.expr2); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label2; + label2->stmt = stmt; + + if (!temp) { + n = nullnode(); + n->rtype = &stvoid; + return n; + } + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeExpr(ENode *expr) { + ENodeList *list; + + switch (expr->type) { + case EFORCELOAD: + return CInline_SerializeEFORCELOAD(expr); + case ECOMMA: + return CInline_SerializeECOMMA(expr); + case ELAND: + return CInline_SerializeELAND(expr); + case ELOR: + return CInline_SerializeELOR(expr); + case EPRECOMP: + return CInline_SerializeEPRECOMP(expr); + case ENULLCHECK: + return CInline_SerializeENULLCHECK(expr); + case ECOND: + return CInline_SerializeECOND(expr); + + case EINITTRYCATCH: + expr->data.itc.initexpr = CInline_SerializeExpr(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CInline_SerializeExpr(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CInline_SerializeExpr(expr->data.itc.catchexpr); + expr->data.itc.result = CInline_SerializeExpr(expr->data.itc.result); + return expr; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); + return expr; + + case EMUL: + case EDIV: + case EMODULO: + 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 EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EPMODULO: + case EROTL: + case EROTR: + expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); + expr->data.diadic.right = CInline_SerializeExpr(expr->data.diadic.right); + return expr; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_SerializeExpr(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_SerializeExpr(list->node); + return expr; + + case EMFPOINTER: + // bug??? + expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.accessnode); + expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.mfpointer); + return expr; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_SerializeExpr(expr->data.emember->expr); + return expr; + + default: + CError_FATAL(2684); + return expr; + } +} + +void CInline_SerializeStatement(Statement *stmt) { + Statement *scan; + Statement *copy; + + cinline_serial_stmt = NULL; + cinline_uid_temps = NULL; + stmt->expr = CInline_SerializeExpr(stmt->expr); + + if (cinline_serial_stmt) { + for (scan = cinline_serial_stmt; scan; scan = scan->next) { + scan->value = stmt->value; + scan->dobjstack = stmt->dobjstack; + scan->sourceoffset = stmt->sourceoffset; + scan->sourcefilepath = stmt->sourcefilepath; + } + + copy = CInline_NewStatement(ST_EXPRESSION); + *copy = *stmt; + + *stmt = *cinline_serial_stmt; + } +} + +static void CInline_UnpackSwitch(Statement *stmt, CI_Statement *packstmt, CLabel **labels) { + SwitchInfo *info; + SwitchCase *swcase; + short i; + + info = lalloc(sizeof(SwitchInfo)); + stmt->label = (CLabel *) info; + CError_ASSERT(2730, info->defaultlabel = labels[packstmt->u.switchdata->defaultlabelID]); + info->x8 = packstmt->u.switchdata->unkSwitch8; + + for (i = 0; i < packstmt->u.switchdata->numcases; i++) { + if (i == 0) { + swcase = lalloc(sizeof(SwitchCase)); + info->cases = swcase; + } else { + swcase->next = lalloc(sizeof(SwitchCase)); + swcase = swcase->next; + } + + swcase->next = NULL; + swcase->min = packstmt->u.switchdata->cases[i].min; + swcase->max = packstmt->u.switchdata->cases[i].max; + CError_ASSERT(2740, swcase->label = labels[packstmt->u.switchdata->cases[i].labelID]); + } +} + +Object *CInline_GetLocalObj(SInt32 id, Boolean flag) { + ObjectList *list; + + if (id) { + if (id & 0x80000000) { + id = (id & 0x7FFFFFFF) - 1; + if (flag) { + CError_ASSERT(2761, local_aobjects[id].object); + return local_aobjects[id].object; + } + + for (list = arguments; list; list = list->next, id--) { + if (id == 0) + return list->object; + } + + CError_FATAL(2765); + } else { + id--; + if (flag) { + CError_ASSERT(2772, local_dobjects[id]); + return local_dobjects[id]; + } + + for (list = locals; list; list = list->next, id--) { + if (id == 0) + return list->object; + } + + CError_FATAL(2776); + } + } + + return NULL; +} + +static ExceptionAction *CInline_UnpackActions(CI_Statement *packstmt, Boolean flag) { + ExceptionAction *packexc; + ExceptionAction *last; + ExceptionAction *exc; + + packexc = packstmt->dobjstack; + last = NULL; + + while (packexc) { + exc = galloc(sizeof(ExceptionAction)); + exc->prev = last; + last = exc; + + exc->type = packexc->type; + + switch (packexc->type) { + case EAT_DESTROYLOCAL: + exc->data.destroy_local.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local.local, flag); + exc->data.destroy_local.dtor = packexc->data.destroy_local.dtor; + break; + case EAT_DESTROYLOCALCOND: + exc->data.destroy_local_cond.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.local, flag); + exc->data.destroy_local_cond.dtor = packexc->data.destroy_local_cond.dtor; + exc->data.destroy_local_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.cond, flag); + break; + case EAT_DESTROYLOCALOFFSET: + exc->data.destroy_local_offset.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_offset.local, flag); + exc->data.destroy_local_offset.dtor = packexc->data.destroy_local_offset.dtor; + exc->data.destroy_local_offset.offset = packexc->data.destroy_local_offset.offset; + break; + case EAT_DESTROYLOCALPOINTER: + exc->data.destroy_local_pointer.pointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_pointer.pointer, flag); + exc->data.destroy_local_pointer.dtor = packexc->data.destroy_local_pointer.dtor; + break; + case EAT_DESTROYLOCALARRAY: + exc->data.destroy_local_array.localarray = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_array.localarray, flag); + exc->data.destroy_local_array.dtor = packexc->data.destroy_local_array.dtor; + exc->data.destroy_local_array.elements = packexc->data.destroy_local_array.elements; + exc->data.destroy_local_array.element_size = packexc->data.destroy_local_array.element_size; + break; + case EAT_DESTROYPARTIALARRAY: + exc->data.destroy_partial_array.arraypointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraypointer, flag); + exc->data.destroy_partial_array.arraycounter = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraycounter, flag); + exc->data.destroy_partial_array.dtor = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.dtor, flag); + exc->data.destroy_partial_array.element_size = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.element_size, flag); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + exc->data.destroy_member.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member.objectptr, flag); + exc->data.destroy_member.dtor = packexc->data.destroy_member.dtor; + exc->data.destroy_member.offset = packexc->data.destroy_member.offset; + break; + case EAT_DESTROYMEMBERCOND: + exc->data.destroy_member_cond.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.objectptr, flag); + exc->data.destroy_member_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.cond, flag); + exc->data.destroy_member_cond.dtor = packexc->data.destroy_member_cond.dtor; + exc->data.destroy_member_cond.offset = packexc->data.destroy_member_cond.offset; + break; + case EAT_DESTROYMEMBERARRAY: + exc->data.destroy_member_array.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_array.objectptr, flag); + exc->data.destroy_member_array.dtor = packexc->data.destroy_member_array.dtor; + exc->data.destroy_member_array.offset = packexc->data.destroy_member_array.offset; + exc->data.destroy_member_array.elements = packexc->data.destroy_member_array.elements; + exc->data.destroy_member_array.element_size = packexc->data.destroy_member_array.element_size; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + exc->data.delete_pointer.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer.pointerobject, flag); + exc->data.delete_pointer.deletefunc = packexc->data.delete_pointer.deletefunc; + break; + case EAT_DELETEPOINTERCOND: + exc->data.delete_pointer_cond.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.pointerobject, flag); + exc->data.delete_pointer_cond.deletefunc = packexc->data.delete_pointer_cond.deletefunc; + exc->data.delete_pointer_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.cond, flag); + break; + case EAT_CATCHBLOCK: { + LabelTrans *trans; + exc->data.catch_block.catch_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_object, flag); + exc->data.catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_info_object, flag); + + trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + + trans->id = (SInt32) packexc->data.catch_block.catch_label; + trans->labelptr = &exc->data.catch_block.catch_label; + + exc->data.catch_block.catch_typeid = packexc->data.catch_block.catch_typeid; + exc->data.catch_block.catch_type = packexc->data.catch_block.catch_type; + exc->data.catch_block.catch_qual = packexc->data.catch_block.catch_qual; + break; + } + case EAT_ACTIVECATCHBLOCK: + exc->data.active_catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.active_catch_block.catch_info_object, flag); + break; + case EAT_SPECIFICATION: { + LabelTrans *trans; + exc->data.specification.unexp_ids = packexc->data.specification.unexp_ids; + exc->data.specification.unexp_id = packexc->data.specification.unexp_id; + + trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + + trans->id = (SInt32) packexc->data.specification.unexp_label; + trans->labelptr = &exc->data.specification.unexp_label; + + exc->data.specification.unexp_info_object = CInline_GetLocalObj((SInt32) packexc->data.specification.unexp_info_object, flag); + break; + } + case EAT_TERMINATE: + break; + default: + CError_FATAL(2904); + } + + packexc = packexc->prev; + } + + return last; +} + +static Statement *CInline_ExpandStatements(Object *funcobj, Statement *stmt, CI_FuncData *funcdata, ENode *funccall, CLabel *label, Object *resultobj, Boolean flag) { + CLabel **labels; + CI_Statement *packstmt; + short i; + CI_StmtLink *stmtLinks; + CI_StmtLink *link; + ENode *setupArgs; + Boolean is_result_class_1; + Statement origStmt; + + origStmt = *stmt; + is_result_class_1 = CMach_GetFunctionResultClass(TYPE_FUNC(funcobj->type)) == 1; + + if ((setupArgs = CInline_SetupArgsExpression(funcobj, funcdata, funccall->data.funccall.args))) { + stmt->type = ST_EXPRESSION; + stmt->expr = CInline_FoldConst(setupArgs); + } else { + stmt->type = ST_NOP; + } + + stmtLinks = NULL; + cinline_label_trans = NULL; + + labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); + memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); + + for (i = 0, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + + stmt->type = packstmt->type; + stmt->flags = packstmt->flags; + stmt->value += packstmt->value; + + if (packstmt->dobjstack) { + ExceptionAction *unpacked = CInline_UnpackActions(packstmt, 1); + if (stmt->dobjstack) { + ExceptionAction *scan = unpacked; + while (scan->prev) + scan = scan->prev; + scan->prev = stmt->dobjstack; + } + stmt->dobjstack = unpacked; + } + + switch (stmt->type) { + case ST_NOP: + break; + + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); + break; + + case ST_RETURN: + if (packstmt->u.expr) { + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); + if (is_result_class_1) + stmt->expr = makecommaexpression(stmt->expr, CInline_ReturnMemResult(funcobj)); + + if (resultobj) { + stmt->type = ST_EXPRESSION; + stmt->expr = makediadicnode(create_objectnode2(resultobj), stmt->expr, EASS); + } else { + stmt->type = origStmt.type; + if (stmt->type == ST_EXPRESSION && !CInline_ExpressionHasSideEffect(stmt->expr)) + stmt->type = ST_NOP; + } + + if (label) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + stmt->type = ST_GOTO; + stmt->label = label; + } + } else { + if (label) { + stmt->type = ST_GOTO; + stmt->label = label; + } else { + stmt->type = ST_NOP; + } + } + break; + + case ST_LABEL: + labels[i] = stmt->label = newlabel(); + stmt->label->stmt = stmt; + break; + + case ST_IFGOTO: + case ST_IFNGOTO: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode4)); + case ST_GOTO: + link = lalloc(sizeof(CI_StmtLink)); + link->next = stmtLinks; + stmtLinks = link; + + link->stmt = stmt; + link->ciStmt = packstmt; + break; + + case ST_SWITCH: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode4)); + case ST_ASM: + link = lalloc(sizeof(CI_StmtLink)); + link->next = stmtLinks; + stmtLinks = link; + + link->stmt = stmt; + link->ciStmt = packstmt; + break; + + default: + CError_FATAL(3040); + } + } + + if (label) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + + stmt->type = ST_LABEL; + stmt->label = label; + label->stmt = stmt; + + if (flag) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + } + } + + while (stmtLinks) { + Statement *linkstmt = stmtLinks->stmt; + packstmt = stmtLinks->ciStmt; + + switch (linkstmt->type) { + case ST_GOTO: + CError_ASSERT(3060, linkstmt->label = labels[packstmt->u.statementnum]); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CError_ASSERT(3065, linkstmt->label = labels[packstmt->u.ifgoto.statementnum]); + break; + case ST_SWITCH: + CInline_UnpackSwitch(linkstmt, packstmt, labels); + break; + case ST_ASM: + InlineAsm_UnpackAsmStatement(linkstmt, labels, 1, packstmt->u.asmdata.data, packstmt->u.asmdata.size); + break; + default: + CError_FATAL(3076); + } + + stmtLinks = stmtLinks->next; + } + + while (cinline_label_trans) { + CError_ASSERT(3083, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); + cinline_label_trans = cinline_label_trans->next; + } + + return stmt; +} + +static Statement *CInline_InlineFunctionStatement(Statement *stmt, Boolean *changed) { + Object *object; + CI_FuncData *funcdata; + CLabel *label; + + *changed = 0; + + object = stmt->expr->data.funccall.funcref->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + funcdata = object->u.func.u.ifuncdata; + if (!funcdata || funcdata->can_inline < CI_CanInline3) + return stmt; + + if (stmt->type != ST_EXPRESSION) { + short i; + for (i = 0; i < (funcdata->numstatements - 1); i++) { + if (funcdata->statements[i].type == ST_RETURN) + return stmt; + } + + if (funcdata->statements[funcdata->numstatements - 1].type != ST_RETURN) + return stmt; + + label = NULL; + } else { + label = newlabel(); + } + + *changed = 1; + CInline_ExpandStatements(object, stmt, funcdata, stmt->expr, label, NULL, 0); +} + +static Statement *CInline_ExtractInlineFunction(Statement *stmt) { + ENode *expr; + CI_FuncData *funcdata; + short i; + Object *funcObject; + Object *resultObject; + + for (i = 0; i < cinline_stmtlevelexprs; i++) { + expr = cinline_stmtlevelexpr[i]; + + funcObject = expr->data.funccall.funcref->data.objref; + if (funcObject->datatype == DALIAS) + funcObject = funcObject->u.alias.object; + + if ((funcdata = funcObject->u.func.u.ifuncdata)) { + TypeFunc *tfunc = TYPE_FUNC(funcObject->type); + CError_ASSERT(3141, IS_TYPE_FUNC(tfunc)); + + if (!IS_TYPE_VOID(tfunc->functype)) { + if (CMach_GetFunctionResultClass(TYPE_FUNC(funcObject->type)) == 1) + resultObject = CInline_NewLocalObject(CDecl_NewPointerType(tfunc->functype), 0, 0, 0); + else + resultObject = CInline_NewLocalObject(tfunc->functype, 0, 0, 0); + } else { + resultObject = NULL; + } + + stmt = CInline_ExpandStatements(funcObject, stmt, funcdata, expr, newlabel(), resultObject, 1); + + if (resultObject) + *expr = *create_objectnode2(resultObject); + else + *expr = *nullnode(); + } + } + + return stmt; +} + +static Statement *CInline_ExpandStatement(Statement *stmt) { + Boolean changed; + + do { + changed = 0; + + if ( + stmt->type == ST_EXPRESSION && + ENODE_IS(stmt->expr, EINDIRECT) && + !CParser_IsVolatile(stmt->expr->rtype, ENODE_QUALS(stmt->expr)) + ) + { + stmt->expr = stmt->expr->data.monadic; + changed = 1; + if (ENODE_IS2(stmt->expr, EOBJREF, EBITFIELD)) + stmt->expr = nullnode(); + } + + if (ENODE_IS(stmt->expr, ECOMMA)) { + Statement *newStmt = lalloc(sizeof(Statement)); + *newStmt = *stmt; + + stmt->next = newStmt; + stmt->type = ST_EXPRESSION; + stmt->expr = stmt->expr->data.diadic.left; + newStmt->expr = newStmt->expr->data.diadic.right; + + changed = 1; + } + } while (changed); + + if ( + ENODE_IS2(stmt->expr, EFUNCCALL, EFUNCCALLP) && + ENODE_IS(stmt->expr->data.funccall.funcref, EOBJREF) && + CInline_InlineFunctionCheck(stmt->expr->data.funccall.funcref) + ) + { + stmt = CInline_InlineFunctionStatement(stmt, &changed); + if (changed) { + any_inline_expanded = 1; + return stmt; + } + } + + inline_expanded = 0; + cinline_unconditionalpart = 1; + cinline_serialize_stmt = 0; + cinline_stmtlevelexprs = 0; + stmt->expr = CInline_ExpandExpression(stmt->expr); + + if (cinline_serialize_stmt) { + cinline_unconditionalpart = 1; + cinline_serialize_stmt = 0; + cinline_stmtlevelexprs = 0; + CInline_SerializeStatement(stmt); + stmt->expr = CInline_ExpandExpression(stmt->expr); + } + + if (inline_expanded) { + stmt->expr = CInline_FoldConst(stmt->expr); + any_inline_expanded = 1; + } + + if (cinline_stmtlevelexprs) { + stmt = CInline_ExtractInlineFunction(stmt); + any_inline_expanded = 1; + } + + return stmt; +} + +static void CInline_ForceReverseSearch(ENode *) { + cinline_funccallfound = 1; +} + +static ENode *CInline_ForceReverseEvaluation(ENode *expr) { + ENode *commanodes; + ENodeList *list; + int counter; + ENode *ass; + ENode *inner; + ENode *copy; + + list = expr->data.funccall.args; + counter = 0; + commanodes = NULL; + + while (list) { + cinline_funccallfound = 0; + inner = list->node; + CExpr_SearchExprTree(inner, CInline_ForceReverseSearch, 2, EFUNCCALL, EFUNCCALLP); + + if (cinline_funccallfound && ++counter > 0) { + inner = create_objectrefnode(create_temp_object(inner->rtype)); + copy = lalloc(sizeof(ENode)); + *copy = *inner; + + copy = makemonadicnode(copy, EINDIRECT); + copy->rtype = TPTR_TARGET(copy->rtype); + + inner = makemonadicnode(inner, EINDIRECT); + inner->rtype = TPTR_TARGET(inner->rtype); + + ass = makediadicnode(inner, copy, EASS); + list->node = copy; + + if (commanodes) + commanodes = makediadicnode(ass, commanodes, ECOMMA); + else + commanodes = ass; + } + + list = list->next; + } + + if (commanodes) { + commanodes = makediadicnode(commanodes, expr, ECOMMA); + commanodes->rtype = expr->rtype; + return commanodes; + } + + return expr; +} + +static void CInline_ExportCheck(ENode *expr) { + while (1) { + switch (expr->type) { + case EOBJREF: + CInline_ObjectAddrRef(expr->data.objref); + if (expr->data.objref->datatype == DALIAS) { + CExpr_AliasTransform(expr); + continue; + } + return; + + ENODE_CASE_MONADIC: + expr = expr->data.monadic; + continue; + + ENODE_CASE_DIADIC_ALL: + CInline_ExportCheck(expr->data.diadic.left); + expr = expr->data.diadic.right; + continue; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EPRECOMP: + case EINSTRUCTION: + case EVECTOR128CONST: + return; + + case ELABEL: + if (expr->data.label->stmt) + expr->data.label->stmt->flags |= StmtFlag_1; + return; + + case EFUNCCALL: + case EFUNCCALLP: { + ENodeList *list; + TypeClass *tclass; + SInt32 index; + + for (list = expr->data.funccall.args; list; list = list->next) + CInline_ExportCheck(list->node); + + expr = expr->data.funccall.funcref; + if ( + copts.warn_notinlined && + !copts.dont_inline && + ENODE_IS(expr, EOBJREF) && + (expr->data.objref->qual & Q_INLINE) && + expr->data.objref->datatype != DINLINEFUNC && + !CParser_IsVirtualFunction(expr->data.objref, &tclass, &index) + ) + CError_Warning(CErrorStr342, expr->data.objref); + + continue; + } + + case ENULLCHECK: + CInline_ExportCheck(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + continue; + + case EMFPOINTER: + *expr = *nullnode(); + continue; + + case ECOND: + CInline_ExportCheck(expr->data.cond.cond); + CInline_ExportCheck(expr->data.cond.expr1); + expr = expr->data.cond.expr2; + continue; + + case EMEMBER: + if (expr->data.emember->expr) { + *expr = *expr->data.emember->expr; + continue; + } + case EOBJLIST: + *expr = *nullnode(); + continue; + + default: + CError_FATAL(3372); + } + } +} + +static void CInline_Expand(Statement *stmt) { + Statement *scan; + + if (!copts.dont_inline && copts.inlinelevel >= 0) { + if (copts.inline_bottom_up) { + inline_max_size = copts.inline_max_size; + while (inline_max_size > 1 && EstimateExpandedSizeOfFunction(stmt) > copts.inline_max_total_size) + inline_max_size >>= 1; + } + + cinline_level = 0; + while (1) { + any_inline_expanded = 0; + for (scan = stmt; scan; scan = scan->next) { + switch (scan->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!scan->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + scan = CInline_ExpandStatement(scan); + break; + default: + CError_FATAL(3438); + } + } + + if (!copts.inline_bottom_up && !any_inline_expanded) + break; + + if (!copts.always_inline || copts.inline_bottom_up) { + if (copts.inlinelevel == 0) { + if (copts.inline_bottom_up) { + if ((cinline_level + 1) >= 8) + break; + } else { + if (cinline_level >= 3) + break; + } + } else { + if ((cinline_level + 1) >= copts.inlinelevel) + break; + } + } + + if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) + CError_UserBreak(); + + cinline_level++; + } + } + + while (stmt) { + if (stmt->dobjstack) + CExcept_CheckStackRefs(stmt->dobjstack); + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + CInline_ExportCheck(stmt->expr); + break; + default: + CError_FATAL(3501); + } + + stmt = stmt->next; + } +} + +SInt16 CInline_GetStatementNumber(Statement *first, Statement *stmt) { + SInt16 number = 0; + + while (first) { + if (first == stmt) + return number; + + first = first->next; + number++; + } + + CError_FATAL(3517); + return 0; +} + +static CI_Switch *CInline_PackSwitch(Statement *start, Statement *stmt) { + SwitchInfo *info; + SwitchCase *swcase; + short numcases; + CI_Switch *packed; + + info = (SwitchInfo *) stmt->label; + swcase = info->cases; + numcases = 0; + while (swcase) { + swcase = swcase->next; + numcases++; + } + + packed = galloc(sizeof(CI_Switch) + numcases * sizeof(CI_SwitchCase)); + packed->expr = CInline_CopyExpression(stmt->expr, CopyMode2); + packed->defaultlabelID = CInline_GetStatementNumber(start, info->defaultlabel->stmt); + packed->unkSwitch8 = info->x8; + packed->numcases = numcases; + + for (swcase = info->cases, numcases = 0; swcase; swcase = swcase->next, numcases++) { + packed->cases[numcases].labelID = CInline_GetStatementNumber(start, swcase->label->stmt); + packed->cases[numcases].min = swcase->min; + packed->cases[numcases].max = swcase->max; + } + + return packed; +} + +static UInt8 CInline_CanInline(Object *object, Statement *stmt) { + UInt8 resultClass; + FuncArg *arg; + UInt8 result; + + resultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); + if ( + resultClass && + (resultClass != 1 || (IS_TYPE_CLASS(TYPE_FUNC(object->type)->functype) && CClass_Destructor(TYPE_CLASS(TYPE_FUNC(object->type)->functype)))) + ) + return CI_CanInline0; + + for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { + if (arg == &elipsis) + return CI_CanInline0; + if (arg == &oldstyle) + break; + + if (IS_TYPE_CLASS(arg->type) && CClass_Destructor(TYPE_CLASS(arg->type))) + return CI_CanInline0; + } + + result = CI_CanInline6; + + while (stmt) { + if (stmt->dobjstack) + return CI_CanInline3; + + switch (stmt->type) { + case ST_EXPRESSION: + break; + case ST_RETURN: + if (stmt->next || (stmt->expr == NULL && TYPE_FUNC(object->type)->functype != &stvoid)) + result = CI_CanInline3; + break; + default: + result = CI_CanInline3; + } + + stmt = stmt->next; + } + + return result; +} + +static ExceptionAction *CInline_PackActions(Statement *start, Statement *stmt) { + ExceptionAction *exc; + ExceptionAction *last; + ExceptionAction *packexc; + + exc = stmt->dobjstack; + last = NULL; + + while (exc) { + packexc = galloc(sizeof(ExceptionAction)); + packexc->prev = last; + last = packexc; + + packexc->type = exc->type; + + switch (exc->type) { + case EAT_DESTROYLOCAL: + packexc->data.destroy_local.local = (void *) CInline_GetLocalID(exc->data.destroy_local.local); + packexc->data.destroy_local.dtor = exc->data.destroy_local.dtor; + break; + case EAT_DESTROYLOCALCOND: + packexc->data.destroy_local_cond.local = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.local); + packexc->data.destroy_local_cond.dtor = exc->data.destroy_local_cond.dtor; + packexc->data.destroy_local_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + packexc->data.destroy_local_offset.local = (void *) CInline_GetLocalID(exc->data.destroy_local_offset.local); + packexc->data.destroy_local_offset.dtor = exc->data.destroy_local_offset.dtor; + packexc->data.destroy_local_offset.offset = exc->data.destroy_local_offset.offset; + break; + case EAT_DESTROYLOCALPOINTER: + packexc->data.destroy_local_pointer.pointer = (void *) CInline_GetLocalID(exc->data.destroy_local_pointer.pointer); + packexc->data.destroy_local_pointer.dtor = exc->data.destroy_local_pointer.dtor; + break; + case EAT_DESTROYLOCALARRAY: + packexc->data.destroy_local_array.localarray = (void *) CInline_GetLocalID(exc->data.destroy_local_array.localarray); + packexc->data.destroy_local_array.dtor = exc->data.destroy_local_array.dtor; + packexc->data.destroy_local_array.elements = exc->data.destroy_local_array.elements; + packexc->data.destroy_local_array.element_size = exc->data.destroy_local_array.element_size; + break; + case EAT_DESTROYPARTIALARRAY: + packexc->data.destroy_partial_array.arraypointer = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraypointer); + packexc->data.destroy_partial_array.arraycounter = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraycounter); + packexc->data.destroy_partial_array.dtor = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.dtor); + packexc->data.destroy_partial_array.element_size = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + packexc->data.destroy_member.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member.objectptr); + packexc->data.destroy_member.dtor = exc->data.destroy_member.dtor; + packexc->data.destroy_member.offset = exc->data.destroy_member.offset; + break; + case EAT_DESTROYMEMBERCOND: + packexc->data.destroy_member_cond.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.objectptr); + packexc->data.destroy_member_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.cond); + packexc->data.destroy_member_cond.dtor = exc->data.destroy_member_cond.dtor; + packexc->data.destroy_member_cond.offset = exc->data.destroy_member_cond.offset; + break; + case EAT_DESTROYMEMBERARRAY: + packexc->data.destroy_member_array.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_array.objectptr); + packexc->data.destroy_member_array.dtor = exc->data.destroy_member_array.dtor; + packexc->data.destroy_member_array.offset = exc->data.destroy_member_array.offset; + packexc->data.destroy_member_array.elements = exc->data.destroy_member_array.elements; + packexc->data.destroy_member_array.element_size = exc->data.destroy_member_array.element_size; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + packexc->data.delete_pointer.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer.pointerobject); + packexc->data.delete_pointer.deletefunc = exc->data.delete_pointer.deletefunc; + break; + case EAT_DELETEPOINTERCOND: + packexc->data.delete_pointer_cond.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.pointerobject); + packexc->data.delete_pointer_cond.deletefunc = exc->data.delete_pointer_cond.deletefunc; + packexc->data.delete_pointer_cond.cond = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.cond); + break; + case EAT_CATCHBLOCK: + packexc->data.catch_block.catch_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_object); + packexc->data.catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_info_object); + packexc->data.catch_block.catch_label = (void *) CInline_GetStatementNumber(start->next, exc->data.catch_block.catch_label->stmt); + packexc->data.catch_block.catch_typeid = exc->data.catch_block.catch_typeid; + packexc->data.catch_block.catch_type = exc->data.catch_block.catch_type; + packexc->data.catch_block.catch_qual = exc->data.catch_block.catch_qual; + break; + case EAT_ACTIVECATCHBLOCK: + packexc->data.active_catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.active_catch_block.catch_info_object); + packexc->data.active_catch_block.call_dtor = exc->data.active_catch_block.call_dtor; + break; + case EAT_SPECIFICATION: + packexc->data.specification.unexp_ids = exc->data.specification.unexp_ids; + packexc->data.specification.unexp_id = exc->data.specification.unexp_id; + packexc->data.specification.unexp_label = (void *) CInline_GetStatementNumber(start->next, exc->data.specification.unexp_label->stmt); + packexc->data.specification.unexp_info_object = (void *) CInline_GetLocalID(exc->data.specification.unexp_info_object); + break; + case EAT_TERMINATE: + break; + default: + CError_FATAL(3720); + } + + exc = exc->prev; + } + + return last; +} + +void CInline_PackIFunctionData(CI_FuncData *funcdata, Statement *stmt, Object *object) { + ObjectList *list; + CI_Var *var; + Statement *scan; + CI_Statement *packstmt; + int i; + + cinline_first_stmt = stmt->next; + memclrw(funcdata, sizeof(CI_FuncData)); + + funcdata->can_inline = CInline_CanInline(object, stmt->next); + + if (copts.isGeneratingDebugInfo) { + funcdata->fileoffset = cparser_fileoffset; + funcdata->fileoffset.is_inline = 1; + funcdata->symdecloffset = symdecloffset; + funcdata->functionbodyoffset = functionbodyoffset; + funcdata->functionbodypath = functionbodypath; + funcdata->symdeclend = symdeclend; + } + + list = arguments; + i = 0; + while (list) { + list = list->next; + i++; + } + + if ((funcdata->numarguments = i) > 0) { + loc_args = funcdata->arguments = galloc(sizeof(CI_Var) * i); + memclrw(funcdata->arguments, sizeof(CI_Var) * i); + + for (list = arguments, var = funcdata->arguments; list; list = list->next, var++) { + var->name = list->object->name; + var->type = list->object->type; + var->qual = list->object->qual; + var->sflags = CInline_GetObjectSFlags(list->object); + var->xD = 0; + var->xE = 1; + } + } + + list = locals; + i = 0; + while (list) { + if (list->object->datatype == DLOCAL) + i++; + list = list->next; + } + + if ((funcdata->numlocals = i) > 0) { + loc_vars = funcdata->locals = galloc(sizeof(CI_Var) * i); + memclrw(funcdata->locals, sizeof(CI_Var) * i); + + for (list = locals, var = funcdata->locals; list; list = list->next) { + if (list->object->datatype == DLOCAL) { + var->name = list->object->name; + var->type = list->object->type; + var->qual = list->object->qual; + var->sflags = CInline_GetObjectSFlags(list->object); + var->xD = 0; + var->xE = 0; + var++; + } + } + } + + scan = stmt->next; + i = 0; + while (scan) { + scan = scan->next; + i++; + } + + funcdata->numstatements = i; + funcdata->statements = galloc(sizeof(CI_Statement) * i); + + for (scan = stmt->next, packstmt = funcdata->statements; scan; scan = scan->next, packstmt++) { + packstmt->type = scan->type; + packstmt->flags = scan->flags; + packstmt->value = scan->value; + packstmt->dobjstack = CInline_PackActions(stmt, scan); + packstmt->sourceoffset = scan->sourceoffset; + packstmt->sourcefilepath = scan->sourcefilepath; + + switch (scan->type) { + case ST_NOP: + case ST_LABEL: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); + break; + case ST_RETURN: + if (scan->expr) + packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); + else + packstmt->u.expr = NULL; + break; + case ST_GOTO: + packstmt->u.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + packstmt->u.ifgoto.expr = CInline_CopyExpression(scan->expr, CopyMode2); + packstmt->u.ifgoto.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); + break; + case ST_SWITCH: + packstmt->u.switchdata = CInline_PackSwitch(stmt->next, scan); + break; + case ST_ASM: + InlineAsm_PackAsmStatement(scan, stmt->next, &packstmt->u.asmdata.data, &packstmt->u.asmdata.size); + break; + default: + CError_FATAL(3862); + } + } +} + +void CInline_UnpackIFunctionData(Object *object, CI_FuncData *funcdata, Statement *firstStmt) { + CLabel **labels; + CI_Var *var; + ObjectList *last; + Statement *stmt; + CI_Statement *packstmt; + int i; + + cparser_fileoffset = funcdata->fileoffset; + symdecloffset = funcdata->symdecloffset; + functionbodyoffset = funcdata->functionbodyoffset; + functionbodypath = funcdata->functionbodypath; + symdeclend = funcdata->symdeclend; + + for (i = 0, var = funcdata->arguments; i < funcdata->numarguments; i++, var++) { + if (i == 0) { + last = lalloc(sizeof(ObjectList)); + arguments = last; + } else { + last->next = lalloc(sizeof(ObjectList)); + last = last->next; + } + + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + last->object = object; + last->next = NULL; + + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + object->name = var->name; + object->type = var->type; + object->qual = var->qual; + CInline_SetObjectSFlags(object, var->sflags); + CFunc_SetupLocalVarInfo(object); + + if (funcdata->fileoffset.file) { + object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; + object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; + } + } + + for (i = 0, var = funcdata->locals; i < funcdata->numlocals; i++, var++) { + if (i == 0) { + last = lalloc(sizeof(ObjectList)); + locals = last; + } else { + last->next = lalloc(sizeof(ObjectList)); + last = last->next; + } + + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + last->object = object; + last->next = NULL; + + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + object->name = var->name; + object->type = var->type; + object->qual = var->qual; + CInline_SetObjectSFlags(object, var->sflags); + CFunc_SetupLocalVarInfo(object); + + if (funcdata->fileoffset.file) { + object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; + object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; + } + } + + enode_idtrans = NULL; + cinline_label_trans = NULL; + + labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); + memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); + + for (i = 0, stmt = firstStmt, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + + stmt->type = packstmt->type; + stmt->flags = packstmt->flags; + stmt->value = packstmt->value; + stmt->sourceoffset = packstmt->sourceoffset; + stmt->sourcefilepath = packstmt->sourcefilepath; + stmt->dobjstack = CInline_UnpackActions(packstmt, 0); + stmt->next = NULL; + + switch (stmt->type) { + case ST_NOP: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); + break; + case ST_RETURN: + if (packstmt->u.expr) + stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); + else + stmt->expr = NULL; + break; + case ST_LABEL: + labels[i] = stmt->label = newlabel(); + stmt->label->stmt = stmt; + break; + case ST_IFGOTO: + case ST_IFNGOTO: + stmt->expr = CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode3); + break; + case ST_SWITCH: + stmt->expr = CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode3); + break; + default: + CError_FATAL(4017); + } + } + + for (stmt = firstStmt->next, packstmt = funcdata->statements; stmt; stmt = stmt->next, packstmt++) { + switch (stmt->type) { + case ST_GOTO: + CError_ASSERT(4024, stmt->label = labels[packstmt->u.statementnum]); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CError_ASSERT(4029, stmt->label = labels[packstmt->u.ifgoto.statementnum]); + break; + case ST_SWITCH: + CInline_UnpackSwitch(stmt, packstmt, labels); + break; + case ST_ASM: + InlineAsm_UnpackAsmStatement(stmt, labels, 0, packstmt->u.asmdata.data, packstmt->u.asmdata.size); + break; + } + } + + cinline_first_stmt = firstStmt->next; + + while (cinline_label_trans) { + CError_ASSERT(4045, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); + cinline_label_trans = cinline_label_trans->next; + } +} + +static void CInline_GenIFunctionCode(Object *object, CI_FuncData *func, UInt8 unk) { + Boolean saveDebugInfo; + CScopeSave saveScope; + Statement firstStmt; + + if (cparamblkptr->isPrecompiling != 1 && func) { + ObjGen_SetupSym(); + CScope_SetFunctionScope(object, &saveScope); + CFunc_FuncGenSetup(&firstStmt, object); + CInline_UnpackIFunctionData(object, func, &firstStmt); + + saveDebugInfo = copts.isGeneratingDebugInfo; + if (copts.nosyminline || (!symdecloffset && !symdeclend)) + copts.isGeneratingDebugInfo = 0; + + expanding_function = object; + recursive_inline = 0; + CInline_Expand(&firstStmt); + + if (!anyerrors) { + if (copts.isGeneratingDebugInfo) + CPrep_SetSourceFile(&cparser_fileoffset); + CodeGen_Generator(&firstStmt, object, unk, 0); + } + + CScope_RestoreScope(&saveScope); + copts.isGeneratingDebugInfo = saveDebugInfo; + } +} + +void CInline_AddDefaultFunctionAction(Object *object) { + CI_Action *action; + + for (action = cinline_actionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionDefaultFunc; + action->obj = object; + + action->next = cinline_actionlist; + cinline_actionlist = action; +} + +void CInline_AddInlineFunctionAction(Object *object, TypeClass *tclass, FileOffsetInfo *fileoffset, TStream *stream, Boolean flag) { + CI_Action *action; + + for (action = flag ? cinline_tactionlist : cinline_actionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + CError_ASSERT(4132, IS_TYPE_FUNC(object->type)); + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800000; + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionInlineFunc; + action->obj = object; + action->u.inlinefunc.tclass = tclass; + action->u.inlinefunc.fileoffset = *fileoffset; + action->u.inlinefunc.stream = *stream; + + if (flag) { + action->next = cinline_tactionlist; + cinline_tactionlist = action; + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; + } else { + action->next = cinline_actionlist; + cinline_actionlist = action; + } +} + +void CInline_AddMemberFunctionAction(Object *object, TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb) { + CI_Action *action; + + for (action = cinline_tactionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionMemberFunc; + action->obj = object; + action->u.memberfunc.templ = templ; + action->u.memberfunc.inst = inst; + action->u.memberfunc.tmemb = tmemb; + + action->next = cinline_tactionlist; + cinline_tactionlist = action; + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; +} + +void CInline_AddTemplateFunctionAction(Object *object, TemplateFunction *func, TemplFuncInstance *inst) { + CI_Action *action; + + for (action = cinline_tactionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionTemplateFunc; + action->obj = object; + action->u.templatefunc.func = func; + action->u.templatefunc.inst = inst; + + action->next = cinline_tactionlist; + cinline_tactionlist = action; + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; +} + +static void CInline_AddFRefList_Object(Object *object) { + ObjectList *list; + + if ( + !(object->datatype == DFUNC || object->datatype == DVFUNC) || + (object->flags & OBJECT_FLAGS_4) || + IS_TEMPL_FUNC(object->type) + ) + return; + + for (list = cinline_freflist; list; list = list->next) { + if (list->object == object) + return; + } + + list = lalloc(sizeof(ObjectList)); + list->object = object; + list->next = cinline_freflist; + cinline_freflist = list; + + if ((object->qual & Q_INLINE) && object->u.func.u.ifuncdata) + CInline_AddFRefList_InlineFunc(object->u.func.u.ifuncdata); +} + +static void CInline_AddFRefList_ExAction(ExceptionAction *exc) { + while (exc) { + switch (exc->type) { + case EAT_DESTROYLOCAL: + CInline_AddFRefList_Object(exc->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_partial_array.dtor); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_AddFRefList_Object(exc->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(4307); + } + exc = exc->prev; + } +} + +static void CInline_AddFRefList_ExprCB(ENode *expr) { + CInline_AddFRefList_Object(expr->data.objref); +} + +static void CInline_AddFRefList_Expr(ENode *expr) { + CExpr_SearchExprTree(expr, CInline_AddFRefList_ExprCB, 1, EOBJREF); +} + +static void CInline_AddFRefList_Statement(Statement *stmt) { + while (stmt) { + if (stmt->dobjstack) + CInline_AddFRefList_ExAction(stmt->dobjstack); + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + CInline_AddFRefList_Expr(stmt->expr); + break; + default: + CError_FATAL(4368); + } + + stmt = stmt->next; + } +} + +static void CInline_AddFRefList_InlineFunc(CI_FuncData *data) { + short i; + CI_Statement *stmt; + ExceptionAction *exc; + + for (i = 0; i < data->numstatements; i++) { + stmt = data->statements + i; + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + CInline_AddFRefList_Expr(stmt->u.expr); + break; + case ST_RETURN: + if (stmt->u.expr) + CInline_AddFRefList_Expr(stmt->u.expr); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CInline_AddFRefList_Expr(stmt->u.ifgoto.expr); + break; + case ST_SWITCH: + CInline_AddFRefList_Expr(stmt->u.switchdata->expr); + break; + default: + CError_FATAL(4420); + } + + for (exc = data->statements[i].dobjstack; exc; exc = exc->prev) { + switch (exc->type) { + case EAT_DESTROYLOCAL: + CInline_AddFRefList_Object(exc->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_AddFRefList_Object(exc->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(4470); + } + } + } +} + +static void CInline_GenerateTemplateInline(Object *object) { + CI_Action **ptr; + CI_Action *action; + + ptr = &cinline_tactionlist; + while ((action = *ptr)) { + if (object == action->obj) { + *ptr = action->next; + action->next = cinline_actionlist; + cinline_actionlist = action; + + TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_200000; + return; + } + + ptr = &action->next; + } + + CError_FATAL(4499); +} + +void CInline_ObjectAddrRef(Object *object) { + CI_FuncData *funcdata; + + object->flags |= OBJECT_FLAGS_2; + + switch (object->datatype) { + case DFUNC: + case DVFUNC: + if ( + (object->qual & Q_INLINE) && + (funcdata = object->u.func.u.ifuncdata) && + !(object->flags & OBJECT_FLAGS_4) && + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100000) + ) + { + CI_Export *export = galloc(sizeof(CI_Export)); + + export->object = object; + export->funcdata = funcdata; + export->xC = 0; + + export->next = cinline_exportlist; + cinline_exportlist = export; + + object->flags |= OBJECT_FLAGS_4; + return; + } + else if ( + (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100) && + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) + ) + { + CInline_AddDefaultFunctionAction(object); + return; + } + else if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) + { + CInline_GenerateTemplateInline(object); + return; + } + return; + + case DALIAS: + CInline_ObjectAddrRef(object->u.alias.object); + return; + + case DDATA: + if (object->qual & Q_10000) + CInit_ExportConst(object); + + if (object->flags & OBJECT_FLAGS_8) { + object->flags &= ~OBJECT_FLAGS_8; + CParser_CallBackAction(object); + } + return; + } +} + +static Boolean CInline_CheckDependencies(ObjectList *list) { + Object *object; + Boolean result; + + result = 0; + + while (list) { + object = list->object; + + if ( + (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100) && + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) + ) + { + CInline_AddDefaultFunctionAction(object); + result = 1; + } + else if ( + (object->qual & Q_400000) && + CTempl_InlineFunctionCheck(object) + ) + { + result = 1; + } + else { + CI_Action *action; + for (action = cinline_actionlist; action; action = action->next) { + if (object == action->obj) { + result = 1; + break; + } + } + + if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) { + CInline_GenerateTemplateInline(object); + result = 1; + } + } + + list = list->next; + } + + return result; +} + +static Boolean CInline_IsSmallFunction(Object *object, Statement *stmt) { + SInt32 statementCount; + ObjectList *list; + SInt32 localSize; + + statementCount = 0; + while (stmt) { + if (stmt->type != ST_NOP && stmt->type != ST_LABEL) + statementCount++; + if (statementCount > 15) + return 0; + stmt = stmt->next; + } + + for (list = locals, localSize = 0; list; list = list->next) + localSize += list->object->type->size; + + if (localSize > 1024) + return 0; + + return 1; +} + +static Boolean CInline_NoFPLocals(void) { + ObjectList *list; + + for (list = locals; list; list = list->next) { + if (IS_TYPE_FLOAT(list->object->type)) + return 0; + } + + return 1; +} + +void CInline_GenFunc(Statement *stmt, Object *object, UInt8 unk) { + CI_FuncData *funcdata; + CI_Export *export; + Boolean flag24; + Boolean flag30; + + TYPE_FUNC(object->type)->flags |= OBJECT_FLAGS_2; + + flag24 = 0; + flag30 = 0; + if (!(object->qual & Q_INLINE)) { + if ( + copts.autoinline && + !copts.dont_inline && + CInline_CanInline(object, stmt->next) && + CInline_IsSmallFunction(object, stmt->next) + ) + { + flag24 = 1; + flag30 = 1; + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800; + } + } else { + flag30 = 1; + } + + if (flag30) { + COpt_SimpleOptimizer(object, stmt); + + funcdata = galloc(sizeof(CI_FuncData)); + CInline_PackIFunctionData(funcdata, stmt, object); + + object->u.func.u.ifuncdata = funcdata; + + if (!flag24 && !(object->flags & OBJECT_FLAGS_2)) { + if (cinline_gendeps) { + cinline_freflist = NULL; + CInline_AddFRefList_Statement(stmt); + CInline_CheckDependencies(cinline_freflist); + } + return; + } + } + + object->flags |= OBJECT_FLAGS_4; + + cinline_freflist = NULL; + CInline_AddFRefList_Statement(stmt); + + if (CInline_CheckDependencies(cinline_freflist) || copts.defer_codegen) { + if (!flag30) { + funcdata = galloc(sizeof(CI_FuncData)); + CInline_PackIFunctionData(funcdata, stmt, object); + } else { + funcdata = object->u.func.u.ifuncdata; + } + + export = galloc(sizeof(CI_Export)); + export->object = object; + export->funcdata = funcdata; + export->xC = unk; + + export->next = cinline_exportlist; + cinline_exportlist = export; + + return; + } + + expanding_function = object; + recursive_inline = 0; + CInline_Expand(stmt); + + if (copts.isGeneratingDebugInfo) + CPrep_SetSourceFile(&cparser_fileoffset); + + if (!anyerrors) + CodeGen_Generator(stmt, object, unk, 0); +} + +static void CInline_GenerateDefaultFunc(Object *object) { + TypeClass *tclass; + + CError_ASSERT(4770, TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100); + CError_ASSERT(4771, TYPE_FUNC(object->type)->flags & FUNC_FLAGS_METHOD); + + tclass = TYPE_METHOD(object->type)->theclass; + + if (object == CClass_DefaultConstructor(tclass)) { + if (object->u.func.defargdata) + CABI_MakeDefaultArgConstructor(tclass, object); + else + CABI_MakeDefaultConstructor(tclass, object); + } else if (object == CClass_CopyConstructor(tclass)) { + CABI_MakeDefaultCopyConstructor(tclass, object); + } else if (object == CClass_AssignmentOperator(tclass)) { + CABI_MakeDefaultAssignmentOperator(tclass, object); + } else if (object == CClass_Destructor(tclass)) { + CABI_MakeDefaultDestructor(tclass, object); + } else { + CError_FATAL(4805); + } +} + +static TemplClassInst *CInline_FindNestedTemplInst(TypeClass *tclass) { + NameSpace *nspace; + + while (tclass) { + if ((tclass->flags & CLASS_FLAGS_800)) + return TEMPL_CLASS_INST(tclass); + + if (!copts.template_patch) + break; + + nspace = tclass->nspace->parent; + tclass = NULL; + while (nspace) { + if (nspace->theclass) { + tclass = nspace->theclass; + break; + } + nspace = nspace->parent; + } + } + + return NULL; +} + +static void CInline_GenerateInlineFunc(CI_Action *action) { + Object *object; + TemplClassInst *inst; + DeclInfo di; + SInt32 streamState; + + object = action->obj; + + CPrep_StreamInsert(&action->u.inlinefunc.stream, &streamState); + cparser_fileoffset = action->u.inlinefunc.fileoffset; + symdecloffset = cparser_fileoffset.tokenline; + + switch ((tk = lex())) { + case ':': + case '{': + case TK_TRY: + break; + default: + CError_FATAL(4860); + } + + symdecltoken = *CPrep_CurStreamElement(); + + TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_2; + if (IS_TYPE_METHOD(object->type) && (inst = CInline_FindNestedTemplInst(TYPE_METHOD(object->type)->theclass))) { + CTempl_ParseInstanceScopeFunction(object, inst, NULL); + } else { + memclrw(&di, sizeof(di)); + if (action->u.inlinefunc.tclass) { + if ((inst = CInline_FindNestedTemplInst(action->u.inlinefunc.tclass))) { + CTempl_ParseInstanceScopeFunction(object, inst, action->u.inlinefunc.tclass); + } else { + CFunc_ParseFuncDef(object, &di, action->u.inlinefunc.tclass, 0, 0, NULL); + } + } else { + CFunc_ParseFuncDef(object, &di, NULL, 0, 0, NULL); + } + } + + CPrep_StreamRemove(&action->u.inlinefunc.stream, &streamState); +} + +Boolean CInline_CanFreeLHeap(void) { + CI_Action *action; + + if (!anyerrors) { + for (action = cinline_actionlist; action; action = action->next) { + if (action->actiontype == CI_ActionInlineFunc) + return 0; + } + } + + return 1; +} + +Boolean CInline_GenerateDeferredFuncs(void) { + CI_Action *action; + CI_Export *export; + + if (!anyerrors) { + if ((action = cinline_actionlist)) { + cinline_actionlist = action->next; + cinline_gendeps = 1; + + switch (action->actiontype) { + case CI_ActionDefaultFunc: + CInline_GenerateDefaultFunc(action->obj); + break; + case CI_ActionInlineFunc: + if (!(action->obj->flags & OBJECT_FLAGS_4)) + CInline_GenerateInlineFunc(action); + break; + case CI_ActionMemberFunc: + if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_FLAGS_2)) + CTempl_InstantiateMember( + action->u.memberfunc.templ, action->u.memberfunc.inst, + action->u.memberfunc.tmemb, action->obj, 0); + break; + case CI_ActionTemplateFunc: + if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_FLAGS_2) && !action->u.templatefunc.inst->is_specialized) + CTempl_GenFuncInstance(action->u.templatefunc.func, action->u.templatefunc.inst, 0); + break; + default: + CError_FATAL(5001); + } + + cinline_gendeps = 0; + return 1; + } else { + if ((export = cinline_exportlist) && !copts.defer_codegen) { + cinline_exportlist = export->next; + CInline_GenIFunctionCode(export->object, export->funcdata, export->xC); + return 1; + } + } + } + + return 0; +} + +static InitExpr *CInline_InitTemplateData(InitExpr *init) { + Statement *stmt; + CLabel *label; + Object *object; + Object *data; + + object = init->object; + + data = CParser_NewCompilerDefDataObject(); + data->type = TYPE(&stsignedchar); + data->name = CParser_NameConcat("__init__", CMangler_GetLinkName(object)->name); + data->qual = Q_OVERLOAD; + CInit_DeclareData(data, NULL, NULL, data->type->size); + + stmt = CFunc_AppendStatement(ST_IFGOTO); + stmt->expr = create_objectnode(data); + label = newlabel(); + stmt->label = label; + + do { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); + init = init->next; + } while (init && init->object == object); + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode(data), intconstnode(TYPE(&stsignedchar), 1), EASS); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return init; +} + +void CInline_Finish(void) { + NameSpace *nspace; + Boolean saveDebugInfo; + Statement firstStmt; + Statement *stmt; + InitExpr *init; + Boolean doMore; + + if (!init_expressions || anyerrors) + return; + + cinline_freflist = NULL; + + for (init = init_expressions; init; init = init->next) + CInline_AddFRefList_Expr(init->expr); + + CInline_CheckDependencies(cinline_freflist); + + do { + doMore = CInline_GenerateDeferredFuncs(); + } while (doMore); + + nspace = CFunc_FuncGenSetup(&firstStmt, NULL); + saveDebugInfo = copts.isGeneratingDebugInfo; + copts.isGeneratingDebugInfo = 0; + + init = init_expressions; + while (init) { + if (init->object->nspace->theclass && (init->object->nspace->theclass->flags & CLASS_FLAGS_800)) { + init = CInline_InitTemplateData(init); + } else { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); + init = init->next; + } + } + + CFunc_CodeCleanup(&firstStmt); + + expanding_function = NULL; + recursive_inline = 0; + CInline_Expand(&firstStmt); + + if (!anyerrors) { + if (copts.isGeneratingDebugInfo) + CPrep_SetSourceFile(&cparser_fileoffset); + CodeGen_Generator(&firstStmt, NULL, 0, 1); + } + + cscope_current = nspace->parent; + copts.isGeneratingDebugInfo = saveDebugInfo; +} diff --git a/compiler_and_linker/unsorted/CMachine.c b/compiler_and_linker/unsorted/CMachine.c index 0c1ac0d..2b1440f 100644 --- a/compiler_and_linker/unsorted/CMachine.c +++ b/compiler_and_linker/unsorted/CMachine.c @@ -1,6 +1,11 @@ -#include "compiler.h" +#include "compiler/CMachine.h" +#include "compiler/CClass.h" #include "compiler/CError.h" #include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CompilerTools.h" #include "compiler/objects.h" #include "compiler/types.h" @@ -157,10 +162,8 @@ SInt32 CMach_GetQUALalign(UInt32 qual) { result = 4096; else if (chk == Q_ALIGNED_8192) result = 8192; - else { -#line 226 - CError_FATAL(); - } + else + CError_FATAL(226); } return result; @@ -240,8 +243,7 @@ CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right) { case 8: break; default: -#line 327 - CError_FATAL(); + CError_FATAL(327); } switch (op) { @@ -339,8 +341,7 @@ CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right) { case 8: break; default: -#line 389 - CError_FATAL(); + CError_FATAL(389); } switch (op) { @@ -441,8 +442,7 @@ CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val) { case 8: break; default: -#line 448 - CError_FATAL(); + CError_FATAL(448); } switch (op) { @@ -486,8 +486,7 @@ CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val) { case 8: break; default: -#line 478 - CError_FATAL(); + CError_FATAL(478); } switch (op) { @@ -549,28 +548,26 @@ void CMach_InitIntMem(Type *type, CInt64 val, void *mem) { case TYPEINT: switch (type->size) { case 1: - ch = (UInt8) val.lo; + ch = (UInt8) CInt64_GetULong(&val); memcpy(mem, &ch, 1); break; case 2: - sh = (UInt16) val.lo; + sh = (UInt16) CTool_EndianConvertWord16(CInt64_GetULong(&val)); memcpy(mem, &sh, 2); break; case 4: - lg = (UInt32) val.lo; + lg = (UInt32) CTool_EndianConvertWord32(CInt64_GetULong(&val)); memcpy(mem, &lg, 4); break; case 8: CTool_EndianConvertWord64(val, mem); break; default: -#line 566 - CError_FATAL(); + CError_FATAL(566); } break; default: -#line 570 - CError_FATAL(); + CError_FATAL(570); } } @@ -612,13 +609,11 @@ void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) { memcpy(mem, f, 16); break; default: -#line 655 - CError_FATAL(); + CError_FATAL(655); } break; default: -#line 659 - CError_FATAL(); + CError_FATAL(659); } } @@ -637,8 +632,7 @@ Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right) { left.value /= right.value; break; default: -#line 679 - CError_FATAL(); + CError_FATAL(679); } return CMach_CalcFloatConvert(type, left); @@ -646,8 +640,7 @@ Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right) { Float CMach_CalcFloatMonadic(Type *type, short op, Float fval) { if (op != '-') -#line 692 - CError_FATAL(); + CError_FATAL(692); fval.value = -fval.value; return CMach_CalcFloatConvert(type, fval); @@ -668,8 +661,7 @@ Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right) case '<': return left.value < right.value; default: -#line 714 - CError_FATAL(); + CError_FATAL(714); return 0; } } @@ -681,8 +673,7 @@ Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVe case TK_LOGICAL_NE: return (left->ul[0] != right->ul[0]) && (left->ul[1] != right->ul[1]) && (left->ul[2] != right->ul[2]) && (left->ul[3] != right->ul[3]); default: -#line 740 - CError_FATAL(); + CError_FATAL(740); return 0; } } @@ -732,8 +723,7 @@ Float CMach_CalcFloatConvert(Type *type, Float fval) { case 12: break; default: -#line 801 - CError_FATAL(); + CError_FATAL(801); } return fval; } @@ -759,16 +749,17 @@ void CMach_InitFloatMem(Type *type, Float val, void *mem) { case 4: f = val.value; memcpy(mem, &f, 4); + CTool_EndianConvertMem(mem, 4); return; case 8: d = val.value; memcpy(mem, &d, 8); + CTool_EndianConvertMem(mem, 8); return; } } -#line 866 - CError_FATAL(); + CError_FATAL(866); } void CMach_PrintFloat(char *buf, Float val) { @@ -870,8 +861,7 @@ static SInt16 CMach_GetQualifiedStructAlign(TypeStruct *tstruct, Boolean flag) { best = 1; switch (copts.align_mode) { default: -#line 1026 - CError_FATAL(); + CError_FATAL(1026); case AlignMode4_2Byte: case AlignMode5_4Byte: case AlignMode6_8Byte: @@ -954,8 +944,7 @@ static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) { best = 1; switch (copts.align_mode) { default: -#line 1149 - CError_FATAL(); + CError_FATAL(1149); case AlignMode4_2Byte: case AlignMode5_4Byte: case AlignMode6_8Byte: @@ -1092,8 +1081,7 @@ restart: return 8; return 4; default: -#line 1346 - CError_FATAL(); + CError_FATAL(1346); } case TYPEMEMBERPOINTER: case TYPEPOINTER: @@ -1146,8 +1134,7 @@ restart: case TYPETEMPLATE: return 1; default: -#line 1392 - CError_FATAL(); + CError_FATAL(1392); return 0; } } @@ -1261,8 +1248,7 @@ SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) { basesize_bits = 32; break; default: -#line 1620 - CError_FATAL(); + CError_FATAL(1620); } switch (copts.align_mode) { diff --git a/compiler_and_linker/unsorted/CMangler.c b/compiler_and_linker/unsorted/CMangler.c index 569871e..e3e3c3e 100644 --- a/compiler_and_linker/unsorted/CMangler.c +++ b/compiler_and_linker/unsorted/CMangler.c @@ -1,6 +1,10 @@ -#include "compiler.h" +#include "compiler/CMangler.h" #include "compiler/CError.h" #include "compiler/CInt64.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" #include "compiler/enode.h" #include "compiler/objects.h" #include "compiler/scopes.h" @@ -197,8 +201,7 @@ static void CMangler_CheckTemplateArguments(TemplArg *arg) { while (arg) { if (arg->pid.type == TPT_NONTYPE) { expr = arg->data.paramdecl.expr; -#line 360 - CError_ASSERT(expr); + CError_ASSERT(360, expr); if (expr->rtype->type != TYPETEMPLDEPEXPR) { switch (expr->type) { case EINTCONST: @@ -207,8 +210,7 @@ static void CMangler_CheckTemplateArguments(TemplArg *arg) { CMangler_GetLinkName(expr->data.objref); break; default: -#line 383 - CError_FATAL(); + CError_FATAL(383); } } } @@ -225,8 +227,7 @@ static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { while (arg) { if (arg->pid.type == TPT_NONTYPE) { expr = arg->data.paramdecl.expr; -#line 409 - CError_ASSERT(expr); + CError_ASSERT(409, expr); if (expr->rtype->type != TYPETEMPLDEPEXPR) { switch (expr->type) { case EINTCONST: @@ -238,8 +239,7 @@ static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name); break; default: -#line 452 - CError_FATAL(); + CError_FATAL(452); } } else { AppendGListByte(&name_mangle_list, 'T'); @@ -247,8 +247,7 @@ static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { } 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); + CError_ASSERT(467, arg->pid.type == TPT_TEMPLATE); CMangler_MangleTypeAppend(arg->data.ttargtype, 0); } @@ -385,8 +384,7 @@ static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { AppendGListByte(&name_mangle_list, 'r'); return; default: -#line 619 - CError_FATAL(); + CError_FATAL(619); } case TYPEENUM: CMangler_MangleQualifier(qual); @@ -485,8 +483,7 @@ static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { AppendGListName(&name_mangle_list, "class"); break; default: -#line 701 - CError_FATAL(); + CError_FATAL(701); } break; @@ -500,8 +497,7 @@ static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { break; default: -#line 716 - CError_FATAL(); + CError_FATAL(716); } } @@ -712,8 +708,7 @@ HashNameNode *CMangler_GetLinkName(Object *obj) { obj->u.toc.linkname = CMangler_DataLinkName(obj); return obj->u.toc.linkname; default: -#line 1110 - CError_FATAL(); + CError_FATAL(1110); return NULL; } } diff --git a/compiler_and_linker/unsorted/CObjC.c b/compiler_and_linker/unsorted/CObjC.c index e69de29..7685a33 100644 --- a/compiler_and_linker/unsorted/CObjC.c +++ b/compiler_and_linker/unsorted/CObjC.c @@ -0,0 +1,3102 @@ +#include "compiler/CObjC.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "cos.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ObjCString { + struct ObjCString *next; + Object *object; + char *str; + Section section; +} ObjCString; + +typedef struct ObjCCategoryEntry { + struct ObjCCategoryEntry *next; + ObjCCategory *category; + Object *object; +} ObjCCategoryEntry; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +Type *cobjc_type_class; +Type *cobjc_type_id; +Type *cobjc_type_sel; +TypeClass *cobjc_currentclass; +ObjCSelector **cobjc_selhashtable; +BClassList *cobjc_classdefs; +ObjCProtocol *cobjc_protocols; +long cobjc_selrefcount; +long cobjc_classrefcount; +long cobjc_stringcount; +Boolean cobjc_encodemethod; +static ObjCCategoryEntry *cobjc_categories; +static ObjCString *cobjc_strings; + +// forward decls +static void CObjC_EncodeType(Type *type, UInt32 qual, Boolean flag); +static Object *CObjC_GetProtocolObject(ObjCProtocol *protocol); + +void CObjC_Setup(void) { + cobjc_type_class = NULL; + cobjc_type_id = NULL; + cobjc_type_sel = NULL; + cobjc_currentclass = NULL; + cobjc_selhashtable = NULL; + cobjc_strings = NULL; + cobjc_classdefs = NULL; + cobjc_protocols = NULL; + cobjc_categories = NULL; + + cobjc_selrefcount = 0; + cobjc_classrefcount = 0; + cobjc_stringcount = 0; + + cobjc_encodemethod = 0; +} + +void CObjC_Cleanup(void) { +} + +static HashNameNode *CObjC_GetSelfName(void) { + return self_name_node; +} + +static char *CObjC_StringConcat(char *a, char *b, char *c) { + char *buf; + int len; + + len = 1; + if (a) + len += strlen(a); + if (b) + len += strlen(b); + if (c) + len += strlen(c); + + buf = galloc(len); + len = 0; + + if (a) { + strcpy(&buf[len], a); + len += strlen(a); + } + if (b) { + strcpy(&buf[len], b); + len += strlen(b); + } + if (c) { + strcpy(&buf[len], c); + len += strlen(c); + } + buf[len] = 0; + return buf; +} + +static Object *CObjC_SectionString(char *str, Section section) { + ObjCString *objcstr; + Object *object; + + for (objcstr = cobjc_strings; objcstr; objcstr = objcstr->next) { + if (objcstr->section == section && !strcmp(str, objcstr->str)) + return objcstr->object; + } + + object = CParser_NewCompilerDefDataObject(); + object->nspace = cscope_root; + object->name = CParser_GetUniqueName(); + object->type = CDecl_NewArrayType(TYPE(&stchar), strlen(str) + 1); + object->sclass = TK_STATIC; + object->section = section; + + CInit_DeclareData(object, str, NULL, object->type->size); + + objcstr = galloc(sizeof(ObjCString)); + objcstr->next = cobjc_strings; + cobjc_strings = objcstr; + + objcstr->str = str; + objcstr->section = section; + objcstr->object = object; + + return objcstr->object; +} + +static ObjCProtocol *CObjC_FindProtocol(HashNameNode *name) { + ObjCProtocol *prot; + + for (prot = cobjc_protocols; prot; prot = prot->next) { + if (prot->name == name) + break; + } + + return prot; +} + +static ObjCSelector *CObjC_FindSelector(HashNameNode *name) { + ObjCSelector *sel; + + if (!cobjc_selhashtable) + return NULL; + + for (sel = cobjc_selhashtable[name->hashval & 0x3FF]; sel; sel = sel->next) { + if (sel->name == name) + break; + } + + return sel; +} + +static ObjCSelector *CObjC_NewSelector(HashNameNode *name) { + ObjCSelector *sel; + ObjCSelector **ptr; + + if (!cobjc_selhashtable) { + cobjc_selhashtable = galloc(sizeof(ObjCSelector *) * 0x400); + memclrw(cobjc_selhashtable, sizeof(ObjCSelector *) * 0x400); + } + + sel = galloc(sizeof(ObjCSelector)); + sel->selobject = NULL; + sel->name = name; + sel->methods = NULL; + ptr = cobjc_selhashtable + (name->hashval & 0x3FF); + sel->next = *ptr; + *ptr = sel; + return sel; +} + +static ObjCSelector *CObjC_FindKeyArgSelector(ObjCNamedArg *arg) { + HashNameNode *name; + + if (!arg->next && !arg->expr) { + name = arg->name; + } else { + name_mangle_list.size = 0; + while (arg) { + if (arg->name) + AppendGListName(&name_mangle_list, arg->name->name); + AppendGListByte(&name_mangle_list, ':'); + arg = arg->next; + } + + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + } + + return CObjC_FindSelector(name); +} + +static Boolean CObjC_IsSameType(Type *a, Type *b) { + if (!copts.objc_strict && CObjC_IsCompatibleType(a, b)) + return 1; + + return is_typesame(a, b); +} + +static Boolean CObjC_IsSameMethod(ObjCMethod *a, ObjCMethod *b) { + ObjCMethodArg *argA; + ObjCMethodArg *argB; + + if ( + CObjC_IsSameType(a->return_type, b->return_type) && + a->return_qual == b->return_qual && + a->has_valist == b->has_valist + ) + { + argA = a->selector_args; + argB = b->selector_args; + + while (1) { + if (!argA) + return !argB; + if (!argB) + return 0; + + if (argA->selector != argB->selector || argA->qual != argB->qual) + return 0; + + if (argA->type) { + // bug? + if (!argB->type || !CObjC_IsSameType(argB->type, argB->type)) + return 0; + } else { + if (argB->type) + return 0; + } + + argA = argA->next; + argB = argB->next; + } + } + + return 0; +} + +static ObjCSelector *CObjC_MakeSelector(ObjCMethod *meth) { + ObjCMethodList *methlist; + HashNameNode *selname; + ObjCSelector *sel; + ObjCMethodArg *arg; + + if (!meth->selector_args->next && !meth->selector_args->type) { + selname = meth->selector_args->selector; + } else { + name_mangle_list.size = 0; + for (arg = meth->selector_args; arg; arg = arg->next) { + if (arg->selector) + AppendGListName(&name_mangle_list, arg->selector->name); + AppendGListByte(&name_mangle_list, ':'); + } + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + selname = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + } + + sel = CObjC_FindSelector(selname); + if (!sel) { + methlist = galloc(sizeof(ObjCMethodList)); + methlist->next = NULL; + methlist->method = meth; + + sel = CObjC_NewSelector(selname); + sel->methods = methlist; + } else { + for (methlist = sel->methods; methlist; methlist = methlist->next) { + if (CObjC_IsSameMethod(methlist->method, meth)) + break; + } + + if (!methlist) { + methlist = galloc(sizeof(ObjCMethodList)); + methlist->method = meth; + methlist->next = sel->methods; + sel->methods = methlist; + } + } + + meth->selector = sel; + return sel; +} + +static Object *CObjC_GetSelectorObject(ObjCSelector *sel) { + Object *nameobj; + Object *dataobj; + + char str[32]; + OLinkList refs; + char buf[8]; + + if (!sel->selobject) { + nameobj = CObjC_SectionString(sel->name->name, SECT_OBJC_METH_VAR_NAMES); + sprintf(str, "L_OBJC_SELECTOR_REFERENCES_%ld", cobjc_selrefcount++); + + dataobj = CParser_NewCompilerDefDataObject(); + dataobj->name = GetHashNameNodeExport(str); + dataobj->sclass = TK_STATIC; + dataobj->type = TYPE(&void_ptr); + dataobj->section = SECT_OBJC_MESSAGE_REFS; + + if (CScope_GetLocalObject(cscope_root, dataobj->name)) + CError_Error(CErrorStr333, dataobj); + else + CScope_AddGlobalObject(dataobj); + + sel->selobject = dataobj; + + memclrw(buf, dataobj->type->size); + refs.next = NULL; + refs.obj = nameobj; + refs.offset = 0; + refs.somevalue = 0; + CInit_DeclareData(dataobj, buf, &refs, dataobj->type->size); + } + + return sel->selobject; +} + +static Object *CObjC_GetClassRefObject(TypeClass *tclass) { + Object *nameobj; + Object *dataobj; + + char str[32]; + OLinkList refs; + char buf[8]; + + if (!tclass->objcinfo->classrefobj) { + nameobj = CObjC_SectionString(tclass->classname->name, SECT_OBJC_CLASS_NAMES); + sprintf(str, "L_OBJC_CLASS_REFERENCES_%ld", cobjc_classrefcount++); + + dataobj = CParser_NewCompilerDefDataObject(); + dataobj->name = GetHashNameNodeExport(str); + dataobj->sclass = TK_STATIC; + dataobj->type = TYPE(&void_ptr); + dataobj->section = SECT_OBJC_CLS_REFS; + + if (CScope_GetLocalObject(cscope_root, dataobj->name)) + CError_Error(CErrorStr333, dataobj); + else + CScope_AddGlobalObject(dataobj); + + tclass->objcinfo->classrefobj = dataobj; + + memclrw(buf, dataobj->type->size); + refs.next = NULL; + refs.obj = nameobj; + refs.offset = 0; + refs.somevalue = 0; + CInit_DeclareData(dataobj, buf, &refs, dataobj->type->size); + } + + return tclass->objcinfo->classrefobj; +} + +static Object *CObjC_MakeObject(char *name1, char *name2, SInt32 size) { + Object *object = CParser_NewCompilerDefDataObject(); + object->name = CParser_NameConcat(name1, name2); + object->type = CDecl_NewStructType(size, 4); + CScope_AddObject(object->nspace, object->name, OBJ_BASE(object)); + return object; +} + +static Object *CObjC_FindRTFunc(char *namestr, char *namestr2) { + NameSpaceObjectList *list; + Object *object; + HashNameNode *name; + NameSpace *saveNSpace; + Boolean savecpp; + + savecpp = copts.cplusplus; + name = GetHashNameNodeExport(namestr); + + if ((list = CScope_GetLocalObject(cscope_root, name))) { + if (IS_TYPE_FUNC(OBJECT(list->object)->type)) + return OBJECT(list->object); + + CError_Error(CErrorStr122, name); + } + + copts.cplusplus = 0; + + saveNSpace = cscope_current; + cscope_current = cscope_root; + object = CParser_NewFunctionObject(NULL); + cscope_current = saveNSpace; + + object->type = TYPE(&rt_func); + object->name = name; + if (!list) + CScope_AddObject(cscope_root, name, OBJ_BASE(object)); + + copts.cplusplus = savecpp; + + return object; +} + +static Object *CObjC_FindSendMessageRTFunc(Boolean flag1, Boolean flag2) { + if (flag1) { + if (flag2) + return CObjC_FindRTFunc("objc_msgSendSuper_stret", "_objc_msgSendSuper_stret"); + else + return CObjC_FindRTFunc("objc_msgSendSuper", "_objc_msgSendSuper"); + } else { + if (flag2) + return CObjC_FindRTFunc("objc_msgSend_stret", "_objc_msgSend_stret"); + else + return CObjC_FindRTFunc("objc_msgSend", "_objc_msgSend"); + } +} + +typedef struct RawSymbols { + UInt32 x0; + UInt32 x4; + UInt16 x8; + UInt16 xA; + UInt32 offsets[1]; +} RawSymbols; + +void CObjC_GenerateModule(void) { + int i; + RawSymbols *symdata; + SInt32 size; + Object *object; + OLinkList *refs; + OLinkList *ref; + int classCount; + int categoryCount; + ObjCCategoryEntry *catEntry; + BClassList *classdef; + UInt32 data[4]; + + if (copts.objective_c || cobjc_classdefs) { + for (classdef = cobjc_classdefs, classCount = 0; classdef; classdef = classdef->next) + classCount++; + for (catEntry = cobjc_categories, categoryCount = 0; catEntry; catEntry = catEntry->next) + categoryCount++; + + size = sizeof(RawSymbols) + 4 * (classCount + categoryCount - 1); + symdata = lalloc(size); + memclrw(symdata, size); + + symdata->x0 = CTool_EndianConvertWord32(0); + symdata->x4 = CTool_EndianConvertWord32(0); + symdata->x0 = CTool_EndianConvertWord16(0); + symdata->x8 = CTool_EndianConvertWord16(classCount); + symdata->xA = CTool_EndianConvertWord16(categoryCount); + + refs = NULL; + i = 0; + for (classdef = cobjc_classdefs; classdef; classdef = classdef->next) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = TYPE_CLASS(classdef->type)->objcinfo->classobject; + ref->offset = ((char *) &symdata->offsets[i]) - ((char *) symdata); + ref->somevalue = 0; + i++; + } + for (catEntry = cobjc_categories; catEntry; catEntry = catEntry->next) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = catEntry->object; + ref->offset = ((char *) &symdata->offsets[i]) - ((char *) symdata); + ref->somevalue = 0; + i++; + } + + object = CObjC_MakeObject("", "L_OBJC_SYMBOLS", size); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_MSYMBOLS; + CInit_DeclareData(object, symdata, refs, object->type->size); + + refs = NULL; + + data[0] = CTool_EndianConvertWord32(5); + data[1] = CTool_EndianConvertWord32(16); + data[2] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(CPrep_GetFileName(NULL, 1, 0), SECT_OBJC_CLASS_NAMES); + ref->offset = 8; + ref->somevalue = 0; + + data[3] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 12; + ref->somevalue = 0; + + object = CObjC_MakeObject("", "L_OBJC_MODULES", 16); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_MODULE_INFO; + CInit_DeclareData(object, data, refs, object->type->size); + } +} + +static TypeClass *CObjC_FindObjCClass(HashNameNode *name, Boolean flag) { + NameSpaceObjectList *list; + + list = CScope_FindName(cscope_root, name); + if ( + !list || + list->object->otype != OT_TYPE || + !IS_TYPE_CLASS(OBJ_TYPE(list->object)->type) || + !TYPE_CLASS(OBJ_TYPE(list->object)->type)->objcinfo + ) + { + if (list || flag) + CError_Error(CErrorStr292, name->name); + return NULL; + } else { + return TYPE_CLASS(OBJ_TYPE(list->object)->type); + } +} + +static Type *CObjC_FindObjCType(char *namestr, Boolean flag) { + NameSpaceObjectList *list; + + list = CScope_FindName(cscope_root, GetHashNameNodeExport(namestr)); + if (list && list->object->otype == OT_TYPE) { + if (IS_TYPE_POINTER_ONLY(OBJ_TYPE(list->object)->type)) + return OBJ_TYPE(list->object)->type; + CError_Error(CErrorStr298, namestr); + } else { + if (flag) + CError_Error(CErrorStr297, namestr); + } + + return NULL; +} + +static Type *CObjC_GetObjCType_Class(Boolean flag) { + Type *type; + + if (cobjc_type_class) + return cobjc_type_class; + + type = CObjC_FindObjCType("Class", flag); + if (!type) + return TYPE(&void_ptr); + + cobjc_type_class = type; + return type; +} + +Type *CObjC_GetObjCType_id(Boolean flag) { + Type *type; + + if (cobjc_type_class) + return cobjc_type_id; + + type = CObjC_FindObjCType("id", flag); + if (!type) + return TYPE(&void_ptr); + + cobjc_type_id = type; + return type; +} + +Boolean CObjC_IsType_id(Type *type) { + if (IS_TYPE_POINTER_ONLY(type)) { + if (type == TYPE(&void_ptr)) + return 0; + + type = TPTR_TARGET(type); + if (type == TPTR_TARGET(CObjC_GetObjCType_id(0))) + return 1; + if (type == TPTR_TARGET(CObjC_GetObjCType_Class(0))) + return 1; + } + + return 0; +} + +Boolean CObjC_IsCompatibleType(Type *a, Type *b) { + Boolean a_is_id; + Boolean b_is_id; + + if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) { + a_is_id = CObjC_IsType_id(a); + b_is_id = CObjC_IsType_id(b); + + if (a_is_id && b_is_id) + return 1; + + if (a_is_id && IS_TYPE_OBJC_CLASS(TPTR_TARGET(b))) + return 1; + + if (b_is_id && IS_TYPE_OBJC_CLASS(TPTR_TARGET(a))) + return 1; + } + + return 0; +} + +static Type *CObjC_FindObjCType_SEL(void) { + Type *type; + + if (cobjc_type_sel) + return cobjc_type_sel; + + type = CObjC_FindObjCType("SEL", 1); + if (!type) + return TYPE(&void_ptr); + + cobjc_type_sel = type; + return type; +} + +static Boolean CObjC_IsType_SEL(Type *type) { + Type *sel; + + if (!IS_TYPE_POINTER_ONLY(type)) + return 0; + + type = TPTR_TARGET(type); + + sel = CObjC_FindObjCType_SEL(); + + CError_ASSERT(847, IS_TYPE_POINTER_ONLY(sel)); + return type == TPTR_TARGET(sel); +} + +static TypeClass *CObjC_NewObjCClass(HashNameNode *name) { + NameSpaceObjectList *list; + ObjCInfo *info; + TypeClass *tclass; + + if ((list = CScope_FindName(cscope_root, name))) { + if ( + list->object->otype != OT_TYPE || + !IS_TYPE_CLASS(tclass = TYPE_CLASS(OBJ_TYPE(list->object)->type)) || + !tclass->objcinfo + ) + { + CError_Error(CErrorStr122, name->name); + return NULL; + } + + return tclass; + } + + info = galloc(sizeof(ObjCInfo)); + memclrw(info, sizeof(ObjCInfo)); + + tclass = CDecl_DefineClass(cscope_root, name, NULL, CLASS_MODE_2, 1, 1); + tclass->flags |= CLASS_FLAGS_10; + tclass->objcinfo = info; + + info->classobject = CObjC_MakeObject("L_OBJC_CLASS_", name->name, 40); + info->classobject->sclass = TK_STATIC; + info->classobject->section = SECT_OBJC_CLASS; + + info->metaobject = CObjC_MakeObject("L_OBJC_METACLASS_", name->name, 40); + info->metaobject->sclass = TK_STATIC; + info->metaobject->section = SECT_OBJC_META_CLASS; + + return tclass; +} + +static void CObjC_ParseTypeName(Type **type, UInt32 *qual) { + DeclInfo di; + + tk = lex(); + + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + scandeclarator(&di); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + if (di.name) + CError_Error(CErrorStr121); + + *type = di.x4A ? CObjC_GetObjCType_id(1) : di.thetype; + *qual = di.qual; +} + +void CObjC_TranslateSelectorToken(void) { + switch (tk) { + case TK_CLASS: + tkidentifier = GetHashNameNodeExport("class"); + tk = TK_IDENTIFIER; + break; + case TK_SELF: + tkidentifier = GetHashNameNodeExport("self"); + tk = TK_IDENTIFIER; + break; + case TK_IN: + tkidentifier = GetHashNameNodeExport("in"); + tk = TK_IDENTIFIER; + break; + case TK_BREAK: + tkidentifier = GetHashNameNodeExport("break"); + tk = TK_IDENTIFIER; + break; + case TK_NEW: + tkidentifier = GetHashNameNodeExport("new"); + tk = TK_IDENTIFIER; + break; + case TK_DELETE: + tkidentifier = GetHashNameNodeExport("delete"); + tk = TK_IDENTIFIER; + break; + } +} + +static ObjCMethod *CObjC_ParseMethod(Boolean is_global) { + ObjCMethod *meth; + ObjCMethodArg *arg; + ObjCMethodArg **ptr; + Boolean argflag; + + if (is_global) { + meth = galloc(sizeof(ObjCMethod)); + memclrw(meth, sizeof(ObjCMethod)); + } else { + meth = lalloc(sizeof(ObjCMethod)); + memclrw(meth, sizeof(ObjCMethod)); + } + + switch (tk) { + case '+': + meth->is_class_method = 1; + break; + case '-': + meth->is_class_method = 0; + break; + default: + CError_FATAL(976); + } + + if ((tk = lex()) == '(') { + CObjC_ParseTypeName(&meth->return_type, &meth->return_qual); + CError_QualifierCheck(meth->return_qual & ~(Q_CONST | Q_VOLATILE | Q_BYCOPY | Q_BYREF | Q_ONEWAY)); + } else { + meth->return_type = CObjC_GetObjCType_id(1); + } + + ptr = &meth->selector_args; + argflag = 1; + while (1) { + if (is_global) { + arg = galloc(sizeof(ObjCMethodArg)); + memclrw(arg, sizeof(ObjCMethodArg)); + } else { + arg = lalloc(sizeof(ObjCMethodArg)); + memclrw(arg, sizeof(ObjCMethodArg)); + } + + *ptr = arg; + ptr = &arg->next; + + CObjC_TranslateSelectorToken(); + + if (tk == TK_IDENTIFIER) { + arg->selector = tkidentifier; + if ((tk = lex()) != ':') { + if (argflag) + break; + + CError_Error(CErrorStr170); + return NULL; + } + } + + if (tk != ':') { + CError_Error(CErrorStr170); + return NULL; + } + + if ((tk = lex()) == '(') { + CObjC_ParseTypeName(&arg->type, &arg->qual); + + if (IS_TYPE_ARRAY(arg->type)) + arg->type = CDecl_NewPointerType(TPTR_TARGET(arg->type)); + + CError_QualifierCheck(arg->qual & ~(Q_CONST | Q_VOLATILE | Q_IN | Q_OUT | Q_INOUT | Q_BYCOPY | Q_BYREF)); + if ((arg->qual & (Q_OUT | Q_INOUT)) && !IS_TYPE_POINTER_ONLY(arg->type)) + CError_QualifierCheck(arg->qual & (Q_OUT | Q_INOUT)); + } else { + arg->type = CObjC_GetObjCType_id(1); + } + + if (tk != TK_IDENTIFIER) { + CObjC_TranslateSelectorToken(); + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + tkidentifier = no_name_node; + } + } + + arg->name = tkidentifier; + + if ((tk = lex()) == ',') { + if ((tk = lex()) == TK_ELLIPSIS) { + meth->has_valist = 1; + tk = lex(); + break; + } + + CError_Error(CErrorStr121); + } + + CObjC_TranslateSelectorToken(); + if (tk != ':' && tk != TK_IDENTIFIER) + break; + + argflag = 0; + } + + return meth; +} + +static ObjCMethod *CObjC_FindMethod(ObjCMethod *methods, ObjCMethod *wanted, Boolean flag1, Boolean flag2) { + ObjCMethod *meth; + ObjCMethodArg *wanted_arg; + ObjCMethodArg *meth_arg; + + for (meth = methods; meth; meth = meth->next) { + if (wanted->is_class_method == meth->is_class_method) { + wanted_arg = wanted->selector_args; + meth_arg = meth->selector_args; + while (1) { + if (!wanted_arg || !meth_arg) { + if (wanted_arg) + break; + if (meth_arg) + break; + + if (flag1) { + wanted_arg = wanted->selector_args; + meth_arg = meth->selector_args; + while (1) { + if (!wanted_arg) + break; + if (wanted_arg->qual != meth_arg->qual) + break; + + if (wanted_arg->type) { + if (!meth_arg->type) + break; + if (!CObjC_IsSameType(wanted_arg->type, meth_arg->type)) + break; + } else { + if (meth_arg->type) + break; + } + + meth_arg->name = wanted_arg->name; + wanted_arg = wanted_arg->next; + meth_arg = meth_arg->next; + } + + if ( + wanted_arg || + wanted->has_valist != meth->has_valist || + wanted->return_qual != meth->return_qual || + !CObjC_IsSameType(wanted->return_type, meth->return_type) + ) + CError_Error(CErrorStr293, meth); + } + + return meth; + } + + if (wanted_arg->selector != meth_arg->selector) + break; + if (!wanted_arg->type && meth_arg->type) + break; + if (wanted_arg->type && !meth_arg->type) + break; + + wanted_arg = wanted_arg->next; + meth_arg = meth_arg->next; + } + } + } + + if (!flag2) + CError_Error(CErrorStr294, wanted); + return NULL; +} + +static ObjCMethod *CObjC_CloneMethod(ObjCMethod *meth) { + ObjCMethod *copy; + + copy = galloc(sizeof(ObjCMethod)); + memclrw(copy, sizeof(ObjCMethod)); + + copy->selector = meth->selector; + copy->return_type = meth->return_type; + copy->return_qual = meth->return_qual; + copy->selector_args = meth->selector_args; + copy->has_valist = meth->has_valist; + copy->is_class_method = meth->is_class_method; + copy->is_defined = 0; + + return copy; +} + +static void CObjC_AddProtocolMethods(TypeClass *tclass, ObjCMethod **methods, ObjCProtocolList *protocols) { + ObjCMethod *meth; + ObjCMethod *copy; + + while (protocols) { + for (meth = protocols->protocol->methods; meth; meth = meth->next) { + if (!CObjC_FindMethod(*methods, meth, 1, 1)) { + copy = CObjC_CloneMethod(meth); + copy->next = *methods; + *methods = copy; + if (tclass) + CObjC_MakeSelector(copy); + } + } + protocols = protocols->next; + } +} + +static void CObjC_AppendArgument(TypeFunc *tfunc, HashNameNode *name, Type *type, UInt32 qual) { + FuncArg *arg; + + if (tfunc->args) { + arg = tfunc->args; + while (arg->next) + arg = arg->next; + arg->next = CParser_NewFuncArg(); + arg = arg->next; + } else { + arg = CParser_NewFuncArg(); + tfunc->args = arg; + } + + arg->name = name; + arg->type = type; + arg->qual = qual; +} + +static HashNameNode *CObjC_MangleMethodName(TypeClass *tclass, ObjCCategory *cat, ObjCMethod *meth) { + ObjCMethodArg *arg; + HashNameNode *name; + + name_mangle_list.size = 0; + + if (meth->is_class_method) + AppendGListName(&name_mangle_list, "+["); + else + AppendGListName(&name_mangle_list, "-["); + + AppendGListName(&name_mangle_list, tclass->classname->name); + + if (cat) { + AppendGListByte(&name_mangle_list, '('); + AppendGListName(&name_mangle_list, cat->name->name); + AppendGListByte(&name_mangle_list, ')'); + } + + AppendGListByte(&name_mangle_list, ' '); + + for (arg = meth->selector_args; arg; arg = arg->next) { + if (arg->selector) + AppendGListName(&name_mangle_list, arg->selector->name); + if (arg->type) + AppendGListByte(&name_mangle_list, ':'); + } + + AppendGListID(&name_mangle_list, "]"); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static TypeFunc *CObjC_GetMethodFuncType(ObjCMethod *meth) { + ObjCMethodArg *metharg; + TypeFunc *functype; + FuncArg *funcarg; + + if (!meth->functype) { + functype = galloc(sizeof(TypeFunc)); + memclrw(functype, sizeof(TypeFunc)); + + functype->type = TYPEFUNC; + functype->functype = meth->return_type; + functype->qual = meth->return_qual; + functype->flags = FUNC_FLAGS_4000; + CDecl_SetFuncFlags(functype, 1); + + CObjC_AppendArgument(functype, CObjC_GetSelfName(), CObjC_GetObjCType_id(1), 0); + CObjC_AppendArgument(functype, GetHashNameNodeExport("_cmd"), CObjC_FindObjCType_SEL(), 0); + + for (metharg = meth->selector_args; metharg; metharg = metharg->next) { + if (metharg->type) + CObjC_AppendArgument(functype, metharg->name, metharg->type, metharg->qual); + } + + if (meth->has_valist) { + for (funcarg = functype->args; ; funcarg = funcarg->next) { + if (!funcarg->next) { + funcarg->next = &elipsis; + break; + } + } + } + + meth->functype = functype; + } + + return meth->functype; +} + +static Object *CObjC_GetMethodObject(TypeClass *tclass, ObjCCategory *cat, ObjCMethod *meth) { + Object *object; + Boolean saveCPP; + NameSpace *saveNS; + + if (!meth->object) { + saveCPP = copts.cplusplus; + copts.cplusplus = 0; + + saveNS = cscope_current; + cscope_current = cscope_root; + + object = CParser_NewFunctionObject(NULL); + object->nspace = tclass->nspace; + object->type = TYPE(CObjC_GetMethodFuncType(meth)); + object->name = CObjC_MangleMethodName(tclass, cat, meth); + object->u.func.linkname = object->name; + object->sclass = TK_STATIC; + meth->object = object; + + cscope_current = saveNS; + copts.cplusplus = saveCPP; + } + + return meth->object; +} + +static void CObjC_AddMethod(TypeClass *tclass) { + ObjCMethod *meth; + ObjCMethod *existing; + + if ((meth = CObjC_ParseMethod(1))) { + existing = CObjC_FindMethod(tclass->objcinfo->methods, meth, 0, 1); + if (!existing) { + meth->next = tclass->objcinfo->methods; + tclass->objcinfo->methods = meth; + CObjC_MakeSelector(meth); + } else { + if (copts.objc_strict || !CObjC_IsSameMethod(meth, existing)) + CError_Error(CErrorStr293, meth); + } + } + + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); +} + +static Boolean CObjC_IsSameProtocolList(ObjCProtocolList *a, ObjCProtocolList *b) { + while (1) { + if (!a) + return !b; + + if (!b || a->protocol != b->protocol) + return 0; + + a = a->next; + b = b->next; + } +} + +static ObjCProtocolList *CObjC_ParserProtocolList(void) { + ObjCProtocolList *list; + ObjCProtocolList *entry; + ObjCProtocol *protocol; + + list = NULL; + tk = lex(); + + while (1) { + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + break; + } + + if ((protocol = CObjC_FindProtocol(tkidentifier))) { + for (entry = list; entry; entry = entry->next) { + if (entry->protocol == protocol) + break; + } + + if (!entry) { + entry = galloc(sizeof(ObjCProtocolList)); + entry->next = list; + entry->protocol = protocol; + list = entry; + } else { + CError_Error(CErrorStr310, tkidentifier->name); + } + } else { + CError_Error(CErrorStr309, tkidentifier->name); + } + + if ((tk = lex()) == '>') { + tk = lex(); + break; + } + + if (tk != ',') { + CError_Error(CErrorStr116); + break; + } + + tk = lex(); + } + + return list; +} + +static void CObjC_AddClassMembers(TypeStruct *tstruct, TypeClass *tclass) { + ObjMemberVar *ivar; + StructMember *member; + + if (tclass->bases) + CObjC_AddClassMembers(tstruct, tclass->bases->base); + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + member = galloc(sizeof(StructMember)); + memclrw(member, sizeof(StructMember)); + + member->name = ivar->name; + member->type = ivar->type; + member->qual = ivar->qual; + member->offset = ivar->offset; + + appendmember(tstruct, member); + } +} + +void CObjC_ParseDefs(TypeStruct *tstruct) { + TypeClass *tclass; + + if ((tk = lex()) == '(') { + if ((tk = lex()) == TK_IDENTIFIER) { + if ((tclass = CObjC_FindObjCClass(tkidentifier, 1))) { + if (tclass->flags & CLASS_FLAGS_2) { + tstruct->size = tclass->size; + tstruct->align = tclass->align; + CObjC_AddClassMembers(tstruct, tclass); + } else { + CError_Error(CErrorStr136, tclass, 0); + } + } + + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + + } else { + CError_Error(CErrorStr107); + } + } else { + CError_Error(CErrorStr114); + } +} + +Type *CObjC_ParseID(void) { + TypeObjCID *type; + + if ((tk = lex()) == '<') { + type = galloc(sizeof(TypeObjCID)); + memclrw(type, sizeof(TypeObjCID)); + + type->pointer = *TYPE_POINTER(CObjC_GetObjCType_id(1)); + type->protocols = CObjC_ParserProtocolList(); + type->pointer.qual |= Q_100000; + + return TYPE(type); + } else { + return CObjC_GetObjCType_id(1); + } +} + +Type *CObjC_ParseTypeProtocol(TypeClass *tclass) { + CError_ASSERT(1526, tk == '<'); + CObjC_ParserProtocolList(); + return TYPE(tclass); +} + +static void CObjC_ParseCategoryInterface(TypeClass *tclass) { + ObjCCategory *cat; + ObjCMethod *meth; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + for (cat = tclass->objcinfo->categories; cat; cat = cat->next) { + if (cat->name == tkidentifier) { + CError_Error(CErrorStr311, tkidentifier->name); + break; + } + } + + cat = galloc(sizeof(ObjCCategory)); + memclrw(cat, sizeof(ObjCCategory)); + + cat->name = tkidentifier; + + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + return; + } + + tk = lex(); + if (tk == '<') { + cat->protocols = CObjC_ParserProtocolList(); + CObjC_AddProtocolMethods(tclass, &cat->methods, cat->protocols); + } + + while (1) { + switch (tk) { + case '-': + case '+': + if ((meth = CObjC_ParseMethod(1))) { + if (!CObjC_FindMethod(cat->methods, meth, 0, 1)) { + meth->next = cat->methods; + cat->methods = meth; + CObjC_MakeSelector(meth); + } else { + CError_Error(CErrorStr293, meth); + } + } + + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); + continue; + + case TK_AT_END: + break; + + default: + CParser_ParseGlobalDeclaration(); + continue; + } + + break; + } + + cat->next = tclass->objcinfo->categories; + tclass->objcinfo->categories = cat; +} + +static void CObjC_DefineMethod(TypeClass *tclass, ObjCCategory *category, ObjCMethod **methods) { + ObjCMethod *meth30; + Object *object; + ObjCMethod *meth26; + FuncArg *funcarg; + ObjCMethodArg *selarg; + DeclInfo di; + + meth26 = CObjC_ParseMethod(1); + if (!meth26) + return; + + meth30 = CObjC_FindMethod(*methods, meth26, 1, 1); + if (!meth30) { + meth30 = meth26; + meth26->next = *methods; + *methods = meth26; + CObjC_MakeSelector(meth26); + } + + if (meth30->is_defined) + CError_Error(CErrorStr300, meth30); + + object = CObjC_GetMethodObject(tclass, category, meth30); + CError_ASSERT(1627, IS_TYPE_FUNC(object->type)); + + if ((funcarg = TYPE_FUNC(object->type)->args)) { + funcarg->type = CDecl_NewPointerType(TYPE(tclass)); + + if (funcarg->next && funcarg->next->next) { + funcarg = funcarg->next->next; + selarg = meth26->selector_args; + while (selarg && funcarg) { + funcarg->name = selarg->name; + funcarg->type = selarg->type; + funcarg->qual |= selarg->qual; + selarg = selarg->next; + funcarg = funcarg->next; + } + } + } + + if (tk == ';') { + if (copts.objc_strict) + CError_Warning(CErrorStr135); + tk = lex(); + } + + memclrw(&di, sizeof(di)); + CFunc_ParseFuncDef(object, &di, tclass, 1, meth30->is_class_method, NULL); + meth30->is_defined = 1; + + tk = lex(); +} + +static void CObjC_EncodeTypeStruct(TypeStruct *tstruct, Boolean flag) { + StructMember *member; + + AppendGListByte(&name_mangle_list, (tstruct->stype == STRUCT_TYPE_UNION) ? '(' : '{'); + + if (cobjc_encodemethod) + AppendGListByte(&name_mangle_list, '?'); + else if (tstruct->name) + AppendGListName(&name_mangle_list, tstruct->name->name); + + if (flag) { + AppendGListByte(&name_mangle_list, '='); + for (member = tstruct->members; member; member = member->next) + CObjC_EncodeType(member->type, member->qual, 1); + } + + AppendGListByte(&name_mangle_list, (tstruct->stype == STRUCT_TYPE_UNION) ? ')' : '}'); +} + +static void CObjC_EncodeTypeClass(TypeClass *tclass, Boolean flag) { + ObjMemberVar *ivar; + + if (CClass_IsPODClass(tclass)) { + AppendGListByte(&name_mangle_list, (tclass->mode == CLASS_MODE_1) ? '(' : '{'); + + if (cobjc_encodemethod) + AppendGListByte(&name_mangle_list, '?'); + else if (tclass->classname) + AppendGListName(&name_mangle_list, tclass->classname->name); + + if (flag) { + AppendGListByte(&name_mangle_list, '='); + for (ivar = tclass->ivars; ivar; ivar = ivar->next) + CObjC_EncodeType(ivar->type, ivar->qual, 1); + } + + AppendGListByte(&name_mangle_list, (tclass->mode == CLASS_MODE_1) ? ')' : '}'); + } else { + AppendGListByte(&name_mangle_list, '?'); + } +} + +static void CObjC_EncodeTypeMethod(ObjCMethod *meth, Boolean flag) { + ObjCMethodArg *arg; + + char buf[16]; + + if (meth->return_qual & Q_IN) + AppendGListByte(&name_mangle_list, 'n'); + if (meth->return_qual & Q_OUT) + AppendGListByte(&name_mangle_list, 'o'); + if (meth->return_qual & Q_INOUT) + AppendGListByte(&name_mangle_list, 'N'); + if (meth->return_qual & Q_BYCOPY) + AppendGListByte(&name_mangle_list, 'O'); + if (meth->return_qual & Q_ONEWAY) + AppendGListByte(&name_mangle_list, 'V'); + + if (meth->return_type) + CObjC_EncodeType(meth->return_type, 0, flag); + else + AppendGListByte(&name_mangle_list, '@'); + + sprintf(buf, "%ld", CodeGen_objc_method_args_size(meth)); + AppendGListName(&name_mangle_list, buf); + + AppendGListByte(&name_mangle_list, '@'); + + sprintf(buf, "%ld", CodeGen_objc_method_self_offset(meth)); + AppendGListName(&name_mangle_list, buf); + + AppendGListByte(&name_mangle_list, ':'); + + sprintf(buf, "%ld", CodeGen_objc_method_sel_offset(meth)); + AppendGListName(&name_mangle_list, buf); + + for (arg = meth->selector_args; arg; arg = arg->next) { + if (arg->type) { + if (arg->qual & Q_CONST) + AppendGListByte(&name_mangle_list, 'r'); + + CObjC_EncodeType(arg->type, 0, flag); + + sprintf(buf, "%ld", CodeGen_objc_method_arg_offset(meth, arg)); + AppendGListName(&name_mangle_list, buf); + } + } +} + +static void CObjC_EncodeType(Type *type, UInt32 qual, Boolean flag) { + char buf[16]; + + while (1) { + switch (type->type) { + case TYPEVOID: + AppendGListByte(&name_mangle_list, 'v'); + return; + + case TYPEINT: + case TYPEFLOAT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + AppendGListByte(&name_mangle_list, 'C'); + return; + case IT_CHAR: + AppendGListByte(&name_mangle_list, copts.unsignedchars ? 'C' : 'c'); + return; + case IT_UCHAR: + AppendGListByte(&name_mangle_list, 'C'); + return; + case IT_SCHAR: + AppendGListByte(&name_mangle_list, 'c'); + return; + case IT_WCHAR_T: + AppendGListByte(&name_mangle_list, 'i'); + return; + case IT_SHORT: + AppendGListByte(&name_mangle_list, 's'); + return; + case IT_USHORT: + AppendGListByte(&name_mangle_list, 'S'); + return; + case IT_INT: + AppendGListByte(&name_mangle_list, 'i'); + return; + case IT_UINT: + AppendGListByte(&name_mangle_list, 'I'); + return; + case IT_LONG: + AppendGListByte(&name_mangle_list, 'l'); + return; + case IT_ULONG: + AppendGListByte(&name_mangle_list, 'L'); + return; + case IT_LONGLONG: + AppendGListByte(&name_mangle_list, 'q'); + return; + case IT_ULONGLONG: + AppendGListByte(&name_mangle_list, 'Q'); + 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, 'D'); + return; + default: + CError_FATAL(1841); + } + + case TYPEENUM: + type = TYPE_ENUM(type)->enumtype; + continue; + + case TYPEPOINTER: + if (CObjC_IsType_id(type)) { + AppendGListByte(&name_mangle_list, '@'); + return; + } + if (CObjC_IsType_SEL(type)) { + AppendGListByte(&name_mangle_list, ':'); + return; + } + type = TPTR_TARGET(type); + if (type == TYPE(&stchar)) { + AppendGListByte(&name_mangle_list, '*'); + return; + } + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->objcinfo) { + AppendGListByte(&name_mangle_list, '@'); + return; + } + AppendGListByte(&name_mangle_list, '^'); + flag = cobjc_encodemethod; + continue; + + case TYPEARRAY: + AppendGListByte(&name_mangle_list, '['); + if (TPTR_TARGET(type)->size) { + sprintf(buf, "%ld", type->size / TPTR_TARGET(type)->size); + AppendGListName(&name_mangle_list, buf); + } else { + AppendGListByte(&name_mangle_list, '0'); + } + CObjC_EncodeType(TPTR_TARGET(type), 0, 1); + AppendGListByte(&name_mangle_list, ']'); + return; + + case TYPEBITFIELD: + AppendGListByte(&name_mangle_list, 'b'); + sprintf(buf, "%ld", TYPE_BITFIELD(type)->unkB); + AppendGListName(&name_mangle_list, buf); + return; + + case TYPESTRUCT: + CObjC_EncodeTypeStruct(TYPE_STRUCT(type), flag); + return; + + case TYPECLASS: + CObjC_EncodeTypeClass(TYPE_CLASS(type), flag); + return; + + case TYPEFUNC: + case TYPETEMPLATE: + case TYPEMEMBERPOINTER: + AppendGListByte(&name_mangle_list, '?'); + return; + + default: + CError_FATAL(1892); + } + break; + } +} + +static char *CObjC_EncodeMethodTypeString(ObjCMethod *meth, int unused) { + char *buf; + + cobjc_encodemethod = 1; + + name_mangle_list.size = 0; + CObjC_EncodeTypeMethod(meth, 1); + AppendGListByte(&name_mangle_list, 0); + + buf = galloc(name_mangle_list.size); + memcpy(buf, *name_mangle_list.data, name_mangle_list.size); + + cobjc_encodemethod = 0; + + return buf; +} + +static char *CObjC_EncodeTypeString(Type *type, UInt32 qual) { + char *buf; + + name_mangle_list.size = 0; + CObjC_EncodeType(type, qual, 1); + AppendGListByte(&name_mangle_list, 0); + + buf = galloc(name_mangle_list.size); + memcpy(buf, *name_mangle_list.data, name_mangle_list.size); + + return buf; +} + +typedef struct RawIVar { + UInt32 name; + UInt32 typestring; + UInt32 offset; +} RawIVar; +typedef struct RawIVarList { + UInt32 count; + RawIVar ivars[1]; +} RawIVarList; + +static Object *CObjC_DefineIVarListObject(TypeClass *tclass) { + Object *object; + RawIVarList *data; + ObjMemberVar *ivar; + OLinkList *refs; + OLinkList *ref; + RawIVar *rawvar; + int i; + SInt32 size; + char *str; + + for (ivar = tclass->ivars, i = 0; ivar; ivar = ivar->next) + i++; + + if (i) { + size = sizeof(RawIVarList) + sizeof(RawIVar) * (i - 1); + data = lalloc(size); + memclrw(data, size); + + object = CObjC_MakeObject( + "L_OBJC_INSTANCE_VARIABLES_", tclass->classname->name, + size); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_INSTANCE_VARS; + + refs = NULL; + data->count = CTool_EndianConvertWord32(i); + + for (ivar = tclass->ivars, rawvar = data->ivars; ivar; ivar = ivar->next, rawvar++) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(ivar->name->name, SECT_OBJC_METH_VAR_NAMES); + ref->offset = ((char *) &rawvar->name) - ((char *) data); + ref->somevalue = 0; + + str = CObjC_EncodeTypeString(ivar->type, ivar->qual); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(str, SECT_OBJC_METH_VAR_TYPES); + ref->offset = ((char *) &rawvar->typestring) - ((char *) data); + ref->somevalue = 0; + + rawvar->offset = CTool_EndianConvertWord32(ivar->offset); + } + + CInit_DeclareData(object, data, refs, object->type->size); + } else { + object = NULL; + } + + return object; +} + +typedef struct RawMethod { + UInt32 name; + UInt32 typestring; + UInt32 offset; +} RawMethod; +typedef struct RawMethodList { + UInt32 x0; + UInt32 count; + RawMethod methods[1]; +} RawMethodList; + +static Object *CObjC_DefineMethodListObject(TypeClass *tclass, ObjCCategory *cat, ObjCMethod *methods, char *name1, char *name2, Section sectionID, Boolean doing_class_methods) { + Object *object; + RawMethodList *data; + ObjCMethod *meth; + OLinkList *refs; + OLinkList *ref; + RawMethod *rawmeth; + int i; + SInt32 size; + + for (meth = methods, i = 0; meth; meth = meth->next) { + if (doing_class_methods == meth->is_class_method) + i++; + } + + if (i) { + size = sizeof(RawMethodList) + sizeof(RawMethod) * (i - 1); + data = lalloc(size); + memclrw(data, size); + + object = CObjC_MakeObject(name1, name2, size); + object->sclass = TK_STATIC; + object->section = sectionID; + + refs = NULL; + data->count = CTool_EndianConvertWord32(i); + + for (meth = methods, rawmeth = data->methods; meth; meth = meth->next) { + if (doing_class_methods == meth->is_class_method) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(meth->selector->name->name, SECT_OBJC_METH_VAR_NAMES); + ref->offset = ((char *) &rawmeth->name) - ((char *) data); + ref->somevalue = 0; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(CObjC_EncodeMethodTypeString(meth, 0), SECT_OBJC_METH_VAR_TYPES); + ref->offset = ((char *) &rawmeth->typestring) - ((char *) data); + ref->somevalue = 0; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_GetMethodObject(tclass, cat, meth); + ref->offset = ((char *) &rawmeth->offset) - ((char *) data); + ref->somevalue = 0; + + rawmeth++; + } + } + + CInit_DeclareData(object, data, refs, object->type->size); + } else { + object = NULL; + } + + return object; +} + +typedef struct RawProtocolList { + UInt32 offset; +} RawProtocolList; +typedef struct RawProtocolListList { + UInt32 x0; + UInt32 count; + RawProtocolList lists[1]; +} RawProtocolListList; + +static Object *CObjC_DefineProtocolListObject(ObjCProtocolList *list, char *str) { + Object *object; + RawProtocolListList *data; + ObjCProtocolList *scan; + OLinkList *refs; + OLinkList *ref; + int i; + SInt32 size; + + for (scan = list, i = 0; scan; scan = scan->next) + i++; + + if (i) { + size = sizeof(RawProtocolListList) + sizeof(RawProtocolList) * (i - 1); + data = lalloc(size); + memclrw(data, size); + + object = CObjC_MakeObject("L_OBJC_PROTOCOLS_", str, size); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_PROTOCOL; + + refs = NULL; + data->count = CTool_EndianConvertWord32(i); + + for (scan = list, i = 0; scan; scan = scan->next, i++) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_GetProtocolObject(scan->protocol); + ref->offset = ((char *) &data->lists[i].offset) - ((char *) data); + ref->somevalue = 0; + } + + CInit_DeclareData(object, data, refs, object->type->size); + } else { + object = NULL; + } + + return object; +} + +typedef struct RawProtocolMethodList { + UInt32 name; + UInt32 typestring; +} RawProtocolMethodList; +typedef struct RawProtocolMethodListList { + UInt32 count; + RawProtocolMethodList methods[1]; +} RawProtocolMethodListList; + +static Object *CObjC_DefineProtocolMethodListObject(ObjCProtocol *protocol, char *name, Section sectionID, Boolean doing_class_methods) { + Object *object; + ObjCMethod *meth; + OLinkList *refs; + OLinkList *ref; + RawProtocolMethodList *rawmeth; + RawProtocolMethodListList *data; + int i; + SInt32 size; + + for (meth = protocol->methods, i = 0; meth; meth = meth->next) { + if (doing_class_methods == meth->is_class_method) + i++; + } + + if (i) { + size = sizeof(RawProtocolMethodListList) + sizeof(RawProtocolMethodList) * (i - 1); + data = lalloc(size); + memclrw(data, size); + + object = CObjC_MakeObject(name, protocol->name->name, size); + object->sclass = TK_STATIC; + object->section = sectionID; + + refs = NULL; + data->count = CTool_EndianConvertWord32(i); + + for (meth = protocol->methods, rawmeth = data->methods; meth; meth = meth->next) { + if (doing_class_methods == meth->is_class_method) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(meth->selector->name->name, SECT_OBJC_METH_VAR_NAMES); + ref->offset = ((char *) &rawmeth->name) - ((char *) data); + ref->somevalue = 0; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(CObjC_EncodeMethodTypeString(meth, 0), SECT_OBJC_METH_VAR_TYPES); + ref->offset = ((char *) &rawmeth->typestring) - ((char *) data); + ref->somevalue = 0; + + rawmeth++; + } + } + + CInit_DeclareData(object, data, refs, object->type->size); + } else { + object = NULL; + } + + return object; +} + +typedef struct RawProtocol { + UInt32 x0; + UInt32 x4; + UInt32 x8; + UInt32 xC; + UInt32 x10; +} RawProtocol; + +static Object *CObjC_GetProtocolObject(ObjCProtocol *protocol) { + TypeClass *protocolType; + OLinkList *refs; + OLinkList *ref; + Object *object; + char *str; + RawProtocol data; + + refs = NULL; + + if (!protocol->object) { + if ((protocolType = CObjC_FindObjCClass(GetHashNameNodeExport("Protocol"), 1))) { + data.x0 = 0; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(protocolType->classname->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 0; + ref->somevalue = 0; + + data.x4 = 0; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(protocol->name->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 4; + ref->somevalue = 0; + + data.x8 = 0; + + if (protocol->protocols) { + str = CObjC_StringConcat(protocol->name->name, "_PROTOCOLS", NULL); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_DefineProtocolListObject(protocol->protocols, str); + ref->offset = 8; + ref->somevalue = 0; + } + + data.xC = 0; + + object = CObjC_DefineProtocolMethodListObject(protocol, "L_OBJC_PROTOCOL_INSTANCE_METHODS_", SECT_OBJC_CAT_INST_METH, 0); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0xC; + ref->somevalue = 0; + } + + data.x10 = 0; + + object = CObjC_DefineProtocolMethodListObject(protocol, "L_OBJC_PROTOCOL_CLASS_METHODS_", SECT_OBJC_CAT_CLS_METH, 1); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0x10; + ref->somevalue = 0; + } + + object = CObjC_MakeObject("L_OBJC_PROTOCOL_", protocol->name->name, sizeof(data)); + protocol->object = object; + object->type = TYPE(protocolType); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_PROTOCOL; + if (object->type->size != sizeof(data)) { + if (object->type->size == 0) + object->type = CDecl_NewStructType(sizeof(data), 4); + else + CError_FATAL(2262); + } + + CInit_DeclareData(object, &data, refs, object->type->size); + object->type = TYPE(protocolType); + } + + if (!protocol->object) + protocol->object = CObjC_SectionString(protocol->name->name, SECT_OBJC_PROTOCOL); + } + + return protocol->object; +} + +static void CObjC_DefineClassObjects(TypeClass *tclass) { + Object *protocollistobj; + Object *classobject; + Object *classnameobj; + OLinkList *refs; + Object *metaobject; + OLinkList *ref; + Object *object; + TypeClass *basescan; + UInt32 data[10]; + + metaobject = tclass->objcinfo->metaobject; + classobject = tclass->objcinfo->classobject; + classnameobj = CObjC_SectionString(tclass->classname->name, SECT_OBJC_CLASS_NAMES); + protocollistobj = CObjC_DefineProtocolListObject(tclass->objcinfo->protocols, tclass->classname->name); + + // part 1 + data[0] = CTool_EndianConvertWord32(0); + data[1] = CTool_EndianConvertWord32(0); + + basescan = tclass; + while (basescan->bases) + basescan = basescan->bases->base; + + refs = NULL; + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(basescan->classname->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 0; + ref->somevalue = 0; + + if (tclass->bases) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(tclass->bases->base->classname->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 4; + ref->somevalue = 0; + } + + data[2] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = classnameobj; + ref->offset = 8; + ref->somevalue = 0; + + data[3] = CTool_EndianConvertWord32(0); + data[4] = CTool_EndianConvertWord32(2); + data[5] = CTool_EndianConvertWord32(sizeof(data)); + data[6] = CTool_EndianConvertWord32(0); + data[7] = CTool_EndianConvertWord32(0); + + object = CObjC_DefineMethodListObject( + tclass, NULL, tclass->objcinfo->methods, "L_OBJC_CLASS_METHODS_", + tclass->classname->name, SECT_OBJC_CLS_METH, 1); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0x1C; + ref->somevalue = 0; + } + + data[8] = CTool_EndianConvertWord32(0); + data[9] = CTool_EndianConvertWord32(0); + + if (protocollistobj) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = protocollistobj; + ref->offset = 0x24; + ref->somevalue = 0; + } + + CError_ASSERT(2367, metaobject->type->size == sizeof(data)); + CInit_DeclareData(metaobject, data, refs, metaobject->type->size); + + // part 2 + refs = NULL; + + data[0] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = metaobject; + ref->offset = 0; + ref->somevalue = 0; + + data[1] = CTool_EndianConvertWord32(0); + + if (tclass->bases) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(tclass->bases->base->classname->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 4; + ref->somevalue = 0; + } + + data[2] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = classnameobj; + ref->offset = 8; + ref->somevalue = 0; + + data[3] = CTool_EndianConvertWord32(0); + data[4] = CTool_EndianConvertWord32(1); + data[5] = CTool_EndianConvertWord32(tclass->size); + data[6] = CTool_EndianConvertWord32(0); + + object = CObjC_DefineIVarListObject(tclass); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0x18; + ref->somevalue = 0; + } + + data[7] = CTool_EndianConvertWord32(0); + + object = CObjC_DefineMethodListObject( + tclass, NULL, tclass->objcinfo->methods, "L_OBJC_INSTANCE_METHODS_", + tclass->classname->name, SECT_OBJC_INST_METH, 0); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0x1C; + ref->somevalue = 0; + } + + data[8] = CTool_EndianConvertWord32(0); + data[9] = CTool_EndianConvertWord32(0); + + if (protocollistobj) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = protocollistobj; + ref->offset = 0x24; + ref->somevalue = 0; + } + + CError_ASSERT(2437, classobject->type->size == sizeof(data)); + CInit_DeclareData(classobject, data, refs, classobject->type->size); +} + +static void CObjC_DefineCategoryObjects(TypeClass *tclass, ObjCCategory *cat) { + OLinkList *refs; + Object *categoryObj; + char *namestr; + OLinkList *ref; + Object *object; + ObjCCategoryEntry *entry; + UInt32 data[5]; + + namestr = CObjC_StringConcat(tclass->classname->name, "_", cat->name->name); + + categoryObj = CObjC_MakeObject("L_OBJC_CATEGORY_", namestr, sizeof(data)); + categoryObj->sclass = TK_STATIC; + categoryObj->section = SECT_OBJC_CATEGORY; + + refs = NULL; + + data[0] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(cat->name->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 0; + ref->somevalue = 0; + + data[1] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_SectionString(tclass->classname->name, SECT_OBJC_CLASS_NAMES); + ref->offset = 4; + ref->somevalue = 0; + + data[2] = CTool_EndianConvertWord32(0); + + object = CObjC_DefineMethodListObject( + tclass, cat, cat->methods, "L_OBJC_CATEGORY_INSTANCE_METHODS_", + namestr, SECT_OBJC_CAT_INST_METH, 0); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 8; + ref->somevalue = 0; + } + + data[3] = CTool_EndianConvertWord32(0); + + object = CObjC_DefineMethodListObject( + tclass, cat, cat->methods, "L_OBJC_CATEGORY_CLASS_METHODS_", + namestr, SECT_OBJC_CAT_CLS_METH, 1); + if (object) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0xC; + ref->somevalue = 0; + } + + data[4] = CTool_EndianConvertWord32(0); + + if (cat->protocols) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CObjC_DefineProtocolListObject(cat->protocols, namestr); + ref->offset = 0x10; + ref->somevalue = 0; + } + + CInit_DeclareData(categoryObj, data, refs, categoryObj->type->size); + + entry = galloc(sizeof(ObjCCategoryEntry)); + entry->category = cat; + entry->object = categoryObj; + entry->next = cobjc_categories; + cobjc_categories = entry; +} + +static void CObjC_ParseCategoryImplementation(TypeClass *tclass) { + ObjCCategory *cat; + ObjCMethod *meth; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + for (cat = tclass->objcinfo->categories; cat; cat = cat->next) { + if (cat->name == tkidentifier) + break; + } + + if (!cat) { + if (copts.objc_strict) + CError_Warning(CErrorStr312, tkidentifier->name); + + cat = galloc(sizeof(ObjCCategory)); + memclrw(cat, sizeof(ObjCCategory)); + + cat->name = tkidentifier; + cat->next = tclass->objcinfo->categories; + tclass->objcinfo->categories = cat; + } + + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + return; + } + + tk = lex(); + while (1) { + switch (tk) { + case '-': + case '+': + CObjC_DefineMethod(tclass, cat, &cat->methods); + continue; + + case TK_AT_END: + break; + + default: + CParser_ParseGlobalDeclaration(); + continue; + } + break; + } + + for (meth = cat->methods; meth; meth = meth->next) { + if (!meth->is_defined) + CError_Warning(CErrorStr299, meth); + } + + CObjC_DefineCategoryObjects(tclass, cat); +} + +static Boolean CObjC_IsSameMemberList(ObjMemberVar *a, ObjMemberVar *b) { + while (1) { + if (!a) + return !b; + + if ( + !b || + a->name != b->name || + a->qual != b->qual || + a->access != b->access || + !is_typesame(a->type, b->type) + ) + return 0; + + a = a->next; + b = b->next; + } +} + +static void CObjC_ParseInstanceVariables(TypeClass *tclass, Boolean checkOnly) { + AccessType access; + ObjMemberVar *first; + ObjMemberVar *ivar; + ObjMemberVar *scan; + BigDeclInfo bdi; + + tk = lex(); + access = ACCESSPROTECTED; + + for (first = NULL; ; tk = lex()) { + if (tk == '}') { + tk = lex(); + break; + } + + switch (tk) { + case TK_AT_PRIVATE: + access = ACCESSPRIVATE; + continue; + + case TK_AT_PROTECTED: + access = ACCESSPROTECTED; + continue; + + case TK_AT_PUBLIC: + access = ACCESSPUBLIC; + continue; + } + + memclrw(&bdi, sizeof(bdi)); + CParser_GetDeclSpecs(&bdi.declinfo, 0); + if (bdi.declinfo.storageclass || bdi.declinfo.x44) { + CError_Error(CErrorStr131); + return; + } + + if (tk != ';') { + while (1) { + CDecl_ScanStructDeclarator(&bdi); + if (!CanCreateObject(bdi.declinfo2.thetype)) { + CError_Error(CErrorStr131); + bdi.xCD = 0; + } + if (bdi.declinfo2.x3E) { + CError_Error(CErrorStr131); + bdi.xCD = 0; + } + if (bdi.declinfo.x48) + CError_Error(CErrorStr121); + + if (bdi.xCD) { + for (ivar = first; ivar; ivar = ivar->next) { + if (ivar->name == bdi.declinfo2.name) + break; + } + + if (ivar || bdi.declinfo2.name == no_name_node) { + CError_Error(CErrorStr133, bdi.declinfo2.name->name); + } else { + ivar = galloc(sizeof(ObjMemberVar)); + memclrw(ivar, sizeof(ObjMemberVar)); + + ivar->otype = OT_MEMBERVAR; + ivar->access = access; + ivar->type = bdi.declinfo2.thetype; + ivar->name = bdi.declinfo2.name; + ivar->qual = bdi.declinfo2.qual; + + if ((scan = first)) { + while (scan->next) + scan = scan->next; + scan->next = ivar; + } else { + first = ivar; + } + + if (!checkOnly) + CScope_AddObject(tclass->nspace, ivar->name, OBJ_BASE(ivar)); + } + } + + if (tk != ',') + break; + + tk = lex(); + } + } + + if (tk != ';') { + CError_Error(CErrorStr123); + break; + } + } + + if (checkOnly) { + if (!CObjC_IsSameMemberList(tclass->ivars, first)) + CError_Error(CErrorStr323); + } else { + tclass->ivars = first; + } +} + +static void CObjC_ParseInterfaceImplementation(void) { + TypeClass *tclass; + Boolean isInterface; + Boolean flag2; + ClassList *base; + TypeClass *tclassbase; + ObjCProtocolList *protlist; + ObjCMethod *meth; + BClassList *classdef; + + isInterface = tk == TK_AT_INTERFACE; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if (!(tclass = CObjC_NewObjCClass(tkidentifier))) + return; + + if ((tk = lex()) == '(') { + if (isInterface) + CObjC_ParseCategoryInterface(tclass); + else + CObjC_ParseCategoryImplementation(tclass); + return; + } + + flag2 = (tclass->flags & CLASS_FLAGS_2) ? 1 : 0; + if (flag2 && isInterface) { + CError_Error(CErrorStr132, tclass->classname->name); + return; + } + + if (tk == ':') { + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if ((tclassbase = CObjC_FindObjCClass(tkidentifier, 1))) { + if (tclassbase->flags & CLASS_FLAGS_2) { + if (!flag2) { + base = galloc(sizeof(ClassList)); + memclrw(base, sizeof(ClassList)); + + base->base = tclassbase; + base->access = ACCESSPUBLIC; + tclass->bases = base; + } else { + if (!tclass->bases || tclass->bases->base != tclassbase) + CError_Error(CErrorStr325); + } + } else { + CError_Error(CErrorStr136, tclassbase, 0); + } + } + + tk = lex(); + } + + if (tk == '<') { + protlist = CObjC_ParserProtocolList(); + if (flag2) { + if (!CObjC_IsSameProtocolList(protlist, tclass->objcinfo->protocols)) + CError_Error(CErrorStr324); + } else { + tclass->objcinfo->protocols = protlist; + CObjC_AddProtocolMethods(tclass, &tclass->objcinfo->methods, tclass->objcinfo->protocols); + } + } + + if (tk == '{') + CObjC_ParseInstanceVariables(tclass, flag2); + + if (!flag2) { + DeclE decle; + memclrw(&decle, sizeof(decle)); + CABI_LayoutClass(&decle, tclass); + } + + cobjc_currentclass = tclass; + + while (1) { + switch (tk) { + case '+': + case '-': + if (isInterface) + CObjC_AddMethod(tclass); + else + CObjC_DefineMethod(tclass, NULL, &tclass->objcinfo->methods); + continue; + + case TK_AT_END: + break; + + default: + CParser_ParseGlobalDeclaration(); + continue; + } + + break; + } + + cobjc_currentclass = NULL; + + if (!isInterface) { + for (meth = tclass->objcinfo->methods; meth; meth = meth->next) { + if (!meth->is_defined) + CError_Warning(CErrorStr299, meth); + } + + CObjC_DefineClassObjects(tclass); + + classdef = galloc(sizeof(BClassList)); + classdef->next = cobjc_classdefs; + classdef->type = TYPE(tclass); + cobjc_classdefs = classdef; + } +} + +void CObjC_ParseInterface(void) { + CObjC_ParseInterfaceImplementation(); +} + +void CObjC_ParseImplementation(void) { + CObjC_ParseInterfaceImplementation(); +} + +void CObjC_ParseProtocol(void) { + ObjCProtocol *protocol; + ObjCMethod *meth; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if ((protocol = CObjC_FindProtocol(tkidentifier))) + CError_Error(CErrorStr308, protocol->name->name); + + protocol = galloc(sizeof(ObjCProtocol)); + memclrw(protocol, sizeof(ObjCProtocol)); + + protocol->name = tkidentifier; + + if ((tk = lex()) == '<') { + protocol->protocols = CObjC_ParserProtocolList(); + CObjC_AddProtocolMethods(NULL, &protocol->methods, protocol->protocols); + } + + protocol->next = cobjc_protocols; + cobjc_protocols = protocol; + + while (1) { + switch (tk) { + case '-': + case '+': + if ((meth = CObjC_ParseMethod(1))) { + if (!CObjC_FindMethod(protocol->methods, meth, 0, 1)) { + meth->next = protocol->methods; + protocol->methods = meth; + CObjC_MakeSelector(meth); + } + } + + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); + continue; + + case TK_AT_END: + break; + + default: + CParser_ParseGlobalDeclaration(); + continue; + } + + break; + } +} + +void CObjC_ParseClassDeclaration(void) { + while (1) { + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + break; + } + + CObjC_NewObjCClass(tkidentifier); + + if ((tk = lex()) != ',') { + if (tk != ';') + CError_Error(CErrorStr123); + break; + } + } +} + +void *CObjC_ParseIdentifier() { + // ??? unused + return NULL; +} + +static void CObjC_CoerceMethodArgs(ObjCMethod *meth, ObjCNamedArg *namedArgs, ENodeList *unnamedArgs) { + ObjCMethodArg *metharg; + ObjCNamedArg *arg; + + if (namedArgs->expr) { + metharg = meth->selector_args; + arg = namedArgs; + while (1) { + arg->expr = argumentpromotion(arg->expr, metharg->type, metharg->qual, 1); + arg = arg->next; + if (!arg) + break; + metharg = metharg->next; + CError_ASSERT(3004, metharg); + } + } + + while (unnamedArgs) { + unnamedArgs->node = CExpr_VarArgPromotion(unnamedArgs->node, 1); + unnamedArgs = unnamedArgs->next; + } +} + +static Boolean CObjC_SelectorCompare(ObjCMethod *method, ObjCNamedArg *args, Boolean has_varargs) { + ObjCMethodArg *metharg; + + if (has_varargs && !method->has_valist) + return 0; + + metharg = method->selector_args; + do { + if (metharg->selector != args->name) + return 0; + if (!metharg->type && args->expr) + return 0; + if (metharg->type && !args->expr) + return 0; + + args = args->next; + if (!args) { + if (!metharg->next) + return 1; + else + return 0; + } + + } while ((metharg = metharg->next)); + + return 0; +} + +ENode *CObjC_MakeSendMsgExpr(ENode *objexpr, TypeClass *tclass, ObjCNamedArg *namedArgs, ENodeList *unnamedArgs, UInt8 calltype, Boolean isSuper) { + ObjCMethod *meth; + ObjCSelector *sel; + ENode *callexpr; + ObjCMethodList *methlist; + TypeClass *scanclass; + Object *sendMsgFunc; + TypeFunc *methodtype; + ObjCNamedArg *namedArg; + ENodeList *arg; + ObjCCategory *cat; + ObjCProtocolList *protlist; + + meth = NULL; + + if (tclass) { + scanclass = tclass; + while (1) { + CError_ASSERT(3112, scanclass->objcinfo); + + for (cat = scanclass->objcinfo->categories; cat; cat = cat->next) { + for (meth = cat->methods; meth; meth = meth->next) { + switch (calltype) { + case 0: + if (meth->is_class_method) + continue; + break; + case 1: + if (!meth->is_class_method) + continue; + break; + case 2: + break; + } + + if (CObjC_SelectorCompare(meth, namedArgs, unnamedArgs != NULL)) { + CObjC_CoerceMethodArgs(meth, namedArgs, unnamedArgs); + sel = CObjC_MakeSelector(meth); + break; + } + } + + if (meth) + break; + } + + if (meth) + break; + + for (meth = scanclass->objcinfo->methods; meth; meth = meth->next) { + if (CObjC_SelectorCompare(meth, namedArgs, unnamedArgs != NULL)) { + CObjC_CoerceMethodArgs(meth, namedArgs, unnamedArgs); + sel = CObjC_MakeSelector(meth); + break; + } + } + + if (meth) + break; + + if (!scanclass->bases) { + CError_Warning(CErrorStr304); + break; + } + + scanclass = scanclass->bases->base; + } + } + + if (!meth) { + if (IS_TYPE_POINTER_ONLY(objexpr->rtype) && (TPTR_QUAL(objexpr->rtype) & Q_100000)) { + for (protlist = TYPE_OBJC_ID(objexpr->rtype)->protocols; protlist; protlist = protlist->next) { + for (meth = protlist->protocol->methods; meth; meth = meth->next) { + if (CObjC_SelectorCompare(meth, namedArgs, unnamedArgs != NULL)) { + CObjC_CoerceMethodArgs(meth, namedArgs, unnamedArgs); + sel = CObjC_MakeSelector(meth); + break; + } + } + } + + if (!meth) + CError_Warning(CErrorStr304); + } + + if (!meth) { + if ((sel = CObjC_FindKeyArgSelector(namedArgs))) { + for (methlist = sel->methods; methlist; methlist = methlist->next) { + if (!methlist->method->is_class_method) { + if (meth) + break; + meth = methlist->method; + } + } + + if (!meth) { + for (methlist = sel->methods; methlist; methlist = methlist->next) { + if (methlist->method->is_class_method) { + if (meth) + break; + meth = methlist->method; + } + } + } + + if (meth) { + if (methlist) + CError_Warning(CErrorStr305, meth, methlist->method); + + if (CObjC_SelectorCompare(meth, namedArgs, unnamedArgs != NULL)) { + CObjC_CoerceMethodArgs(meth, namedArgs, unnamedArgs); + } else { + CError_Warning(CErrorStr304); + } + } else { + CError_Error(CErrorStr306); + } + } else { + CError_Error(CErrorStr306); + } + } + } + + if (meth) { + methodtype = CObjC_GetMethodFuncType(meth); + sendMsgFunc = CObjC_FindSendMessageRTFunc(isSuper, CMach_GetFunctionResultClass(methodtype) > 0); + + if (isSuper) { + ENode *temp; + ENode *indirect; + ENode *ass; + ENode *tempCopy; + ENode *classObjRef; + + temp = CExpr_NewETEMPNode(CDecl_NewStructType(8, 4), 1); + + indirect = makemonadicnode(temp, EINDIRECT); + indirect->rtype = TYPE(&void_ptr); + + objexpr = makediadicnode(indirect, objexpr, EASS); + + tempCopy = lalloc(sizeof(ENode)); + *tempCopy = *temp; + + indirect = makediadicnode(tempCopy, intconstnode(TYPE(&stunsignedlong), 4), EADD); + indirect = makemonadicnode(indirect, EINDIRECT); + indirect->rtype = TYPE(&void_ptr); + + classObjRef = create_objectrefnode(tclass->objcinfo->classobject); + classObjRef = makediadicnode(classObjRef, intconstnode(TYPE(&stunsignedlong), 4), EADD); + classObjRef = makemonadicnode(classObjRef, EINDIRECT); + ass = makediadicnode(indirect, classObjRef, EASS); + + objexpr = makediadicnode(objexpr, ass, ECOMMA); + + tempCopy = lalloc(sizeof(ENode)); + *tempCopy = *temp; + + objexpr = makediadicnode(objexpr, tempCopy, ECOMMA); + objexpr->rtype = temp->rtype; + } + + callexpr = lalloc(sizeof(ENode)); + callexpr->type = EFUNCCALL; + callexpr->cost = 200; + callexpr->rtype = meth->return_type; + callexpr->flags = meth->return_qual & ENODE_FLAG_QUALS; + callexpr->data.funccall.funcref = create_objectrefnode(sendMsgFunc); + callexpr->data.funccall.functype = methodtype; + CError_ASSERT(3286, IS_TYPE_FUNC(callexpr->data.funccall.functype)); + + arg = callexpr->data.funccall.args = lalloc(sizeof(ENodeList)); + arg->node = objexpr; + + arg = arg->next = lalloc(sizeof(ENodeList)); + arg->node = create_objectnode(CObjC_GetSelectorObject(sel)); + + for (namedArg = namedArgs; namedArg; namedArg = namedArg->next) { + if (namedArg->expr) { + arg = arg->next = lalloc(sizeof(ENodeList)); + arg->node = namedArg->expr; + } + } + + arg->next = unnamedArgs; + return CExpr_AdjustFunctionCall(callexpr); + } else { + return nullnode(); + } +} + +ENode *CObjC_ParseMessageExpression(void) { + ENode *objexpr; + TypeClass *tclass; + Boolean isSuper; + ENodeList *unnamedArgs; + ObjCNamedArg *namedArgs; + ObjCNamedArg *lastNamedArg; + ENode *callexpr; + UInt8 calltype; + NameSpaceObjectList *list; + + isSuper = 0; + tclass = NULL; + + switch ((tk = lex())) { + case TK_IDENTIFIER: + if (!strcmp(tkidentifier->name, "super")) { + case TK_SUPER: + objexpr = CClass_CreateThisSelfExpr(); + if (!objexpr || !cscope_currentclass->bases) { + CError_Error(CErrorStr302); + objexpr = nullnode(); + } else { + tclass = cscope_currentclass; + isSuper = 1; + } + + if (cscope_is_member_func) + calltype = 0; + else + calltype = 1; + tk = lex(); + break; + } + + if ((list = CScope_FindName(cscope_root, tkidentifier)) && list->object->otype == OT_TYPE) { + tclass = TYPE_CLASS(OBJ_TYPE(list->object)->type); + if (IS_TYPE_CLASS(tclass) && tclass->objcinfo) { + calltype = 1; + objexpr = create_objectnode(CObjC_GetClassRefObject(tclass)); + objexpr->rtype = CDecl_NewPointerType(TYPE(tclass)); + tk = lex(); + break; + } + } + + tclass = NULL; + + default: + objexpr = expression(); + if (CObjC_IsType_id(objexpr->rtype)) { + calltype = 2; + break; + } + + if (!IS_TYPE_POINTER_ONLY(objexpr->rtype) || !IS_TYPE_OBJC_CLASS(TPTR_TARGET(objexpr->rtype))) { + CError_Error(CErrorStr303); + objexpr = nullnode(); + calltype = 2; + break; + } + + if ( + cscope_currentclass == TYPE_CLASS(TPTR_TARGET(objexpr->rtype)) && + !cscope_is_member_func && + ENODE_IS_INDIRECT_TO(objexpr, EOBJREF) && + objexpr->data.monadic->data.objref->name == self_name_node + ) + calltype = 1; + else + calltype = 0; + + tclass = TYPE_CLASS(TPTR_TARGET(objexpr->rtype)); + } + + lastNamedArg = lalloc(sizeof(ObjCNamedArg)); + memclrw(lastNamedArg, sizeof(ObjCNamedArg)); + + namedArgs = lastNamedArg; + unnamedArgs = NULL; + + while (1) { + CObjC_TranslateSelectorToken(); + + if (tk == TK_IDENTIFIER) { + lastNamedArg->name = tkidentifier; + if ((tk = lex()) == ']' && namedArgs == lastNamedArg) + break; + } + + if (tk != ':') { + CError_Error(CErrorStr141); + return nullnode(); + } + + tk = lex(); + lastNamedArg->expr = assignment_expression(); + + if (tk == ']') + break; + + if (tk == ',') { + tk = lex(); + unnamedArgs = CExpr_ScanExpressionList(0); + break; + } + + lastNamedArg->next = lalloc(sizeof(ObjCNamedArg)); + memclrw(lastNamedArg->next, sizeof(ObjCNamedArg)); + lastNamedArg = lastNamedArg->next; + } + + callexpr = CObjC_MakeSendMsgExpr(objexpr, tclass, namedArgs, unnamedArgs, calltype, isSuper); + tk = lex(); + return callexpr; +} + +ENode *CObjC_ParseEncodeExpression(void) { + ENode *expr; + char *str; + Type *type; + UInt32 qual; + + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + + CObjC_ParseTypeName(&type, &qual); + str = CObjC_EncodeTypeString(type, qual); + + expr = lalloc(sizeof(ENode)); + expr->type = ESTRINGCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = CDecl_NewArrayType(TYPE(&stchar), strlen(str) + 1); + expr->data.string.size = expr->rtype->size; + expr->data.string.data = str; + expr->data.string.ispascal = 0; + + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + + return expr; +} + +ENode *CObjC_ParseAtExpression(void) { + TypeClass *strclass; + OLinkList *refs; + OLinkList *ref; + Object *object; + ENode *expr; + NameSpaceObjectList *list; + UInt32 data[3]; + char buf[16]; + + if ((tk = lex()) == TK_STRING) { + if ((strclass = CObjC_FindObjCClass(GetHashNameNodeExport("NSConstantString"), 1))) { + refs = NULL; + + data[0] = CTool_EndianConvertWord32(0); + if ((list = CScope_GetLocalObject(cscope_root, GetHashNameNodeExport("_NSConstantStringClassReference")))) { + object = OBJECT(list->object); + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = object; + ref->offset = 0; + ref->somevalue = 0; + } else { + CError_Error(CErrorStr140, "_NSConstantStringClassReference"); + tk = lex(); + return nullnode(); + } + + data[1] = CTool_EndianConvertWord32(0); + + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + ref->obj = CInit_DeclareString(tkstring, tksize, 0, 0); + ref->offset = 4; + ref->somevalue = 0; + + data[2] = CTool_EndianConvertWord32(tksize - 1); + + sprintf(buf, "%ld", cobjc_stringcount++); + + object = CObjC_MakeObject("L_NSConstantString_", buf, sizeof(data)); + object->type = TYPE(strclass); + object->sclass = TK_STATIC; + object->section = SECT_OBJC_CSTRING_OBJECT; + CInit_DeclareData(object, data, refs, object->type->size); + + expr = create_objectrefnode(object); + } else { + expr = nullnode(); + } + + tk = lex(); + } else { + CError_Error(CErrorStr101); + expr = nullnode(); + } + + return expr; +} + +ENode *CObjC_ParseProtocolExpression(void) { + ObjCProtocol *protocol; + ENode *expr; + + if ((tk = lex()) == '(') { + if ((tk = lex()) == TK_IDENTIFIER) { + if ((protocol = CObjC_FindProtocol(tkidentifier))) { + expr = create_objectrefnode(CObjC_GetProtocolObject(protocol)); + + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + + return expr; + } + } else { + CError_Error(CErrorStr107); + } + } else { + CError_Error(CErrorStr114); + } + + return nullnode(); +} + +ENode *CObjC_ParseSelectorExpression(void) { + HashNameNode *name; + ObjCSelector *selector; + ENode *expr; + + if ((tk = lex()) == '(') { + name_mangle_list.size = 0; + while (1) { + tk = lex(); + + if (tk == TK_IDENTIFIER) { + AppendGListName(&name_mangle_list, tkidentifier->name); + tk = lex(); + } + + if (tk == ')') { + if (name_mangle_list.size == 0) + CError_Error(CErrorStr107); + tk = lex(); + break; + } + + if (tk == ':') { + AppendGListByte(&name_mangle_list, ':'); + } else { + CError_Error(CErrorStr115); + break; + } + } + + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + + selector = CObjC_FindSelector(name); + if (!selector) + selector = CObjC_NewSelector(name); + + expr = create_objectnode(CObjC_GetSelectorObject(selector)); + expr->rtype = CObjC_FindObjCType_SEL(); + + return expr; + } else { + CError_Error(CErrorStr114); + return nullnode(); + } +} diff --git a/compiler_and_linker/unsorted/CObjCModern.c b/compiler_and_linker/unsorted/CObjCModern.c index e69de29..b9695c3 100644 --- a/compiler_and_linker/unsorted/CObjCModern.c +++ b/compiler_and_linker/unsorted/CObjCModern.c @@ -0,0 +1,181 @@ +#include "compiler/CObjCModern.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CObjC.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CompilerTools.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" + +static ObjCNamedArg *CObjC_GetKeywordArgList(HashNameNode *name, Boolean *isSingleArg) { + ObjCNamedArg *first; + ObjCNamedArg *arg; + char *start; + char *p; + + start = name->name; + first = NULL; + + while (1) { + for (p = start; *p != '_'; p++) { + if (*p == 0) { + if (!first) { + first = lalloc(sizeof(ObjCNamedArg)); + memclrw(first, sizeof(ObjCNamedArg)); + + first->name = name; + + *isSingleArg = 1; + return first; + } + + arg->next = lalloc(sizeof(ObjCNamedArg)); + arg = arg->next; + + arg->next = NULL; + arg->name = GetHashNameNode(start); + arg->expr = NULL; + + *isSingleArg = 0; + return first; + } + } + + if (first) { + arg->next = lalloc(sizeof(ObjCNamedArg)); + arg = arg->next; + } else { + arg = lalloc(sizeof(ObjCNamedArg)); + first = arg; + } + + *p = 0; + arg->next = NULL; + arg->name = GetHashNameNode(start); + arg->expr = NULL; + *p = '_'; + + if (*(++p) == 0) { + *isSingleArg = 0; + return first; + } + + start = p; + } +} + +static ENode *CObjC_ModernSendMessage(TypeClass *tclass, ENode *expr, HashNameNode *name, Boolean isSuper) { + ENode *callexpr; + ObjCNamedArg *args; + ObjCNamedArg *arg; + ENodeList *unnamedArgs; + Boolean isSingleArg; + + CError_ASSERT(92, ENODE_IS(expr, EINDIRECT)); + expr = expr->data.monadic; + + args = CObjC_GetKeywordArgList(name, &isSingleArg); + + if ((tk = lex()) == ')') { + if (!isSingleArg) { + CError_Error(CErrorStr162); + return nullnode(); + } + + callexpr = CObjC_MakeSendMsgExpr(expr, tclass, args, NULL, 1, isSuper); + tk = lex(); + return callexpr; + } + + if (isSingleArg) { + CError_Error(CErrorStr162); + return nullnode(); + } + + unnamedArgs = NULL; + arg = args; + while (1) { + arg->expr = assignment_expression(); + + if (tk == ')') { + if (arg->next) { + CError_Error(CErrorStr162); + return nullnode(); + } + break; + } + + if (tk != ',') { + CError_Error(CErrorStr141); + return nullnode(); + } + + tk = lex(); + arg = arg->next; + + if (!arg) { + unnamedArgs = CExpr_ScanExpressionList(0); + break; + } + } + + callexpr = CObjC_MakeSendMsgExpr(expr, tclass, args, unnamedArgs, 1, isSuper); + tk = lex(); + return callexpr; +} + +ENode *CObjC_CheckModernSendMessage(TypeClass *tclass, ENode *expr) { + HashNameNode *name; + SInt32 state; + + CPrep_TokenStreamGetState(&state); + + tk = lex(); + CObjC_TranslateSelectorToken(); + if (tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "super")) { + if (lex() == TK_COLON_COLON) { + tk = lex(); + CObjC_TranslateSelectorToken(); + + name = tkidentifier; + if (tk == TK_IDENTIFIER && lex() == '(') + return CObjC_ModernSendMessage(tclass, expr, name, 1); + } + } else { + name = tkidentifier; + if (lex() == '(') + return CObjC_ModernSendMessage(tclass, expr, name, 0); + } + } + + CPrep_TokenStreamSetState(&state); + return NULL; +} + +ENode *CObjC_New(TypeClass *tclass) { + ObjCNamedArg *arg; + ENode *objexpr; + + arg = lalloc(sizeof(ObjCNamedArg)); + memclrw(arg, sizeof(ObjCNamedArg)); + + arg->name = GetHashNameNode("alloc"); + + objexpr = create_objectrefnode(tclass->objcinfo->classobject); + + return CObjC_MakeSendMsgExpr(objexpr, tclass, arg, NULL, 1, 0); +} + +ENode *CObjC_Delete(TypeClass *tclass, ENode *objexpr) { + ObjCNamedArg *arg; + + arg = lalloc(sizeof(ObjCNamedArg)); + memclrw(arg, sizeof(ObjCNamedArg)); + + arg->name = GetHashNameNode("dealloc"); + + return CObjC_MakeSendMsgExpr(objexpr, tclass, arg, NULL, 0, 0); +} diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c index b7637c8..8fd01ae 100644 --- a/compiler_and_linker/unsorted/COptimizer.c +++ b/compiler_and_linker/unsorted/COptimizer.c @@ -190,12 +190,7 @@ static short cse_cost(COptCSE *cse) { if (ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) cost = 2; } - //cost = (!copts.optimize_for_size && ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) ? 2 : 1; return cse_cost(cse->left) + cse_cost(cse->right) + cost; - //return - // ((!copts.optimize_for_size && ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) ? 2 : 1) + - // cse_cost(cse->left) + - // cse_cost(cse->right); } return 0; @@ -237,8 +232,7 @@ static void cse_remove(void) { if (cse->replaced) { replaces = 0; cse_replace(cse->replaced, cse); -#line 348 - CError_ASSERT(replaces >= 1); + CError_ASSERT(348, replaces >= 1); cse_found = 1; did_replacement = 1; cse_update_usages(cse, cse->x1C); @@ -304,12 +298,10 @@ static void cse_remove(void) { cse_replace(expr2, cse); cse->replaced = expr2; - if (replaces < 2) { -#line 390 - CError_FATAL(); - } else { + if (replaces < 2) + CError_FATAL(390); + else cse_found = 1; - } expr4 = lalloc(sizeof(ENode)); *expr4 = *cse->mexpr; @@ -408,8 +400,7 @@ static COptCSE *cse_add_monadic_node(ENode *outer, COptCSE *innercse) { for (cse = csenodes[outer->type]; cse; cse = cse->next) { if (cse->left == innercse && cse->expr->rtype == outer->rtype) { -#line 524 - CError_ASSERT(cse->expr != outer); + CError_ASSERT(524, cse->expr != outer); cse->x1C++; return cse; } @@ -430,8 +421,7 @@ static COptCSE *cse_add_typecon_node(ENode *outer, COptCSE *innercse) { for (cse = csenodes[outer->type]; cse; cse = cse->next) { if (cse->left == innercse && cse->expr->rtype == outer->rtype) { -#line 552 - CError_ASSERT(cse->expr != outer); + CError_ASSERT(552, cse->expr != outer); cse->x1C++; return cse; } @@ -452,8 +442,7 @@ static COptCSE *cse_add_diadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rig for (cse = csenodes[outer->type]; cse; cse = cse->next) { if (cse->left == leftcse && cse->right == rightcse) { -#line 581 - CError_ASSERT(cse->expr != outer); + CError_ASSERT(581, cse->expr != outer); cse->x1C++; return cse; } @@ -475,8 +464,7 @@ static COptCSE *cse_add_commdiadic_node(ENode *outer, COptCSE *leftcse, COptCSE for (cse = csenodes[outer->type]; cse; cse = cse->next) { if ((cse->left == leftcse && cse->right == rightcse) || (cse->left == rightcse && cse->right == leftcse)) { -#line 612 - CError_ASSERT(cse->expr != outer); + CError_ASSERT(612, cse->expr != outer); cse->x1C++; return cse; } @@ -527,8 +515,7 @@ static void cse_mem_modify(void) { for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) { if (ENODE_IS(cse->expr->data.monadic, EOBJREF)) { Object *obj = cse->expr->data.monadic->data.objref; -#line 672 - CError_ASSERT(obj->datatype != DALIAS); + CError_ASSERT(672, obj->datatype != DALIAS); if (obj->datatype == DLOCAL && !obj->u.var.info->noregister) continue; } @@ -633,8 +620,7 @@ static COptCSE *cse_expression(ENode *expr) { case EPREDEC: save = mexpr; mexpr = expr; -#line 816 - CError_ASSERT(ENODE_IS(expr->data.monadic, EINDIRECT)); + CError_ASSERT(816, ENODE_IS(expr->data.monadic, EINDIRECT)); cse_expression(expr->data.monadic->data.monadic); cse_modify_expression(expr->data.monadic); @@ -697,8 +683,7 @@ static COptCSE *cse_expression(ENode *expr) { case EANDASS: case EXORASS: case EORASS: -#line 887 - CError_ASSERT(ENODE_IS(expr->data.diadic.left, EINDIRECT)); + CError_ASSERT(887, ENODE_IS(expr->data.diadic.left, EINDIRECT)); save = mexpr; mexpr = expr; cse_expression(expr->data.diadic.right); @@ -754,12 +739,10 @@ static COptCSE *cse_expression(ENode *expr) { return NULL; case EPRECOMP: -#line 948 - CError_FATAL(); + CError_FATAL(948); default: -#line 951 - CError_FATAL(); + CError_FATAL(951); return NULL; } } @@ -1085,8 +1068,7 @@ static void CheckExpr(ENode *expr) { case EVECTOR128CONST: return; default: -#line 1332 - CError_FATAL(); + CError_FATAL(1332); } } } @@ -1347,8 +1329,7 @@ static void BasicBlockAnalyze(Statement *stmt) { } } -#line 1602 - CError_ASSERT(iblock); + CError_ASSERT(1602, iblock); } } @@ -1480,8 +1461,7 @@ static void optimizeswitch(Statement *stmt) { SwitchCase *swcase; info = (SwitchInfo *) stmt->label; -#line 1746 - CError_ASSERT(info && info->cases && info->defaultlabel); + CError_ASSERT(1746, info && info->cases && info->defaultlabel); info->defaultlabel = finallabel(info->defaultlabel, stmt); for (swcase = info->cases; swcase; swcase = swcase->next) @@ -1576,8 +1556,7 @@ static void optimizebranches(Statement *stmt) { void SetVarUsage(Object *obj, Boolean noregister) { VarInfo *vi; -#line 1875 - CError_ASSERT(obj->datatype != DALIAS); + CError_ASSERT(1875, obj->datatype != DALIAS); if (obj->datatype == DLOCAL || obj->datatype == DNONLAZYPTR) { vi = obj->u.var.info; @@ -1689,8 +1668,7 @@ static void checkexpression(ENode *expr) { case ESTRINGCONST: return; default: -#line 1998 - CError_FATAL(); + CError_FATAL(1998); } } } @@ -1756,8 +1734,7 @@ static void colorcode(Statement *stmt) { case ST_BEGINLOOP: break; default: -#line 2096 - CError_FATAL(); + CError_FATAL(2096); } stmt = stmt->next; } @@ -1820,8 +1797,7 @@ static void COpt_Optimize(Object *obj, Statement *stmt) { } static void COpt_ELABELCallBack(ENode *expr) { -#line 2195 - CError_ASSERT(expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL); + CError_ASSERT(2195, expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL); expr->data.label->stmt->flags |= StmtFlag_1; } diff --git a/compiler_and_linker/unsorted/CPrec.c b/compiler_and_linker/unsorted/CPrec.c index a879df6..f835c6c 100644 --- a/compiler_and_linker/unsorted/CPrec.c +++ b/compiler_and_linker/unsorted/CPrec.c @@ -1437,10 +1437,10 @@ static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { CPrec_AppendData(tclass, sizeof(TemplClass)); if (TEMPL_CLASS(tclass)->next) hasNextTempl = 1; - if (TEMPL_CLASS(tclass)->templ__parent) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ__parent)); - if (TEMPL_CLASS(tclass)->x3A_maybe_parentinst) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->x3A_maybe_parentinst, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->x3A_maybe_parentinst)); + if (TEMPL_CLASS(tclass)->templ_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ_parent)); + if (TEMPL_CLASS(tclass)->inst_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->inst_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->inst_parent)); if (TEMPL_CLASS(tclass)->templ__params) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__params, CPrec_GetTemplateParamPatch(TEMPL_CLASS(tclass)->templ__params)); if (TEMPL_CLASS(tclass)->members) @@ -1458,8 +1458,8 @@ static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { CPrec_AppendData(tclass, sizeof(TemplClassInst)); if (TEMPL_CLASS_INST(tclass)->next) hasNextTemplInst = 1; - if (TEMPL_CLASS_INST(tclass)->x36) - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->x36, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->x36)); + if (TEMPL_CLASS_INST(tclass)->parent) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->parent)); if (TEMPL_CLASS_INST(tclass)->templ) CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->templ, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->templ)); if (TEMPL_CLASS_INST(tclass)->inst_args) diff --git a/compiler_and_linker/unsorted/CPreprocess.c b/compiler_and_linker/unsorted/CPreprocess.c index e69de29..116d5dc 100644 --- a/compiler_and_linker/unsorted/CPreprocess.c +++ b/compiler_and_linker/unsorted/CPreprocess.c @@ -0,0 +1,676 @@ +#include "compiler/CPreprocess.h" +#include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CompilerTools.h" +#include "cos.h" + +void CPrep_PreprocessDumpNewLine(void) { + if (copts.line_prepdump && pplist.data && filesp >= 0) + AppendGListData(&pplist, "\r", 1); +} + +void CPrep_PreprocessDumpFileInfo(Boolean flag) { + char linebuf[512]; + int size; + SInt16 tmp16; + SInt32 tmp32; + Str255 filename; + + if (pplist.data && filesp >= 0) { + if (nlflag && flag && pplist.size > 0) + AppendGListName(&pplist, "\r"); + + if (copts.line_prepdump) + size = sprintf(linebuf, "#line %ld\t\"", linenumber); + else + size = sprintf(linebuf, "/* #line %ld\t\"", linenumber); + AppendGListData(&pplist, linebuf, size); + + if (copts.fullpath_prepdump) { + if (prep_file->nameNode) { + AppendGListData(&pplist, prep_file->nameNode->name, strlen(prep_file->nameNode->name)); + } else { + COS_FileGetPathName(linebuf, &prep_file->textfile, &tmp32); + AppendGListData(&pplist, linebuf, strlen(linebuf)); + } + } else { + if (prep_file->nameNode) { + char *work = prep_file->nameNode->name + strlen(prep_file->nameNode->name); + while (work > prep_file->nameNode->name && !strchr("/\\:", work[-1])) + work--; + + AppendGListData(&pplist, work, strlen(work)); + } else { + COS_FileGetFSSpecInfo(&prep_file->textfile, &tmp16, &tmp32, filename); + AppendGListData(&pplist, &filename[1], filename[0]); + } + } + + size = sprintf(linebuf, "\"\t/* stack depth %ld */", filesp); + AppendGListData(&pplist, linebuf, size); + + if (copts.line_prepdump && flag) + CPrep_PreprocessDumpNewLine(); + + nlflag = 1; + } +} + +static void CPrep_DumpWString(UInt16 *str, short len) { + int divisor; + int i; + + while (len--) { + if (*str < 32) { + AppendGListByte(&pplist, '\\'); + switch (*str) { + case 7: + AppendGListByte(&pplist, 'a'); + break; + case 8: + AppendGListByte(&pplist, 'b'); + break; + case 27: + AppendGListByte(&pplist, 'e'); + break; + case 12: + AppendGListByte(&pplist, 'f'); + break; + case 10: + AppendGListByte(&pplist, 'n'); + break; + case 13: + AppendGListByte(&pplist, 'r'); + break; + case 9: + AppendGListByte(&pplist, 't'); + break; + case 11: + AppendGListByte(&pplist, 'v'); + break; + default: + if (*str >= 8) + AppendGListByte(&pplist, '0' + (*str / 8)); + AppendGListByte(&pplist, '0' + (*str % 8)); + } + } else if (*str > 255) { + AppendGListByte(&pplist, '\\'); + AppendGListByte(&pplist, 'x'); + + divisor = 0x1000; + for (i = 0; i < 4; i++) { + AppendGListByte(&pplist, "0123456789ABCDEF"[(*str / divisor) % 16]); + divisor /= 16; + } + } else { + switch (*str) { + case '"': + case '\\': + AppendGListByte(&pplist, '\\'); + default: + AppendGListByte(&pplist, *str); + } + } + str++; + } +} + +static void CPrep_DumpString(UInt8 *str, short len) { + while (len--) { + if (*str < 32) { + AppendGListByte(&pplist, '\\'); + switch (*str) { + case 7: + AppendGListByte(&pplist, 'a'); + break; + case 8: + AppendGListByte(&pplist, 'b'); + break; + case 12: + AppendGListByte(&pplist, 'f'); + break; + case 10: + AppendGListByte(&pplist, 'n'); + break; + case 13: + AppendGListByte(&pplist, 'r'); + break; + case 9: + AppendGListByte(&pplist, 't'); + break; + case 11: + AppendGListByte(&pplist, 'v'); + break; + default: + if (*str >= 8) + AppendGListByte(&pplist, '0' + (*str / 8)); + AppendGListByte(&pplist, '0' + (*str % 8)); + } + } else { + switch (*str) { + case '"': + case '\\': + AppendGListByte(&pplist, '\\'); + default: + AppendGListByte(&pplist, *str); + } + } + str++; + } +} + +void CPrep_Preprocess(void) { + short innertoken; + short token; + char startToken; + char endToken; + int depth; + Boolean save_asmpoundcomment; // r16 + Boolean save_cplusplus; // r15 + char *p; + + startToken = 0; + depth = 0; + + if (InitGList(&pplist, 10000)) + CError_NoMem(); + + nlflag = 0; + spaceskip = 0; + + if ((token = lex())) { + do { + if (nlflag) { + if (!copts.line_prepdump) + AppendGListData(&pplist, "\r", 1); + } else { + if (spaceskip) + AppendGListByte(&pplist, ' '); + } + + while (1) { + switch ((innertoken = token)) { + case '(': + case ')': + case '{': + case '}': + AppendGListByte(&pplist, token); + if (cprep_nostring) { + if (innertoken == startToken) { + depth++; + } else if (innertoken == endToken) { + if (--depth == 0) { + cprep_nostring = 0; + in_assembler = 0; + copts.cplusplus = save_cplusplus; + copts.asmpoundcomment = save_asmpoundcomment; + } + } + } + break; + + case TK_INTCONST: + case TK_FLOATCONST: + if (tokenstacklevel > 0) + p = macropos; + else + p = prep_file_start + ts_current[-1].tokenoffset; + AppendGListData(&pplist, p, pos - p); + break; + + case TK_IDENTIFIER: + AppendGListData(&pplist, tkidentifier->name, strlen(tkidentifier->name)); + break; + + case TK_AUTO: + AppendGListData(&pplist, "auto", 4); + break; + case TK_REGISTER: + AppendGListData(&pplist, "register", 8); + break; + case TK_STATIC: + AppendGListData(&pplist, "static", 6); + break; + case TK_EXTERN: + AppendGListData(&pplist, "extern", 6); + break; + case TK_TYPEDEF: + AppendGListData(&pplist, "typedef", 7); + break; + case TK_INLINE: + AppendGListData(&pplist, "inline", 6); + break; + case TK_VOID: + AppendGListData(&pplist, "void", 4); + break; + case TK_CHAR: + AppendGListData(&pplist, "char", 4); + break; + case TK_SHORT: + AppendGListData(&pplist, "short", 5); + break; + case TK_INT: + AppendGListData(&pplist, "int", 3); + break; + case TK_LONG: + AppendGListData(&pplist, "long", 4); + break; + case TK_FLOAT: + AppendGListData(&pplist, "float", 5); + break; + case TK_DOUBLE: + AppendGListData(&pplist, "double", 6); + break; + case TK_SIGNED: + AppendGListData(&pplist, "signed", 6); + break; + case TK_UNSIGNED: + AppendGListData(&pplist, "unsigned", 8); + break; + case TK_STRUCT: + AppendGListData(&pplist, "struct", 6); + break; + case TK_UNION: + AppendGListData(&pplist, "union", 5); + break; + case TK_ENUM: + AppendGListData(&pplist, "enum", 4); + break; + case TK_CLASS: + AppendGListData(&pplist, "class", 5); + break; + case TK_CONST: + AppendGListData(&pplist, "const", 5); + break; + case TK_VOLATILE: + AppendGListData(&pplist, "volatile", 8); + break; + case TK_PASCAL: + AppendGListData(&pplist, "pascal", 6); + break; + case TK_UU_FAR: + AppendGListData(&pplist, "__far", 5); + break; + case TK_ONEWAY: + AppendGListData(&pplist, "oneway", 6); + break; + case TK_IN: + AppendGListData(&pplist, "in", 2); + break; + case TK_OUT: + AppendGListData(&pplist, "out", 3); + break; + case TK_INOUT: + AppendGListData(&pplist, "inout", 5); + break; + case TK_BYCOPY: + AppendGListData(&pplist, "bycopy", 6); + break; + case TK_BYREF: + AppendGListData(&pplist, "byref", 5); + break; + case TK_ASM: + AppendGListData(&pplist, "asm", 3); + endToken = 0; + startToken = 0; + AppendGListByte(&pplist, ' '); + token = lex(); + if (token == TK_VOLATILE || (token == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { + AppendGListData(&pplist, "volatile", 8); + token = lex(); + } + if (token) { + if (token < ' ' || token > 255) + continue; + AppendGListByte(&pplist, token); + + if (token == '(') { + startToken = '('; + endToken = ')'; + } else if (token == '{') { + startToken = '{'; + endToken = '}'; + } else { + continue; + } + + cprep_nostring = 1; + in_assembler = 1; + depth = 1; + save_asmpoundcomment = copts.asmpoundcomment; + save_cplusplus = copts.cplusplus; + + token = lex(); + if (token == '"') { + AppendGListByte(&pplist, token); + copts.cplusplus = 0; + copts.asmpoundcomment = 1; + break; + } else if (token == 0) { + break; + } + continue; + } + break; + + case TK_CASE: + AppendGListData(&pplist, "case", 4); + break; + case TK_DEFAULT: + AppendGListData(&pplist, "default", 7); + break; + case TK_IF: + AppendGListData(&pplist, "if", 2); + break; + case TK_ELSE: + AppendGListData(&pplist, "else", 4); + break; + case TK_SWITCH: + AppendGListData(&pplist, "switch", 6); + break; + case TK_WHILE: + AppendGListData(&pplist, "while", 5); + break; + case TK_DO: + AppendGListData(&pplist, "do", 2); + break; + case TK_FOR: + AppendGListData(&pplist, "for", 3); + break; + case TK_GOTO: + AppendGListData(&pplist, "goto", 4); + break; + case TK_CONTINUE: + AppendGListData(&pplist, "continue", 8); + break; + case TK_BREAK: + AppendGListData(&pplist, "break", 5); + break; + case TK_RETURN: + AppendGListData(&pplist, "return", 6); + break; + case TK_SIZEOF: + AppendGListData(&pplist, "sizeof", 6); + break; + case TK_CATCH: + AppendGListData(&pplist, "catch", 5); + break; + case TK_DELETE: + AppendGListData(&pplist, "delete", 6); + break; + case TK_FRIEND: + AppendGListData(&pplist, "friend", 6); + break; + case TK_NEW: + AppendGListData(&pplist, "new", 3); + break; + case TK_OPERATOR: + AppendGListData(&pplist, "operator", 8); + break; + case TK_PRIVATE: + AppendGListData(&pplist, "private", 7); + break; + case TK_PROTECTED: + AppendGListData(&pplist, "protected", 9); + break; + case TK_PUBLIC: + AppendGListData(&pplist, "public", 6); + break; + case TK_TEMPLATE: + AppendGListData(&pplist, "template", 8); + break; + case TK_THIS: + AppendGListData(&pplist, "this", 4); + break; + case TK_THROW: + AppendGListData(&pplist, "throw", 5); + break; + case TK_TRY: + AppendGListData(&pplist, "try", 3); + break; + case TK_VIRTUAL: + AppendGListData(&pplist, "virtual", 7); + break; + case TK_INHERITED: + AppendGListData(&pplist, "inherited", 9); + break; + case TK_CONST_CAST: + AppendGListData(&pplist, "const_cast", 10); + break; + case TK_DYNAMIC_CAST: + AppendGListData(&pplist, "dynamic_cast", 12); + break; + case TK_EXPLICIT: + AppendGListData(&pplist, "explicit", 8); + break; + case TK_MUTABLE: + AppendGListData(&pplist, "mutable", 7); + break; + case TK_NAMESPACE: + AppendGListData(&pplist, "namespace", 9); + break; + case TK_REINTERPRET_CAST: + AppendGListData(&pplist, "reinterpret_cast", 16); + break; + case TK_STATIC_CAST: + AppendGListData(&pplist, "static_cast", 11); + break; + case TK_USING: + AppendGListData(&pplist, "using", 5); + break; + case TK_WCHAR_T: + AppendGListData(&pplist, "wchar_t", 7); + break; + case TK_TYPENAME: + AppendGListData(&pplist, "typename", 8); + break; + case TK_TRUE: + AppendGListData(&pplist, "true", 4); + break; + case TK_FALSE: + AppendGListData(&pplist, "false", 5); + break; + case TK_TYPEID: + AppendGListData(&pplist, "typeid", 6); + break; + case TK_EXPORT: + AppendGListData(&pplist, "export", 6); + break; + case TK_UU_STDCALL: + AppendGListData(&pplist, "__stdcall", 9); + break; + case TK_UU_CDECL: + AppendGListData(&pplist, "__cdecl", 7); + break; + case TK_UU_FASTCALL: + AppendGListData(&pplist, "__fastcall", 10); + break; + case TK_UU_DECLSPEC: + AppendGListData(&pplist, "__declspec", 10); + break; + case TK_MULT_ASSIGN: + AppendGListData(&pplist, "*=", 2); + break; + case TK_DIV_ASSIGN: + AppendGListData(&pplist, "/=", 2); + break; + case TK_MOD_ASSIGN: + AppendGListData(&pplist, "%=", 2); + break; + case TK_ADD_ASSIGN: + AppendGListData(&pplist, "+=", 2); + break; + case TK_SUB_ASSIGN: + AppendGListData(&pplist, "-=", 2); + break; + case TK_SHL_ASSIGN: + AppendGListData(&pplist, "<<=", 3); + break; + case TK_SHR_ASSIGN: + AppendGListData(&pplist, ">>=", 3); + break; + case TK_AND_ASSIGN: + AppendGListData(&pplist, "&=", 2); + break; + case TK_XOR_ASSIGN: + AppendGListData(&pplist, "^=", 2); + break; + case TK_OR_ASSIGN: + AppendGListData(&pplist, "|=", 2); + break; + case TK_LOGICAL_OR: + AppendGListData(&pplist, "||", 2); + break; + case TK_LOGICAL_AND: + AppendGListData(&pplist, "&&", 2); + break; + case TK_LOGICAL_EQ: + AppendGListData(&pplist, "==", 2); + break; + case TK_LOGICAL_NE: + AppendGListData(&pplist, "!=", 2); + break; + case TK_LESS_EQUAL: + AppendGListData(&pplist, "<=", 2); + break; + case TK_GREATER_EQUAL: + AppendGListData(&pplist, ">=", 2); + break; + case TK_SHL: + AppendGListData(&pplist, "<<", 2); + break; + case TK_SHR: + AppendGListData(&pplist, ">>", 2); + break; + case TK_INCREMENT: + AppendGListData(&pplist, "++", 2); + break; + case TK_DECREMENT: + AppendGListData(&pplist, "--", 2); + break; + case TK_ARROW: + AppendGListData(&pplist, "->", 2); + break; + case TK_ELLIPSIS: + AppendGListData(&pplist, "...", 3); + break; + case TK_DOT_STAR: + AppendGListData(&pplist, ".*", 2); + break; + case TK_ARROW_STAR: + AppendGListData(&pplist, "->*", 3); + break; + case TK_COLON_COLON: + AppendGListData(&pplist, "::", 2); + break; + case TK_AT_INTERFACE: + AppendGListData(&pplist, "@interface", 10); + break; + case TK_AT_IMPLEMENTATION: + AppendGListData(&pplist, "@implementation", 15); + break; + case TK_AT_PROTOCOL: + AppendGListData(&pplist, "@protocol", 9); + break; + case TK_AT_END: + AppendGListData(&pplist, "@end", 4); + break; + case TK_AT_PRIVATE: + AppendGListData(&pplist, "@private", 8); + break; + case TK_AT_PROTECTED: + AppendGListData(&pplist, "@protected", 10); + break; + case TK_AT_PUBLIC: + AppendGListData(&pplist, "@public", 7); + break; + case TK_AT_CLASS: + AppendGListData(&pplist, "@class", 6); + break; + case TK_AT_SELECTOR: + AppendGListData(&pplist, "@selector", 9); + break; + case TK_AT_ENCODE: + AppendGListData(&pplist, "@encode", 7); + break; + case TK_AT_DEFS: + AppendGListData(&pplist, "@defs", 5); + break; + case TK_SELF: + AppendGListData(&pplist, "self", 4); + break; + case TK_SUPER: + AppendGListData(&pplist, "super", 5); + break; + case TK_BOOL: + if (!copts.cplusplus && copts.c9x) + AppendGListData(&pplist, "_Bool", 5); + else + AppendGListData(&pplist, "bool", 4); + break; + case TK_RESTRICT: + if (copts.c9x) + AppendGListData(&pplist, "restrict", 8); + else + AppendGListData(&pplist, "__restrict", 10); + break; + case TK_UU_VECTOR: + AppendGListData(&pplist, "__vector", 8); + break; + case TK_UU_TYPEOF_UU: + AppendGListData(&pplist, "__typeof__", 10); + break; + case TK_UU_ATTRIBUTE_UU: + AppendGListData(&pplist, "__attribute__", 13); + break; + case TK_UU_ALIGNOF_UU: + AppendGListData(&pplist, "__alignof__", 11); + break; + case TK_UU_UUIDOF: + AppendGListData(&pplist, "__uuidof", 8); + break; + case TK_U_COMPLEX: + AppendGListData(&pplist, "_Complex", 8); + break; + case TK_U_IMAGINARY: + AppendGListData(&pplist, "_Imaginary", 10); + break; + + case TK_STRING: + if (ispascalstring) { + AppendGListData(&pplist, "\"\\p", 3); + CPrep_DumpString((UInt8 *) tkstring + 1, tksize - 1); + } else { + AppendGListByte(&pplist, '"'); + CPrep_DumpString((UInt8 *) tkstring, tksize - 1); + } + AppendGListByte(&pplist, '"'); + break; + + case TK_STRING_WIDE: + AppendGListData(&pplist, "L\"", 2); + CPrep_DumpWString((UInt16 *) tkstring, (tksize / stwchar.size) - 1); + AppendGListByte(&pplist, '"'); + break; + + default: + if (token >= 32 && token <= 255) + AppendGListByte(&pplist, token); + else + CError_FATAL(563); + } + break; + } + + CPrep_TokenStreamFlush(); + nlflag = 0; + spaceskip = 0; + } while ((token = lex())); + } + + AppendGListByte(&pplist, 0); + COS_ResizeHandle(pplist.data, pplist.size); +} diff --git a/compiler_and_linker/unsorted/CRTTI.c b/compiler_and_linker/unsorted/CRTTI.c index e69de29..cc036fb 100644 --- a/compiler_and_linker/unsorted/CRTTI.c +++ b/compiler_and_linker/unsorted/CRTTI.c @@ -0,0 +1,940 @@ +#include "compiler/CRTTI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CPrep.h" + +typedef struct Offset { + struct Offset *next; + SInt32 offset; +} Offset; + +static Offset *crtti_offsets; +static OLinkList *crtti_olinks; + +// forward decls +static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual); + +typedef struct RTTISubClassList { + struct RTTISubClassList *next; + TypeClass *base; + SInt32 voffset; +} RTTISubClassList; + +typedef struct RTTIBaseList { + struct RTTIBaseList *next; + TypeClass *base; + RTTISubClassList *subclasses; + SInt32 voffset; + short numsubclasses; + Boolean x12; + Boolean x13; +} RTTIBaseList; + +static RTTIBaseList *CRTTI_CreateBaseList(TypeClass *tclass, TypeClass *tclassbase, RTTIBaseList *list, SInt32 voffset, Boolean flag) { + RTTIBaseList *scan; + ClassList *base; + Boolean flag27; + SInt32 newvoffset; + + if (tclass != tclassbase) { + flag27 = 0; + + for (scan = list; scan; scan = scan->next) { + if (scan->base == tclassbase) { + if (scan->voffset == voffset) { + if (!flag) + scan->x12 = 0; + flag27 = 0; + } else { + scan->x13 = 1; + flag27 = 1; + } + break; + } + } + + if (!scan || flag27) { + scan = lalloc(sizeof(RTTIBaseList)); + memclrw(scan, sizeof(RTTIBaseList)); + + scan->next = list; + list = scan; + scan->base = tclassbase; + scan->voffset = voffset; + scan->x12 = flag; + scan->x13 = flag27; + } + } + + for (base = tclassbase->bases; base; base = base->next) { + if (base->is_virtual) + newvoffset = CClass_VirtualBaseOffset(tclass, base->base); + else + newvoffset = voffset + base->offset; + + list = CRTTI_CreateBaseList(tclass, base->base, list, newvoffset, flag || base->access == ACCESSPRIVATE); + } + + return list; +} + +static void CRTTI_CreateSubClassList(TypeClass *tclass, RTTIBaseList *baselist, TypeClass *tclassbase, SInt32 voffset, Boolean flag) { + ClassList *base; + RTTISubClassList *scan; + SInt32 newvoffset; + + if (baselist->base != tclassbase) { + for (scan = baselist->subclasses; scan; scan = scan->next) { + if (scan->base == tclassbase && scan->voffset == voffset) + break; + } + + if (!scan) { + scan = lalloc(sizeof(RTTISubClassList)); + scan->next = baselist->subclasses; + baselist->subclasses = scan; + + scan->base = tclassbase; + scan->voffset = voffset; + baselist->numsubclasses++; + } + } + + for (base = tclassbase->bases; base; base = base->next) { + if (base->access == ACCESSPUBLIC) { + if (base->is_virtual) { + if (!flag) + continue; + newvoffset = CClass_VirtualBaseOffset(tclass, base->base); + } else { + newvoffset = voffset + base->offset; + } + + CRTTI_CreateSubClassList(tclass, baselist, base->base, newvoffset, flag); + } + } +} + +static Object *CRTTI_CreateBaseListObject(TypeClass *tclass) { + RTTIBaseList *baselist; + OLinkList *refs; + Object *object; + SInt32 *buf; + SInt32 size; + short count1; + short count2; + short total; + OLinkList *ref; + RTTIBaseList *scan; + RTTISubClassList *subclass; + SInt32 *work; + SInt32 *work2; + + baselist = CRTTI_CreateBaseList(tclass, tclass, NULL, 0, 0); + if (!baselist) + return NULL; + + count1 = 0; + count2 = 0; + total = 0; + + for (scan = baselist; scan; scan = scan->next) { + if (scan->x13 || scan->x12) { + CRTTI_CreateSubClassList(tclass, scan, scan->base, scan->voffset, scan->x13 == 0); + if (scan->numsubclasses) { + total += scan->numsubclasses; + count2++; + } + } else { + count1++; + } + } + + if (!count1 && !count2) + return NULL; + + size = (count1 + total) * 8 + count2 * 12 + 4; + buf = lalloc(size); + memclrw(buf, size); + + object = CParser_NewCompilerDefDataObject(); + object->name = CParser_GetUniqueName(); + object->type = CDecl_NewStructType(size, 4); + object->qual = Q_CONST; + object->sclass = TK_STATIC; + refs = NULL; + + work = buf; + + if (count1) { + for (scan = baselist; scan; scan = scan->next) { + if (!scan->x12 && !scan->x13) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); + ref->offset = ((char *) work) - ((char *) buf); + ref->somevalue = 0; + + work[1] = CTool_EndianConvertWord32(scan->voffset); + work += 2; + } + } + } + + if (count2) { + for (scan = baselist; scan; scan = scan->next) { + if (scan->numsubclasses) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); + ref->offset = ((char *) work) - ((char *) buf); + ref->somevalue = 0; + + work[1] = CTool_EndianConvertWord32(scan->voffset | 0x80000000); + work[2] = CTool_EndianConvertWord32(scan->numsubclasses); + work2 = work + 3; + + for (subclass = scan->subclasses; subclass; subclass = subclass->next) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(subclass->base), 0); + ref->offset = ((char *) work2) - ((char *) buf); + ref->somevalue = 0; + + work2[1] = CTool_EndianConvertWord32(subclass->voffset); + work2 += 2; + } + + work = work2; + } + } + } + + CInit_DeclareData(object, buf, refs, object->type->size); + return object; +} + +static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual) { + Object *baselistobj; + Object *nameobj; + HashNameNode *rttiname; + OLinkList *refs; + char *namestr; + int namelen; + Object *object; + NameSpaceObjectList *list; + TypePointer tptr_copy; + TypeMemberPointer tmemptr_copy; + UInt32 data[2]; + + switch (type->type) { + case TYPEPOINTER: + if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { + tptr_copy = *TYPE_POINTER(type); + tptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); + type = TYPE(&tptr_copy); + } + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->qual & (Q_CONST | Q_VOLATILE)) { + tmemptr_copy = *TYPE_MEMBER_POINTER(type); + tmemptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); + type = TYPE(&tmemptr_copy); + } + break; + default: + qual = 0; + } + + if (IS_TYPE_CLASS(type) && type->size == 0) { + CDecl_CompleteType(type); + if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2)) + CError_Error(CErrorStr136, type, 0); + } + + rttiname = CMangler_RTTIObjectName(type, qual); + list = CScope_FindName(cscope_root, rttiname); + + if (!list || (object = OBJECT(list->object))->otype != OT_OBJECT || object->datatype != DDATA) { + namestr = CError_GetTypeName(type, qual, 0); + namelen = strlen(namestr) + 1; + nameobj = CInit_DeclareString(namestr, namelen, 0, 0); + + baselistobj = NULL; + if (IS_TYPE_CLASS(type)) + baselistobj = CRTTI_CreateBaseListObject(TYPE_CLASS(type)); + + memclrw(data, sizeof(data)); + + object = CParser_NewCompilerDefDataObject(); + object->name = rttiname; + object->type = CDecl_NewStructType(sizeof(data), 4); + object->qual = Q_CONST; + object->sclass = TK_STATIC; + + refs = lalloc(sizeof(OLinkList)); + refs->next = NULL; + refs->obj = nameobj; + refs->offset = 0; + refs->somevalue = 0; + + if (baselistobj) { + refs->next = lalloc(sizeof(OLinkList)); + refs->next->next = NULL; + refs->next->obj = baselistobj; + refs->next->offset = 4; + refs->next->somevalue = 0; + } + + CScope_AddGlobalObject(object); + CInit_DeclareData(object, data, refs, object->type->size); + } + + return object; +} + +static void CRTTI_ConstructVTableHeader(TypeClass *tclass1, TypeClass *tclass2, Object *typeinfoObj, char *data, SInt32 offset, SInt32 voffset) { + ClassList *base; + Offset *o; + OLinkList *olink; + SInt32 tmp; + SInt32 newoffset; + SInt32 newvoffset; + + if (tclass2->vtable->owner == tclass2) { + for (o = crtti_offsets; o; o = o->next) { + if (o->offset == voffset) + break; + } + + if (!o) { + o = lalloc(sizeof(Offset)); + o->next = crtti_offsets; + o->offset = voffset; + crtti_offsets = o; + + olink = lalloc(sizeof(OLinkList)); + olink->next = crtti_olinks; + olink->obj = typeinfoObj; + olink->offset = voffset; + olink->somevalue = 0; + crtti_olinks = olink; + + *((SInt32 *) (data + voffset + 4)) = CTool_EndianConvertWord32(-offset); + } else { + tmp = *((SInt32 *) (data + voffset + 4)); + CError_ASSERT(404, tmp == CTool_EndianConvertWord32(-offset)); + } + } + + for (base = tclass2->bases; base; base = base->next) { + if (base->base->vtable) { + if (base->is_virtual) { + newoffset = CClass_VirtualBaseOffset(tclass1, base->base); + newvoffset = CClass_VirtualBaseVTableOffset(tclass1, base->base); + } else { + newoffset = offset + base->offset; + newvoffset = voffset + base->voffset; + } + + CRTTI_ConstructVTableHeader(tclass1, base->base, typeinfoObj, data, newoffset, newvoffset); + } + } +} + +OLinkList *CRTTI_ConstructVTableHeaders(TypeClass *tclass, void *data, OLinkList *links) { + crtti_offsets = NULL; + crtti_olinks = links; + + CRTTI_ConstructVTableHeader( + tclass, tclass, + CRTTI_ConstructTypeInfoObject(TYPE(tclass), 0), + data, 0, 0); + + return crtti_olinks; +} + +static Type *CRTTI_FindTypeInfoType(void) { + NameSpace *nspace; + NameSpaceObjectList *list; + Type *type; + + if ((list = CScope_FindName(cscope_root, GetHashNameNodeExport("std"))) && list->object->otype == OT_NAMESPACE) + nspace = OBJ_NAMESPACE(list->object)->nspace; + else + nspace = cscope_root; + + type = CScope_GetLocalTagType(nspace, GetHashNameNodeExport("type_info")); + if (type && IS_TYPE_CLASS(type) && type->size) + return type; + + CError_Error(CErrorStr140, "::std::type_info"); + return TYPE(&stchar); +} + +ENode *CRTTI_ParseTypeID(void) { + ENode *expr; + Type *type; + Type *typeinfoType; + UInt32 qual; + + if (!copts.useRTTI) + CError_Warning(CErrorStr257); + + typeinfoType = CRTTI_FindTypeInfoType(); + + if (lex() != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + + tk = lex(); + if ((type = CParser_ParseTypeID(&qual, NULL))) { + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + } else { + expr = s_expression(); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + type = expr->rtype; + qual = ENODE_QUALS(expr); + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->vtable) { + expr = funccallexpr( + Rgtid_func, + getnodeaddress(expr, 0), + intconstnode(TYPE(&stsignedlong), TYPE_CLASS(type)->vtable->offset), + NULL, + NULL); + expr->rtype = CDecl_NewPointerType(typeinfoType); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = typeinfoType; + expr->flags = ENODE_FLAG_CONST; + return expr; + } + } + + expr = create_objectrefnode(CRTTI_ConstructTypeInfoObject(type, qual)); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = typeinfoType; + expr->flags = ENODE_FLAG_CONST; + return expr; +} + +static void CRTTI_ConstCastQualCheck(UInt32 qual1, UInt32 qual2) { + if ( + ((qual1 & Q_CONST) && !(qual2 & Q_CONST)) || + ((qual1 & Q_VOLATILE) && !(qual2 & Q_VOLATILE)) + ) + CError_Error(CErrorStr258); +} + +static void CRTTI_ConstCastCheck(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2) { + Boolean flag = 1; + if (IS_TYPE_REFERENCE(type2)) { + type2 = TPTR_TARGET(type2); + flag = 0; + } + + while (1) { + if (type1->type != type2->type) + break; + + switch (type1->type) { + case TYPEPOINTER: + if (!flag) + CRTTI_ConstCastQualCheck(TPTR_QUAL(type1), TPTR_QUAL(type2)); + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + flag = 0; + continue; + + case TYPEMEMBERPOINTER: + if (!flag) + CRTTI_ConstCastQualCheck(TYPE_MEMBER_POINTER(type1)->qual, TYPE_MEMBER_POINTER(type2)->qual); + type1 = TYPE_MEMBER_POINTER(type1)->ty1; + type2 = TYPE_MEMBER_POINTER(type2)->ty1; + flag = 0; + continue; + } + + break; + } + + if (!flag && !IS_TYPE_FUNC(type1) && !IS_TYPE_FUNC(type2)) + CRTTI_ConstCastQualCheck(CParser_GetCVTypeQualifiers(type1, qual1), CParser_GetCVTypeQualifiers(type2, qual2)); +} + +static ENode *CRTTI_ParseCast(DeclInfo *di) { + ENode *expr; + + if (lex() != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + + memclrw(di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(di, 0); + scandeclarator(di); + + if (di->name) + CError_Error(CErrorStr164); + + if (tk != '>') { + CError_Error(CErrorStr231); + return NULL; + } + + if (lex() != '(') { + CError_Error(CErrorStr114); + return NULL; + } + + tk = lex(); + expr = s_expression(); + if (!IS_TYPE_REFERENCE(di->thetype)) + expr = pointer_generation(expr); + + if (tk != ')') { + CError_Error(CErrorStr115); + return NULL; + } + + tk = lex(); + return expr; +} + +static void CRTTI_IncompleteCheck(Type *type) { + if (IS_TYPE_POINTER_ONLY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && type->size == 0) { + CDecl_CompleteType(type); + if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2)) + CError_Error(CErrorStr136, type, 0); + } +} + +static Boolean CRTTI_IsSameType(Type *a, Type *b) { + while (1) { + if (a->type != b->type) + return 0; + + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + a = TPTR_TARGET(a); + b = TPTR_TARGET(b); + continue; + default: + return is_typesame(a, b); + } + } +} + +static ENode *CRTTI_UniversalCast(ENode *expr, Type *type, UInt32 qual, UInt8 mode) { + // type/qual are the target type + Boolean isSimpleCast; + Boolean needsTypcon; + Boolean failed; + + if (ENODE_IS(expr, EOBJLIST)) + return CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + + isSimpleCast = needsTypcon = failed = 0; + + switch (type->type) { + case TYPEINT: + case TYPEENUM: + if (mode == 2 && IS_TYPE_POINTER_ONLY(expr->rtype) && type != TYPE(&stbool)) + failed = 1; + break; + + case TYPEPOINTER: + if (TPTR_QUAL(type) & Q_REFERENCE) { + if ( + !CRTTI_IsSameType(TPTR_TARGET(type), expr->rtype) && + mode == 2 && + !( + IS_TYPE_CLASS(TPTR_TARGET(type)) && + IS_TYPE_CLASS(expr->rtype) && + ( + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(expr->rtype), NULL, 0, 1) || + CClass_IsBaseClass(TYPE_CLASS(expr->rtype), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) + ) + ) + ) + { + failed = 1; + } + } else if (IS_TYPE_POINTER_ONLY(expr->rtype)) { + if ( + mode == 3 || + CRTTI_IsSameType(type, expr->rtype) || + IS_TYPE_VOID(TPTR_TARGET(type)) || + IS_TYPE_VOID(TPTR_TARGET(expr->rtype)) + ) + { + isSimpleCast = needsTypcon = 1; + } + else if ( + mode == 2 && + !( + IS_TYPE_CLASS(TPTR_TARGET(type)) && + IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && + ( + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(TPTR_TARGET(expr->rtype)), NULL, 0, 1) || + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) + ) + ) + ) + { + failed = 1; + } + } else { + if (IS_TYPE_ENUM(expr->rtype)) + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { + isSimpleCast = 1; + break; + } + + if (mode != 2) + break; + } + + if (IS_TYPE_CLASS(expr->rtype)) { + if (mode == 2) + break; + } + + failed = 1; + } + break; + } + + if (failed) { + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return expr; + } + + if (isSimpleCast) { + if (needsTypcon && ENODE_IS(expr, EINDIRECT) && (copts.pointercast_lvalue || !copts.ANSI_strict)) + expr = makemonadicnode(expr, ETYPCON); + + expr->rtype = type; + expr->flags = qual & ENODE_FLAG_QUALS; + return expr; + } + + if (copts.old_argmatch) + return do_typecast(expr, type, qual); + + return CExpr_Convert(expr, type, qual, 1, 1); +} + +ENode *CRTTI_Parse_dynamic_cast(void) { + Boolean isRef; + ENode *expr; + TypeClass *srcclass; + TypeClass *destclass; + ENode *typeinfo; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + if (!copts.useRTTI) + CError_Warning(CErrorStr257); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + if (!IS_TYPE_POINTER_ONLY(di.thetype)) { + CError_Error(CErrorStr164); + return expr; + } + + isRef = (TPTR_QUAL(di.thetype) & Q_REFERENCE) != 0; + + if (IS_TYPE_CLASS(TPTR_TARGET(di.thetype))) { + destclass = TYPE_CLASS(TPTR_TARGET(di.thetype)); + CDecl_CompleteType(TYPE(destclass)); + if (!(destclass->flags & CLASS_FLAGS_2)) { + CError_Error(CErrorStr136, destclass, 0); + return expr; + } + } else if (!IS_TYPE_VOID(TPTR_TARGET(di.thetype))) { + CError_Error(CErrorStr164); + return expr; + } else { + destclass = NULL; + } + + if (isRef) { + if (!IS_TYPE_CLASS(expr->rtype)) { + CError_Error(CErrorStr164); + return expr; + } + + srcclass = TYPE_CLASS(expr->rtype); + if (destclass) { + if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) + return do_typecast(expr, di.thetype, di.qual); + } + + expr = getnodeaddress(expr, 1); + } else { + if (!IS_TYPE_POINTER_ONLY(expr->rtype) || !IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { + CError_Error(CErrorStr164); + return expr; + } + + srcclass = TYPE_CLASS(TPTR_TARGET(expr->rtype)); + if (destclass) { + if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) + return do_typecast(expr, di.thetype, di.qual); + } + } + + if (!(srcclass->flags & CLASS_FLAGS_2)) { + CError_Error(CErrorStr136, srcclass, 0); + return expr; + } + + if (!srcclass->vtable) { + CError_Error(CErrorStr164); + return expr; + } + + if (srcclass->sominfo) { + CError_Error(CErrorStr164); + return expr; + } + + if (destclass) { + typeinfo = create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(destclass), 0)); + if (destclass->sominfo) { + CError_Error(CErrorStr164); + return expr; + } + } else { + typeinfo = nullnode(); + } + + expr = CExpr_FuncCallSix( + Rdync_func, + expr, + intconstnode(TYPE(&stsignedlong), srcclass->vtable->offset), + typeinfo, + create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(srcclass), 0)), + intconstnode(TYPE(&stsignedshort), isRef), + NULL + ); + + if (isRef) { + expr->rtype = CDecl_NewPointerType(TYPE(destclass)); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(destclass); + } else { + expr->rtype = di.thetype; + } + expr->flags = di.qual & ENODE_FLAG_QUALS; + return expr; +} + +ENode *CRTTI_Parse_static_cast(void) { + ENode *expr; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + + if (IS_TYPE_REFERENCE(di.thetype)) { + if (IS_TYPE_CLASS(expr->rtype) && CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) { + expr = CExpr_Convert(expr, di.thetype, di.qual, 0, 1); + CError_ASSERT(959, IS_TYPE_POINTER_ONLY(expr->rtype)); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(di.thetype); + expr->flags = di.qual & ENODE_FLAG_QUALS; + return expr; + } + } else { + if (CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) + return CExpr_Convert(expr, di.thetype, di.qual, 1, 1); + } + + if (!IS_TYPE_VOID(di.thetype) && !(IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_VOID(TPTR_TARGET(expr->rtype)))) { + CRTTI_IncompleteCheck(di.thetype); + CRTTI_IncompleteCheck(expr->rtype); + } + + return CRTTI_UniversalCast(expr, di.thetype, di.qual, 2); +} + +ENode *CRTTI_Parse_reinterpret_cast(void) { + ENode *expr; + Type *origtype; + ENode *lvalue; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + + if (IS_TYPE_REFERENCE(di.thetype)) { + lvalue = CExpr_LValue(expr, 0, 1); + if (!ENODE_IS(lvalue, EINDIRECT)) + return lvalue; + + lvalue->data.monadic->rtype = CDecl_NewPointerType(lvalue->rtype); + expr = lvalue->data.monadic; + origtype = di.thetype; + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + } else { + origtype = NULL; + } + + switch (di.thetype->type) { + case TYPEINT: + switch (expr->rtype->type) { + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + expr = do_typecast(expr, di.thetype, di.qual); + break; + default: + CError_Error(CErrorStr164); + } + break; + case TYPEPOINTER: + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + if (origtype) + di.thetype = origtype; + expr = do_typecast(expr, di.thetype, di.qual); + break; + case TYPEPOINTER: + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + default: + CError_Error(CErrorStr164); + } + break; + case TYPEMEMBERPOINTER: + if (IS_TYPE_MEMBERPOINTER(expr->rtype)) { + if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(di.thetype)->ty1)) { + if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + } + } else { + if (!IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + } + } + } + expr = do_typecast(expr, di.thetype, di.qual); + break; + default: + CError_Error(CErrorStr164); + } + + if (origtype && IS_TYPE_POINTER_ONLY(expr->rtype)) { + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(di.thetype); + } + + return expr; +} + +ENode *CRTTI_Parse_const_cast(void) { + DeclInfo di; + ENode *expr; + + if (!(expr = CRTTI_ParseCast(&di))) + return nullnode(); + + if (IS_TYPE_POINTER_ONLY(di.thetype)) { + if (TPTR_QUAL(di.thetype) & Q_REFERENCE) { + if (!iscpp_typeequal(TPTR_TARGET(di.thetype), expr->rtype)) + CError_Error(CErrorStr164); + + if (ENODE_IS(expr, EINDIRECT)) { + expr->rtype = TPTR_TARGET(di.thetype); + expr->flags = di.qual & ENODE_FLAG_QUALS; + } else { + CError_Error(CErrorStr142); + } + } else { + if (!iscpp_typeequal(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + + expr = do_typecast(expr, di.thetype, di.qual); + } + } else if (IS_TYPE_MEMBERPOINTER(di.thetype)) { + if (!iscpp_typeequal(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + + expr = do_typecast(expr, di.thetype, di.qual); + } else { + if (!is_typesame(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + else + expr = do_typecast(expr, di.thetype, di.qual); + } + + return expr; +} diff --git a/compiler_and_linker/unsorted/CSOM.c b/compiler_and_linker/unsorted/CSOM.c index e69de29..896c425 100644 --- a/compiler_and_linker/unsorted/CSOM.c +++ b/compiler_and_linker/unsorted/CSOM.c @@ -0,0 +1,2074 @@ +#include "compiler/CSOM.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" +#include "cos.h" + +// all pointers have been converted to UInt32 for the sake of maintaining 32-bit compat + +typedef struct { + SInt32 zero; + /* struct somStaticClassInfo * */ UInt32 sci; + /* void * */ UInt32 instanceDataToken; + SInt32 reserved[3]; + /* void * */ UInt32 tokens[1]; +} somClassDataStructure; + +enum { + mtVirtualMethod = 0, + mtProcedure = 1, + mtNonStatic = 2, + mtEmpty = 3, + mtDToken = 4 +}; + +enum { + pdUByte = 0, + pdSByte = 1, + pdUHalf = 2, + pdSHalf = 3, + pdULong = 4, + pdSLong = 5, + pdVLong = 6, + pdVoid = 7, + pdSFlt = 8, + pdDFlt = 9, + pdLFlt = 10, + pdVSAgg = 11, + pdNPtr = 12, + pdLPtr = 13, + pdSAgg = 14, + pdLAgg = 15 +}; + +enum { + fgShortOrChars = 1, + fgShortFloats = 2, + fgAnyFloats = 4, + fgAnyNon4Bytes = 8 +}; + +enum { + cfSharedStrings = 1, + cfTempClass = 2, + cfProxyClass = 4, + cfClassAllocate = 0x100, + cfClassDeallocate = 0x200, + cfClassInit = 0x400, + cfClassUninit = 0x800 +}; + +typedef struct { + UInt32 majorVersion; + UInt32 minorVersion; + UInt32 flags; + UInt16 dataAlignment; + UInt16 classTokenCount; + UInt16 numDirectParents; + UInt16 numMetaClasses; + UInt16 numOverriddenAncestors; + UInt16 numMigratedMethods; + UInt16 numSelectInherited; + UInt16 numUnused; + UInt16 dummy2a[4]; +} somStaticClassCounts; + +typedef UInt8 somSlotUsage; +typedef UInt8 somSignatureInfo; +typedef UInt16 somOverrideData; +typedef UInt16 somMigratedMethods; +typedef UInt16 somSelectedInherited; +typedef UInt32 somParentVersions; + +typedef struct { + /* const char * */ UInt32 className; + UInt32 instanceDataSize; + /* const somParentVersions * */ UInt32 parentVersions; + /* const somSlotUsage * */ UInt32 ttSlotUsage; + /* const somSignatureInfo * */ UInt32 signatureInfo; + /* const char * */ UInt32 methodNames; + /* const somOverrideData * */ UInt32 overrideData; + /* const somMigratedMethods * */ UInt32 migratedMethods; + /* const somSelectedInherited * */ UInt32 selectedInherited; + /* const void * */ UInt32 unused; + /* const void * */ UInt32 dummy4b[4]; +} somStaticClassDescription; + +typedef struct somStaticClassInfo { + UInt32 layoutVersion; + /* somClassDataStructure * */ UInt32 tokenTable; + /* somMethodPtr * */ UInt32 overrideMethods; + /* somClassDataStructure ** */ UInt32 specifiedAncestry; + /* somOpaque */ UInt32 DLLDesignator; + /* somMethodPtr * */ UInt32 specialProcs; + /* somRuntimeClassInfo * */ UInt32 runtimeClassInfo; + SInt32 interesting; + /* somClassDataStructure ** */ UInt32 actualAncestry; + /* void * */ UInt32 extra[4]; + /* const somStaticClassCounts * */ UInt32 classCounts; + somStaticClassDescription classDescription; +} somStaticClassInfo; + +CSOMStub *csom_stubs; +static HashNameNode *csom_initname; +static HashNameNode *csom_uninitname; +static HashNameNode *csom_envname; +static HashNameNode *csom_selfname; + +static FuncArg SOMIDT_arg1 = { + NULL, + NULL, + NULL, + TYPE(&void_ptr), + 0, + 0, + 0, + 0 +}; + +static TypeFunc SOMIDT_type = { + TYPEFUNC, + 0, + &SOMIDT_arg1, + NULL, + TYPE(&void_ptr), + 0, + 0 +}; + +void CSOM_Setup(Boolean flag) { + if (!flag) + csom_stubs = NULL; + + csom_initname = GetHashNameNodeExport("somInit"); + csom_uninitname = GetHashNameNodeExport("somUninit"); + csom_envname = GetHashNameNodeExport("Environment"); + csom_selfname = GetHashNameNodeExport("__somself"); +} + +void CSOM_Cleanup(void) { + CSOMStub *stub; + + if (cparamblkptr->isPrecompiling != 1) { + for (stub = csom_stubs; stub; stub = stub->next) { + switch (stub->x10) { + case 0: + CodeGen_SOMStub(stub->object, rt_som_glue1, stub->tclass->sominfo->classdataobject, stub->offset); + break; + case 1: + CodeGen_SOMStub(stub->object, rt_som_glue2, stub->tclass->sominfo->classdataobject, stub->offset); + break; + case 2: + CodeGen_SOMStub(stub->object, rt_som_glue3, stub->tclass->sominfo->classdataobject, stub->offset); + break; + default: + CError_FATAL(132); + } + } + } +} + +static HashNameNode *CSOM_NameTranslate(HashNameNode *name) { + if (name == constructor_name_node) + name = csom_initname; + else if (name == destructor_name_node) + name = csom_uninitname; + return name; +} + +static Type *CSOM_FindClassType(HashNameNode *name) { + Type *type; + + type = CScope_GetTagType(cscope_current, name); + if (!type) { + CPrep_ErrorName(CErrorStr281, name->name); + type = &stvoid; + } + + return type; +} + +static inline UInt16 CSOM_GetTokenTableIndex(const Object *object) { + CError_ASSERT(173, IS_TYPE_METHOD(object->type)); + return TYPE_METHOD(object->type)->x1E; +} + +static SInt32 CSOM_GetTokenOffset(Object *object) { + return 24 + 4 * CSOM_GetTokenTableIndex(object); +} + +typedef struct TypeSig { + UInt8 x0; + UInt8 x1; + UInt8 x2; +} TypeSig; + +static UInt8 CSOM_GetTypeSig(TypeSig *sig, Type *type, Boolean flag) { + if (type->size > 4) + sig->x1 |= fgAnyNon4Bytes; + + switch (type->type) { + case TYPEVOID: + if (flag) + return pdVoid; + break; + case TYPEINT: + case TYPEENUM: + if (is_unsigned(type)) { + switch (type->size) { + case 1: + sig->x1 |= fgShortOrChars; + return pdUByte; + case 2: + sig->x1 |= fgShortOrChars; + return pdUHalf; + case 4: + return pdULong; + case 8: + return pdVLong; + } + } else { + switch (type->size) { + case 1: + sig->x1 |= fgShortOrChars; + return pdSByte; + case 2: + sig->x1 |= fgShortOrChars; + return pdSHalf; + case 4: + return pdSLong; + case 8: + return pdVLong; + } + } + break; + case TYPEFLOAT: + sig->x1 |= fgAnyFloats; + switch (type->size) { + case 4: + sig->x1 |= fgShortFloats; + return pdSFlt; + case 8: + return pdDFlt; + case 12: + case 16: + return pdLFlt; + } + break; + case TYPEPOINTER: + return pdNPtr; + case TYPESTRUCT: + case TYPECLASS: + if (flag) { + if (type->size <= 2) { + sig->x1 |= fgShortOrChars; + return pdVSAgg; + } else if (type->size <= 4) { + return pdSAgg; + } else { + return pdLAgg; + } + } + break; + } + + CError_Error(CErrorStr273); + return 5; +} + +static void CSOM_GetFuncSig(TypeFunc *tfunc, Boolean flag) { + FuncArg *arg; + Boolean pendingData; + UInt8 work; + TypeSig sig; + + sig.x2 = CSOM_GetTypeSig(&sig, tfunc->functype, 1); + sig.x1 = 0; + sig.x0 = 0; + + for (arg = tfunc->args; arg; arg = arg->next) { + if (arg == &elipsis || arg == &oldstyle || (++sig.x0 == 0)) { + CError_Error(CErrorStr273); + break; + } + + CSOM_GetTypeSig(&sig, arg->type, 0); + } + + if (flag) { + if ((arg = tfunc->args)) { + if (TYPE_METHOD(tfunc)->x26 == 0) + arg = arg->next; + if (arg && CMach_GetFunctionResultClass(tfunc) != 0) + arg = arg->next; + } + + AppendGListByte(&name_mangle_list, sig.x0); + AppendGListByte(&name_mangle_list, (sig.x1 << 4) | sig.x2); + if (sig.x1) { + pendingData = 0; + work = 0; + while (arg) { + work = (work << 4) | CSOM_GetTypeSig(&sig, arg->type, 0); + if (pendingData) { + AppendGListByte(&name_mangle_list, work); + pendingData = 0; + work = 0; + } else { + pendingData = 1; + } + arg = arg->next; + } + + if (pendingData) + AppendGListByte(&name_mangle_list, work << 4); + } + } +} + +void CSOM_CheckFuncType(TypeFunc *tfunc) { + CSOM_GetFuncSig(tfunc, 0); +} + +static Object *CSOM_MakeObject(char *name1, char *name2, SInt32 size) { + Object *object = CParser_NewCompilerDefDataObject(); + object->name = CParser_NameConcat(name1, name2); + object->type = CDecl_NewStructType(size, 4); + CScope_AddObject(object->nspace, object->name, OBJ_BASE(object)); + return object; +} + +void CSOM_MakeSOMClass(TypeClass *tclass) { + ClassList *base; + + for (base = tclass->bases; base; base = base->next) { + if (!base->base->sominfo) { + CError_Error(CErrorStr267); + break; + } + } + + if (!tclass->sominfo) { + SOMInfo *info = galloc(sizeof(SOMInfo)); + memclrw(info, sizeof(SOMInfo)); + tclass->sominfo = info; + + info->classdataobject = CSOM_MakeObject(tclass->classname->name, "ClassData", 28); + info->classdataobject->flags |= OBJECT_FLAGS_40; + } +} + +static Boolean CSOM_IsTokenListFunc(Object *object) { + Type *type = object->type; + if ( + IS_TYPE_FUNC(type) && + !(TYPE_FUNC(type)->flags & FUNC_FLAGS_20) && + !TYPE_METHOD(type)->x26 && + (!(object->qual & Q_INLINE) || object->datatype == DVFUNC) + ) + return 1; + + return 0; +} + +static Object **CSOM_GetLexicalOrderMethodArray(TypeClass *tclass, int *resultCount) { + Object *object; + int count; + Object **array; + CScopeObjectIterator iter; + + count = 0; + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_METHOD(object->type)) { + if (CSOM_IsTokenListFunc(object)) { + if (TYPE_METHOD(object->type)->x1E > count) + count = TYPE_METHOD(object->type)->x1E; + } else { + TYPE_METHOD(object->type)->x1E = 0; + } + } + } + + *resultCount = ++count; + + array = lalloc(sizeof(Object *) * count); + memclrw(array, sizeof(Object *) * count); + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (CSOM_IsTokenListFunc(object)) + array[TYPE_METHOD(object->type)->x1E] = object; + } + + return array; +} + +void CSOM_ClassComplete(TypeClass *tclass) { + Object *object; + CScopeObjectIterator iter; + SInt32 counter; + SOMReleaseOrder *order; + + if (tclass->sominfo->order) { + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (CSOM_IsTokenListFunc(object)) { + HashNameNode *name; + + name = CSOM_NameTranslate(object->name); + for (order = tclass->sominfo->order, counter = 0; order; order = order->next, counter++) { + if (order->name == name) { + order->state = SOMMS_Method; + TYPE_METHOD(object->type)->x1E = counter; + break; + } + } + + if (!order) + CError_Error(CErrorStr278, object); + } + } + + for (order = tclass->sominfo->order; order; order = order->next) { + if (order->state == SOMMS_Deleted) { + SOMReleaseOrder *order2; + VClassList *vbase; + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + for (order2 = vbase->base->sominfo->order; order2; order2 = order2->next) { + if (order->name == order2->name && order2->state == SOMMS_Method) { + order->state = SOMMS_Migrated; + break; + } + } + } + } + } + } else { + Object **array; + int arrayCount; + SInt32 i; + + array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); + for (i = counter = 0; i < arrayCount; i++) { + object = array[i]; + if (object) { + if (counter == 0 && copts.pedantic) + CError_Warning(CErrorStr291); + TYPE_METHOD(object->type)->x1E = counter++; + } + } + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + NameSpaceObjectList *nsol; + if (!(nsol = CScope_NextObjectIteratorObjectList(&iter))) + break; + + if (nsol->object->otype == OT_OBJECT && nsol->next && nsol->next->object->otype == OT_OBJECT) { + while (nsol) { + if ( + nsol->object->otype == OT_OBJECT && + (!(OBJECT(nsol->object)->qual & Q_INLINE) || OBJECT(nsol->object)->datatype == DVFUNC) + ) + CError_Error(CErrorStr270, nsol->object); + nsol = nsol->next; + } + } + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (!(object->qual & Q_INLINE)) { + CError_ASSERT(529, IS_TYPE_FUNC(object->type)); + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_4; + tclass->action = 1; + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type)) + TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_4; + } + break; + } + } + + if (tclass->sominfo->oidl_callstyle == 0) { + Type *envType; + envType = CSOM_FindClassType(csom_envname); + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + IS_TYPE_FUNC(object->type) && + TYPE_METHOD(object->type)->x26 == 0 && + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20) && + !( + TYPE_FUNC(object->type)->args && + TYPE_FUNC(object->type)->args->next && + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->next->type) && + TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == envType + ) + ) + { + CError_Error(CErrorStr282, object); + } + } + } + + if (tclass->action == 0) + CError_Error(CErrorStr280); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct SOMOverride { + struct SOMOverride *next; + Object *a; + Object *b; +} SOMOverride; + +typedef struct SOMAncestor { + struct SOMAncestor *next; + TypeClass *tclass; + SOMOverride *overrides; + Boolean xC; + Boolean xD; +} SOMAncestor; + +typedef struct SOMMethod { + struct SOMMethod *next; + HashNameNode *name; + union { + Object *object; + struct { + UInt16 a; + UInt16 b; + } pair; + } u; + SOMMethodState state; +} SOMMethod; + +typedef struct SOMGenerator { + SOMMethod *methods; + SOMAncestor *ancestors; + Object *sciObj; + Object *classAncestorsObj; + Object *overrideProcsObj; + Object *dlldFunc; + Object *specialProcsObj; + somStaticClassCounts counts; + int overrideProcsCount; + Boolean hasNew; + Boolean hasDelete; +} SOMGenerator; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static SOMAncestor *CSOM_FindAddAncestor(SOMGenerator *gen, TypeClass *tclass, TypeClass *ancestorClass, UInt16 *resultIndex) { + SOMAncestor *ancestor; + SOMAncestor *scan; + int index; + + ancestor = gen->ancestors; + for (scan = ancestor, index = 0; scan; scan = scan->next, index++) { + if (scan->tclass == ancestorClass) { + if (resultIndex) + *resultIndex = index; + return scan; + } + } + + if (ancestor) { + index = 1; + while (ancestor->next) { + ancestor = ancestor->next; + index++; + } + + ancestor->next = lalloc(sizeof(SOMAncestor)); + memclrw(ancestor->next, sizeof(SOMAncestor)); + ancestor = ancestor->next; + } else { + index = 0; + ancestor = lalloc(sizeof(SOMAncestor)); + memclrw(ancestor, sizeof(SOMAncestor)); + gen->ancestors = ancestor; + } + + ancestor->tclass = ancestorClass; + if (resultIndex) + *resultIndex = index; + return ancestor; +} + +static void CSOM_GenerateOverrideIntroLists(SOMGenerator *gen, TypeClass *tclass) { + Object *object; + VClassList *vbase; + ClassList *base; + SOMMethod *method; + SOMMethod **ptr; + CScopeObjectIterator iter; + + for (base = tclass->bases; base; base = base->next) { + SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, base->base, NULL); + ancestor->xD = 1; + gen->counts.numDirectParents++; + } + + if (tclass->sominfo->metaclass && tclass->sominfo->metaclass->sominfo) { + SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, tclass->sominfo->metaclass, NULL); + ancestor->xC = 1; + gen->counts.numMetaClasses++; + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type) && (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) { + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + Object *object2; + CScopeObjectIterator iter2; + CScope_InitObjectIterator(&iter2, vbase->base->nspace); + while (1) { + if (!(object2 = OBJECT(CScope_NextObjectIteratorObject(&iter2)))) + break; + + if ( + IS_TYPE_FUNC(object2->type) && + object->name == object2->name && + object2->datatype == DVFUNC && + !(TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_20) && + CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(object2->type), 0) != 0 + ) + { + SOMAncestor *ancestor; + SOMOverride *override; + ancestor = CSOM_FindAddAncestor(gen, tclass, vbase->base, NULL); + if (ancestor->overrides) { + override = lalloc(sizeof(SOMOverride)); + memclrw(override, sizeof(SOMOverride)); + override->next = ancestor->overrides; + ancestor->overrides = override; + } else { + override = lalloc(sizeof(SOMOverride)); + memclrw(override, sizeof(SOMOverride)); + ancestor->overrides = override; + gen->counts.numOverriddenAncestors++; + } + override->a = object; + override->b = object2; + break; + } + } + } + gen->overrideProcsCount++; + } + } + + ptr = &gen->methods; + if (tclass->sominfo->order) { + SOMReleaseOrder *order; + SOMReleaseOrder *order2; + SInt32 index; + SInt32 index2; + + for (order = tclass->sominfo->order, index = 0; order; order = order->next, index++) { + method = lalloc(sizeof(SOMMethod)); + memclrw(method, sizeof(SOMMethod)); + *ptr = method; + ptr = &method->next; + + method->name = order->name; + method->state = order->state; + switch (order->state) { + case SOMMS_Migrated: + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + for (order2 = vbase->base->sominfo->order, index2 = 0; order2; order2 = order2->next, index2++) { + if (order->name == order2->name && order2->state == SOMMS_Method) { + CSOM_FindAddAncestor(gen, tclass, vbase->base, &method->u.pair.a); + method->u.pair.b = index2; + break; + } + } + + if (order2) + break; + } + gen->counts.numMigratedMethods++; + break; + + case SOMMS_Method: + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + IS_TYPE_FUNC(object->type) && + CSOM_NameTranslate(object->name) == order->name + ) + { + CError_ASSERT(733, TYPE_METHOD(object->type)->x1E == index); + method->u.object = object; + break; + } + } + + CError_ASSERT(737, object != NULL); + break; + } + + gen->counts.classTokenCount++; + } + } else { + Object **array; + int arrayCount; + SInt32 i; + + array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); + for (i = 0; i < arrayCount; i++) { + object = array[i]; + if (object) { + method = lalloc(sizeof(SOMMethod)); + memclrw(method, sizeof(SOMMethod)); + *ptr = method; + ptr = &method->next; + + method->u.object = object; + method->name = object->name; + method->state = SOMMS_Method; + gen->counts.classTokenCount++; + } + } + } +} + +static void CSOM_GenerateClassAncestors(SOMGenerator *gen, TypeClass *tclass) { + SOMAncestor *ancestor; + Object *object; + OLinkList *relocs; + SInt32 size; + char *buf; + + if (gen->ancestors) { + object = CSOM_MakeObject(tclass->classname->name, "ClassAncestors", 4); + object->sclass = TK_STATIC; + + relocs = NULL; + size = 0; + ancestor = gen->ancestors; + while (ancestor) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = ancestor->tclass->sominfo->classdataobject; + reloc->offset = size; + reloc->somevalue = 0; + ancestor = ancestor->next; + size += 4; + } + + buf = lalloc(size); + memclrw(buf, size); + object->type->size = size; + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->classAncestorsObj = object; + } +} + +static void CSOM_GenerateOverrideProcs(SOMGenerator *gen, TypeClass *tclass) { + SOMOverride *override; + SOMAncestor *ancestor; + Object *object; + OLinkList *relocs; + SInt32 size; + SInt32 offset; + char *buf; + + if (gen->overrideProcsCount) { + size = gen->overrideProcsCount * 4; + object = CSOM_MakeObject(tclass->classname->name, "OverrideProcs", size); + object->sclass = TK_STATIC; + + relocs = NULL; + offset = 0; + ancestor = gen->ancestors; + while (ancestor) { + if (ancestor->overrides) { + override = ancestor->overrides; + while (override) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = override->a; + reloc->offset = offset; + reloc->somevalue = 0; + override = override->next; + offset += 4; + } + } + ancestor = ancestor->next; + } + + buf = lalloc(size); + memclrw(buf, size); + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->overrideProcsObj = object; + } +} + +static Object *CSOM_GenerateOverrideData(SOMGenerator *gen) { + SOMAncestor *ancestor; + Object *object; + short ancestorIndex; + + name_mangle_list.size = 0; + for (ancestor = gen->ancestors, ancestorIndex = 0; ancestor; ancestor = ancestor->next, ancestorIndex++) { + if (ancestor->overrides) { + SOMOverride *override; + short overrideCount; + + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(ancestorIndex)); + + override = ancestor->overrides; + overrideCount = 0; + while (override) { + override = override->next; + overrideCount++; + } + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(overrideCount)); + + for (override = ancestor->overrides; override; override = override->next) { + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(CSOM_GetTokenTableIndex(override->b))); + } + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static Object *CSOM_GenerateMigrateData(SOMGenerator *gen) { + SOMMethod *method; + Object *object; + int index; + + name_mangle_list.size = 0; + for (method = gen->methods, index = 0; method; method = method->next, index++) { + if (method->state == SOMMS_Migrated) { + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.a)); + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.b)); + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(index)); + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static void CSOM_GenerateDLLDFunc(SOMGenerator *gen, TypeClass *tclass) { + TypeFunc *tfunc; + Object *object; + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + + object = CParser_NewCompilerDefFunctionObject(); + object->type = TYPE(tfunc); + object->sclass = TK_STATIC; + object->name = CParser_NameConcat(tclass->classname->name, "DLLD"); + + if (CScope_GetLocalObject(cscope_root, object->name)) + CError_Error(CErrorStr333, object); + + gen->dlldFunc = object; + CFunc_GenerateDummyFunction(object); +} + +static void CSOM_GenerateSpecialProcs(SOMGenerator *gen, TypeClass *tclass) { + Object *newFunc; + Object *deleteFunc; + Object *object; + OLinkList *relocs; + SInt32 size; + CScopeObjectIterator iter; + char buf[16]; + + newFunc = deleteFunc = NULL; + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type)) { + if (object->name == CMangler_OperatorName(TK_NEW)) { + newFunc = object; + gen->hasNew = 1; + } else if (object->name == CMangler_OperatorName(TK_DELETE)) { + deleteFunc = object; + gen->hasDelete = 1; + } + } + } + + if (newFunc || deleteFunc) { + object = CSOM_MakeObject(tclass->classname->name, "SpecialProcs", 4); + object->sclass = TK_STATIC; + + relocs = NULL; + size = 0; + + if (newFunc) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = newFunc; + reloc->offset = size; + reloc->somevalue = 0; + size += 4; + } + + if (deleteFunc) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = deleteFunc; + reloc->offset = size; + reloc->somevalue = 0; + size += 4; + } + + memclrw(buf, sizeof(buf)); + object->type->size = size; + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->specialProcsObj = object; + } +} + +static Object *CSOM_GenerateParentVersion(SOMGenerator *gen) { + SInt32 size; + UInt32 *buf; + SInt32 offset; + SOMAncestor *ancestor; + + size = 8 * (gen->counts.numDirectParents + gen->counts.numMetaClasses); + buf = lalloc(size); + + for (ancestor = gen->ancestors, offset = 0; ancestor; ancestor = ancestor->next) { + if (ancestor->xC || ancestor->xD) { + buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->majorversion); + buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->minorversion); + } + } + + return CInit_DeclareString((char *) buf, size, 0, 0); +} + +static void CSOM_SetNibble(UInt8 *buf, int offset, UInt8 value) { + int i = offset >> 1; + if (offset & 1) { + int left = buf[i] & 0xF0; + int right = value & 0xF; + buf[i] = left | right; + } else { + int left = value << 4; + int right = buf[i] & 0xF; + buf[i] = left | right; + } +} + +static Object *CSOM_GenerateSlotUsage(SOMGenerator *gen) { + SInt32 size; + SOMMethod *method; + UInt8 *buf; + int offset; + + size = (gen->counts.classTokenCount + 1) / 2; + buf = lalloc(size); + memclrw(buf, size); + + for (method = gen->methods, offset = 0; method; method = method->next, offset++) { + switch (method->state) { + case SOMMS_Deleted: + case SOMMS_Migrated: + CSOM_SetNibble(buf, offset, mtEmpty); + break; + case SOMMS_Method: + CSOM_SetNibble(buf, offset, mtVirtualMethod); + break; + default: + CError_FATAL(1048); + } + } + + return CInit_DeclareString((char *) buf, size, 0, 0); +} + +static Object *CSOM_GenerateSignature(SOMGenerator *gen) { + Object *object; + SOMMethod *method; + + name_mangle_list.size = 0; + + for (method = gen->methods; method; method = method->next) { + if (method->state == SOMMS_Method) + CSOM_GetFuncSig(TYPE_FUNC(method->u.object->type), 1); + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static Object *CSOM_GenerateMethodNames(SOMGenerator *gen) { + Object *object; + SOMMethod *method; + HashNameNode *name; + + name_mangle_list.size = 0; + + for (method = gen->methods; method; method = method->next) { + if (method->name) { + name = CSOM_NameTranslate(method->name); + AppendGListID(&name_mangle_list, name->name); + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static void CSOM_SetupClassCounts(SOMGenerator *gen, TypeClass *tclass, somStaticClassCounts *counts) { + gen->counts.majorVersion = tclass->sominfo->majorversion; + gen->counts.minorVersion = tclass->sominfo->minorversion; + gen->counts.flags = cfSharedStrings; + if (gen->hasNew) + gen->counts.flags |= cfClassAllocate; + if (gen->hasDelete) + gen->counts.flags |= cfClassDeallocate; + + switch (tclass->align) { + case 1: + gen->counts.dataAlignment = 0; + break; + case 2: + gen->counts.dataAlignment = 1; + break; + case 4: + gen->counts.dataAlignment = 2; + break; + case 8: + gen->counts.dataAlignment = 3; + break; + default: + gen->counts.dataAlignment = 4; + break; + } + + gen->counts.numSelectInherited = 0; + + memclrw(counts, sizeof(somStaticClassCounts)); + counts->majorVersion = CTool_EndianConvertWord32(gen->counts.majorVersion); + counts->minorVersion = CTool_EndianConvertWord32(gen->counts.minorVersion); + counts->flags = CTool_EndianConvertWord32(gen->counts.flags); + counts->dataAlignment = CTool_EndianConvertWord16(gen->counts.dataAlignment); + counts->classTokenCount = CTool_EndianConvertWord16(gen->counts.classTokenCount); + counts->numDirectParents = CTool_EndianConvertWord16(gen->counts.numDirectParents); + counts->numMetaClasses = CTool_EndianConvertWord16(gen->counts.numMetaClasses); + counts->numOverriddenAncestors = CTool_EndianConvertWord16(gen->counts.numOverriddenAncestors); + counts->numMigratedMethods = CTool_EndianConvertWord16(gen->counts.numMigratedMethods); + counts->numSelectInherited = CTool_EndianConvertWord16(gen->counts.numSelectInherited); +} + +static void CSOM_GenerateSCIObject(SOMGenerator *gen, TypeClass *tclass) { + Object *object; + OLinkList *relocs; + OLinkList *reloc; + somStaticClassInfo sci; + somStaticClassCounts classCounts; + + object = CSOM_MakeObject(tclass->classname->name, "SCI", sizeof(sci)); + object->sclass = TK_STATIC; + + memclrw(&sci, sizeof(sci)); + sci.layoutVersion = CTool_EndianConvertWord32(70); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = NULL; + relocs = reloc; + reloc->obj = tclass->sominfo->classdataobject; + reloc->offset = 4; + reloc->somevalue = 0; + + if (gen->overrideProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->overrideProcsObj; + reloc->offset = 8; + reloc->somevalue = 0; + } + + if (gen->classAncestorsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->classAncestorsObj; + reloc->offset = 12; + reloc->somevalue = 0; + } + + if (gen->dlldFunc) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->dlldFunc; + reloc->offset = 16; + reloc->somevalue = 0; + } + + if (gen->specialProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->specialProcsObj; + reloc->offset = 20; + reloc->somevalue = 0; + } + + CSOM_SetupClassCounts(gen, tclass, &classCounts); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CInit_DeclareString((char *) &classCounts, sizeof(classCounts), 0, 0); + reloc->offset = 52; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CInit_DeclareString(tclass->classname->name, strlen(tclass->classname->name) + 1, 0, 0); + reloc->offset = 56; + reloc->somevalue = 0; + + sci.classDescription.instanceDataSize = CTool_EndianConvertWord32(tclass->size); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateParentVersion(gen); + reloc->offset = 64; + reloc->somevalue = 0; + + if (gen->methods) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateSlotUsage(gen); + reloc->offset = 68; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateSignature(gen); + reloc->offset = 72; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateMethodNames(gen); + reloc->offset = 76; + reloc->somevalue = 0; + } + + if (gen->overrideProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateOverrideData(gen); + reloc->offset = 80; + reloc->somevalue = 0; + } + + if (gen->counts.numMigratedMethods) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateMigrateData(gen); + reloc->offset = 84; + reloc->somevalue = 0; + } + + sci.classDescription.selectedInherited = 0; + + CInit_DeclareData(object, &sci, relocs, object->type->size); + gen->sciObj = object; +} + +static void CSOM_GenerateClassDataObject(SOMGenerator *gen, TypeClass *tclass) { + void *buf; + OLinkList *relocs; + OLinkList *reloc; + SInt32 size; + SOMMethod *method; + + relocs = NULL; + for (size = 24, method = gen->methods; method; method = method->next, size += 4) { + if (method->state == SOMMS_Method) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = method->u.object; + reloc->offset = size; + reloc->somevalue = 0; + } + } + + buf = lalloc(size); + memclrw(buf, size); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->sciObj; + reloc->offset = 4; + reloc->somevalue = 0; + + tclass->sominfo->classdataobject->type->size = size; + CInit_DeclareData(tclass->sominfo->classdataobject, buf, relocs, tclass->sominfo->classdataobject->type->size); +} + +void CSOM_GenerateClassStructures(TypeClass *tclass) { + SOMGenerator gen; + + memclrw(&gen, sizeof(gen)); + CSOM_GenerateOverrideIntroLists(&gen, tclass); + CSOM_GenerateClassAncestors(&gen, tclass); + CSOM_GenerateOverrideProcs(&gen, tclass); + CSOM_GenerateDLLDFunc(&gen, tclass); + CSOM_GenerateSpecialProcs(&gen, tclass); + CSOM_GenerateSCIObject(&gen, tclass); + CSOM_GenerateClassDataObject(&gen, tclass); +} + +static TypeClass *CSOM_GetCurrentSOMClass(void) { + if (cscope_current->theclass && cscope_current->theclass->sominfo) + return cscope_current->theclass; + + CError_Error(CErrorStr277); + return NULL; +} + +void CSOM_PragmaReleaseOrder(void) { + TypeClass *tclass; + SOMReleaseOrder *firstOrder; + SOMReleaseOrder *order; + SOMReleaseOrder **ptr; + Boolean flag; + short token; + + if (!(tclass = CSOM_GetCurrentSOMClass())) + return; + + token = CPrep_PragmaLex(0); + if (token != '(') { + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr114); + return; + } + + if (!strcmp(tkidentifier->name, "list")) { + token = CPrep_PragmaLex(0); + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + } + + flag = 1; + } else { + flag = 0; + token = CPrep_PragmaLex(0); + } + + firstOrder = NULL; + if (flag || token != ')') { + ptr = &firstOrder; + while (1) { + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + for (order = firstOrder; order; order = order->next) { + if (order->name == tkidentifier) { + CError_Error(CErrorStr122, tkidentifier->name); + return; + } + } + + order = galloc(sizeof(SOMReleaseOrder)); + *ptr = order; + ptr = &order->next; + + order->next = NULL; + order->name = tkidentifier; + order->state = SOMMS_Deleted; + + if (flag) { + token = CPrep_PragmaLex(1); + if (!token) + break; + } else { + token = CPrep_PragmaLex(0); + if (token == ')') + break; + } + + if (token != ',') { + CPrep_Error(CErrorStr116); + return; + } + + token = CPrep_PragmaLex(flag); + } + } + + tclass->sominfo->order = firstOrder; +} + +void CSOM_PragmaClassVersion(void) { + Type *type; + + if (CPrep_PragmaLex(0) != '(') { + CPrep_Error(CErrorStr114); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_INTCONST) { + CPrep_Error(CErrorStr186); + return; + } + + TYPE_CLASS(type)->sominfo->majorversion = CInt64_GetULong(&tkintconst); + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_INTCONST) { + CPrep_Error(CErrorStr186); + return; + } + + TYPE_CLASS(type)->sominfo->minorversion = CInt64_GetULong(&tkintconst); + + if (CPrep_PragmaLex(0) != ')') { + CPrep_Error(CErrorStr115); + return; + } +} + +void CSOM_PragmaMetaClass(void) { + Type *type; + Type *type2; + + if (CPrep_PragmaLex(0) != '(') { + CPrep_Error(CErrorStr114); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type2 = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type2 && IS_TYPE_CLASS(type2) && TYPE_CLASS(type2)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + TYPE_CLASS(type)->sominfo->metaclass = TYPE_CLASS(type2); + + if (CPrep_PragmaLex(0) != ')') { + CPrep_Error(CErrorStr115); + return; + } +} + +void CSOM_PragmaCallStyle(void) { + TypeClass *tclass; + + if (!(tclass = CSOM_GetCurrentSOMClass())) + return; + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + if (!strcmp(tkidentifier->name, "IDL")) { + tclass->sominfo->oidl_callstyle = 0; + return; + } + + if (!strcmp(tkidentifier->name, "OIDL")) { + tclass->sominfo->oidl_callstyle = 1; + return; + } + + CPrep_Error(CErrorStr186); +} + +void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc) { + FuncArg *arg = CParser_NewFuncArg(); + arg->name = GetHashNameNodeExport("__theclass"); + arg->type = CDecl_NewPointerType(CSOM_FindClassType(GetHashNameNodeExport("SOMClass"))); + arg->next = tfunc->args; + tfunc->args = arg; +} + +static Object *CSOM_FindRTFunc(char *namestr, char *sig) { + NameSpaceObjectList *nsol; + Object *object; + FuncArg *arg; + + if ( + (nsol = CScope_GetLocalObject(cscope_root, GetHashNameNodeExport(namestr))) && + nsol->object->otype == OT_OBJECT + ) + { + object = OBJECT(nsol->object); + if ( + IS_TYPE_FUNC(object->type) && + *(sig++) == 'p' && + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) + ) + { + for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { + switch (*(sig++)) { + case 'p': + if (IS_TYPE_POINTER_ONLY(arg->type)) + continue; + break; + case 'i': + if (arg->type == TYPE(&stsignedint)) + continue; + break; + case 'I': + if (arg->type == TYPE(&stunsignedint)) + continue; + break; + case 'l': + if (arg->type == TYPE(&stsignedlong)) + continue; + break; + case 'L': + if (arg->type == TYPE(&stunsignedlong)) + continue; + break; + } + break; + } + + if (arg == NULL && *sig == 0) + return object; + } + + CError_Error(CErrorStr275, namestr); + } else { + CError_Error(CErrorStr274, namestr); + } + + return NULL; +} + +static ENode *CSOM_MakeTempCondition(ENode *left, ENode *cond, ENode *expr1, ENode *right) { + ENode *expr; + + expr = lalloc(sizeof(ENode)); + expr->type = ECOND; + expr->cost = 0; + expr->flags = 0; + expr->rtype = &stvoid; + expr->data.cond.cond = cond; + expr->data.cond.expr1 = expr1; + expr->data.cond.expr2 = nullnode(); + expr->data.cond.expr2->rtype = &stvoid; + + if (left) + expr = makediadicnode(left, expr, ECOMMA); + + if (right) { + expr = makediadicnode(expr, right, ECOMMA); + expr->rtype = right->rtype; + } + + return expr; +} + +ENode *CSOM_New(TypeClass *tclass) { + Object *newFunc; + ENode *expr; + + if (tk == '(') { + if ((tk = lex()) == ')') { + tk = lex(); + } else { + CError_Error(CErrorStr272); + } + } + + if (!copts.som_env_check || !copts.som_call_opt) { + newFunc = CSOM_FindRTFunc("somNewObjectInstance", "ppll"); + if (!newFunc) + return nullnode(); + } else { + newFunc = rt_som_new; + } + + expr = funccallexpr( + newFunc, + create_objectrefnode(tclass->sominfo->classdataobject), + intconstnode(TYPE(&stunsignedlong), tclass->sominfo->majorversion), + intconstnode(TYPE(&stunsignedlong), tclass->sominfo->minorversion), + NULL + ); + expr->rtype = CDecl_NewPointerType(TYPE(tclass)); + + if (copts.som_env_check && !copts.som_call_opt) { + ENode *tempExpr; + ENode *checkExpr; + ENode *notExpr; + tempExpr = CExpr_GetETEMPCopy(expr); + checkExpr = funccallexpr(rt_som_newcheck, nullnode(), NULL, NULL, NULL); + notExpr = makemonadicnode(tempExpr, ELOGNOT); + notExpr->rtype = CParser_GetBoolType(); + expr = CSOM_MakeTempCondition(NULL, notExpr, checkExpr, tempExpr); + } + + return expr; +} + +ENode *CSOM_Delete(TypeClass *tclass, ENode *objExpr) { + Object *func; + + if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) + return funccallexpr(func, objExpr, NULL, NULL, NULL); + + return nullnode(); +} + +void CSOM_InitAutoClass(Object *object) { + Type *type; + Statement *stmt; + Object *func; + + if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) { + type = object->type; + object->type = CDecl_NewPointerType(type); + TPTR_QUAL(object->type) = Q_REFERENCE; + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode2(object), CSOM_New(TYPE_CLASS(type)), EASS); + CExcept_RegisterDeleteObject(stmt, object, func); + } +} + +static void CSOM_FindIntroClassOffset(TypeClass *tclass, Object *func, TypeClass **resultClass, SInt32 *resultOffset) { + Object *scan; + VClassList *vbase; + CScopeObjectIterator iter; + + if (!(TYPE_FUNC(func->type)->flags & FUNC_FLAGS_20)) { + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan == func) { + *resultClass = tclass; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + } + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + CScope_InitObjectIterator(&iter, vbase->base->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan == func) { + *resultClass = vbase->base; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + } + } + } else { + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + CScope_InitObjectIterator(&iter, vbase->base->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan->name == func->name) { + if ( + IS_TYPE_FUNC(scan->type) && + scan->datatype == DVFUNC && + !(TYPE_FUNC(scan->type)->flags & FUNC_FLAGS_20) && + CClass_GetOverrideKind(TYPE_FUNC(func->type), TYPE_FUNC(scan->type), 0) + ) + { + *resultClass = vbase->base; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + break; + } + } + } + } + + CError_FATAL(1731); +} + +static ENode *CSOM_ComputeSOMSelf(TypeClass *tclass, ENode *selfExpr) { + ENode *expr; + Object obj; + + expr = create_objectrefnode(tclass->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), 8), EADD); + expr->rtype = CDecl_NewPointerType(TYPE(&SOMIDT_type)); + expr = makemonadicnode(expr, EINDIRECT); + + memclrw(&obj, sizeof(Object)); + obj.otype = OT_OBJECT; + obj.type = TYPE(&SOMIDT_type); + obj.name = no_name_node; + obj.datatype = DFUNC; + selfExpr = funccallexpr(&obj, selfExpr, NULL, NULL, NULL); + + CError_ASSERT(1761, ENODE_IS(selfExpr, EFUNCCALL)); + + selfExpr->data.funccall.funcref = expr; + + return selfExpr; +} + +ENode *CSOM_SOMSelfObjectExpr(TypeClass *tclass) { + ObjectList *list; + Object *obj; + + for (list = locals; list; list = list->next) { + if (list->object->name == csom_selfname) + return create_objectnode(list->object); + } + + obj = CParser_NewLocalDataObject(NULL, 1); + obj->name = csom_selfname; + obj->type = CDecl_NewPointerType(TYPE(tclass)); + CFunc_SetupLocalVarInfo(obj); + return create_objectnode(obj); +} + +void CSOM_InitSOMSelf(TypeClass *tclass, Statement *stmt) { + ObjectList *list; + HashNameNode *name; + ENode *selfExpr; + + name = GetHashNameNodeExport("__somself"); + for (list = locals; list; list = list->next) { + if (list->object->name == name) { + selfExpr = CClass_CreateThisSelfExpr(); + CError_ASSERT(1811, selfExpr); + + selfExpr = CSOM_ComputeSOMSelf(tclass, selfExpr); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = makediadicnode(create_objectnode(list->object), selfExpr, EASS); + break; + } + } +} + +ENode *CSOM_EnvCheck(ENode *funccall, ENodeList *checkArg) { + ENodeList *arg; // r26 + ENodeList *arg2; // r28 + ENode *expr26; // r26 + ENode *expr27; // r27 + ENode *expr28; // r28 + Type *returnType; // r31 + + returnType = funccall->rtype; + CError_ASSERT(1842, arg = funccall->data.funccall.args); + + if (arg == checkArg) + CError_ASSERT(1845, arg = arg->next); + + CError_ASSERT(1847, arg2 = arg->next); + + if (arg2 == checkArg) + CError_ASSERT(1850, arg2 = arg2->next); + + CError_ASSERT(1852, IS_TYPE_POINTER_ONLY(arg2->node->rtype)); + + if (!IS_TYPE_VOID(funccall->data.funccall.functype->functype)) { + if (checkArg) { + if (ENODE_IS(checkArg->node, ETEMP)) { + if (checkArg->node->data.temp.uniqueid == 0) + checkArg->node->data.temp.uniqueid = CParser_GetUniqueID(); + + expr26 = lalloc(sizeof(ENode)); + *expr26 = *checkArg->node; + expr26->data.temp.needs_dtor = 0; + } else { + expr26 = CExpr_GetETEMPCopy(checkArg->node); + } + } else { + expr26 = CExpr_GetETEMPCopy(funccall); + } + } else { + expr26 = NULL; + } + + if (!ENODE_IS(arg2->node, EOBJREF)) { + if (ENODE_IS_INDIRECT_TO(arg2->node, EOBJREF) && arg2->node->data.monadic->data.objref->datatype == DLOCAL) { + expr27 = lalloc(sizeof(ENode)); + *expr27 = *arg2->node; + } else { + expr27 = CExpr_GetETEMPCopy(arg2->node); + } + } else { + expr27 = lalloc(sizeof(ENode)); + *expr27 = *arg2->node; + } + + if (copts.som_call_opt) { + funccall = makediadicnode(funccall, funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), ECOMMA); + if (expr26) + funccall = makediadicnode(funccall, expr26, ECOMMA); + } else { + expr28 = lalloc(sizeof(ENode)); + *expr28 = *expr27; + expr28 = makemonadicnode(expr28, EINDIRECT); + expr28->rtype = TYPE(&stsignedlong); + + funccall = CSOM_MakeTempCondition( + funccall, + expr28, + funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), + expr26); + } + + funccall->rtype = returnType; + return funccall; +} + +static Boolean CSOM_CanUseGlueCall(TypeFunc *tfunc) { + int gprCounter; + int fprCounter; + FuncArg *arg; + + gprCounter = 8; + fprCounter = 13; + if (CMach_GetFunctionResultClass(tfunc) != 0) + gprCounter = 7; + + for (arg = tfunc->args; arg; arg = arg->next) { + if (arg == &elipsis || arg == &oldstyle) + return 0; + + switch (arg->type->type) { + case TYPEINT: + case TYPEENUM: + case TYPEPOINTER: + if (--gprCounter < 0) + return 0; + break; + case TYPEFLOAT: + if (--fprCounter < 0) + return 0; + break; + default: + return 0; + } + } + + return 1; +} + +static char *CSOM_AppendString(char *dst, char *src) { + int ch; + while ((ch = *(src++))) + *(dst++) = ch; + return dst; +} + +static ENode *CSOM_SOMGlueCall(TypeClass *tclass, SInt32 offset, Object *object) { + UInt8 funcResultClass; + UInt32 bufsize; + char *buf; + char *ptr; + Object *stubObj; + CSOMStub *stub; + ENode *expr; + char mybuf[256]; + char numberbuf[16]; + + for (stub = csom_stubs; stub; stub = stub->next) { + if (stub->tclass == tclass && stub->offset == offset) + break; + } + + if (!stub) { + funcResultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); + + bufsize = strlen(tclass->sominfo->classdataobject->name->name) + 32; + buf = (bufsize > sizeof(mybuf)) ? lalloc(bufsize) : mybuf; + + ptr = CSOM_AppendString(buf, "___glue_"); + if (tclass->sominfo->oidl_callstyle == 0) { + if (funcResultClass == 0) { + *(ptr++) = '4'; + } else { + *(ptr++) = '5'; + } + } else { + *(ptr++) = '_'; + } + *(ptr++) = '_'; + + sprintf(numberbuf, "%ld", strlen(tclass->sominfo->classdataobject->name->name)); + ptr = CSOM_AppendString(ptr, numberbuf); + ptr = CSOM_AppendString(ptr, tclass->sominfo->classdataobject->name->name); + *(ptr++) = '_'; + sprintf(numberbuf, "%ld", offset); + ptr = CSOM_AppendString(ptr, numberbuf); + *ptr = 0; + + stubObj = CParser_NewCompilerDefFunctionObject(); + stubObj->nspace = cscope_root; + stubObj->name = GetHashNameNodeExport(buf); + stubObj->u.func.linkname = stubObj->name; + stubObj->type = object->type; + stubObj->qual = object->qual | Q_20000; + stubObj->flags = OBJECT_FLAGS_10; + CScope_AddObject(stubObj->nspace, stubObj->name, OBJ_BASE(stubObj)); + + stub = galloc(sizeof(CSOMStub)); + stub->next = csom_stubs; + stub->object = stubObj; + stub->tclass = tclass; + stub->offset = offset; + csom_stubs = stub; + + if (tclass->sominfo->oidl_callstyle == 0) { + if (funcResultClass == 0) + stub->x10 = 0; + else + stub->x10 = 1; + } else { + stub->x10 = 2; + } + } + + expr = create_objectrefnode(stub->object); + expr->rtype = CDecl_NewPointerType(object->type); + return expr; +} + +ENode *CSOM_MemberVarAccess(BClassList *path, ObjMemberVar *ivar, ENode *thisExpr) { + if (!thisExpr) { + if ( + !cscope_currentfunc || + !cscope_currentclass || + !cscope_is_member_func || + !(thisExpr = CClass_CreateThisSelfExpr()) + ) + { + CError_Error(CErrorStr221); + return NULL; + } + } + + CError_ASSERT(2069, ENODE_IS(thisExpr, EINDIRECT)); + + thisExpr = thisExpr->data.monadic; + + if ( + path->next == NULL && + cscope_currentclass == TYPE_CLASS(path->type) && + ENODE_IS(thisExpr, EOBJREF) && + thisExpr->data.objref->name == this_name_node + ) + { + thisExpr = CSOM_SOMSelfObjectExpr(cscope_currentclass); + } + else + { + CClass_CheckPathAccess(path, NULL, ivar->access); + if (ivar->has_path) + path = OBJ_MEMBER_VAR_PATH(ivar)->path; + while (path->next) + path = path->next; + thisExpr = CSOM_ComputeSOMSelf(TYPE_CLASS(path->type), thisExpr); + } + + thisExpr = makemonadicnode(thisExpr, EINDIRECT); + thisExpr->rtype = path->type; + return CClass_AccessMember(thisExpr, ivar->type, ivar->qual, ivar->offset); +} + +ENode *CSOM_MethodAccess(BClassList *path, Object *func, Boolean flag) { + TypeClass *tclass; + TypeClass *tclass2; + TypeClass *tclass3; + ENode *expr; + SInt32 offset; + ClassList *base; + + CError_ASSERT(2107, path != NULL); + + tclass = TYPE_CLASS(path->type); + if (path->next) + path = path->next; + tclass2 = TYPE_CLASS(path->type); + + if (flag) { + SInt32 counter; + ENode *indirectExpr; + Object *resolveFunc; + + counter = 0; + if (tclass != tclass2) { + for (base = tclass->bases; base; base = base->next) { + counter++; + if (base->base == tclass2) + break; + } + + if (!base) + CError_Error(CErrorStr279); + } + + CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); + expr = create_objectrefnode(tclass3->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); + indirectExpr = makemonadicnode(expr, EINDIRECT); + indirectExpr->rtype = CDecl_NewPointerType(func->type); + + resolveFunc = CSOM_FindRTFunc("somParentNumResolve", "ppip"); + if (!resolveFunc) + return nullnode(); + + expr = funccallexpr( + resolveFunc, + create_objectrefnode(tclass->sominfo->classdataobject), + intconstnode(TYPE(&stsignedint), counter), + indirectExpr, + NULL); + expr->rtype = indirectExpr->rtype; + if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) + expr->flags |= ENODE_FLAG_10; + } else { + CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); + if (copts.som_call_opt && CSOM_CanUseGlueCall(TYPE_FUNC(func->type))) + return CSOM_SOMGlueCall(tclass3, offset, func); + + expr = create_objectrefnode(tclass3->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = CDecl_NewPointerType(func->type); + if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) + expr->flags |= ENODE_FLAG_10; + } + + return expr; +} diff --git a/compiler_and_linker/unsorted/CTemplateClass.c b/compiler_and_linker/unsorted/CTemplateClass.c index e69de29..e0813e8 100644 --- a/compiler_and_linker/unsorted/CTemplateClass.c +++ b/compiler_and_linker/unsorted/CTemplateClass.c @@ -0,0 +1,1632 @@ +#include "compiler/CTemplateClass.h" +#include "compiler/CABI.h" +#include "compiler/CBrowse.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +TemplClass *CTemplClass_GetMasterTemplate(TemplClass *tmclass) { + if (tmclass->inst_parent) { + tmclass = TEMPL_CLASS(tmclass->theclass.nspace->theclass); + CError_ASSERT(42, tmclass->theclass.flags & CLASS_FLAGS_100); + } + + return tmclass; +} + +static void CTemplClass_SetupActionErrorRef(TemplateAction *action, TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_LockErrorPos(&action->source_ref, saved); +} + +static void CTemplClass_RestoreActionErrorRef(TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_UnlockErrorPos(saved); +} + +static void CTemplClass_AppendTemplateAction(TemplClass *tmclass, TemplateAction *action) { + TemplateAction *last; + + action->source_ref = *CPrep_CurStreamElement(); + + if ((last = tmclass->actions)) { + while (last->next) + last = last->next; + last->next = action; + } else { + tmclass->actions = action; + } +} + +static DefAction *CTemplClass_NewDefAction(TypeDeduce *deduce, TemplateAction *action) { + DefAction *defAction = lalloc(sizeof(DefAction)); + defAction->next = deduce->defActions; + defAction->action = action; + deduce->defActions = defAction; + return defAction; +} + +static void CTemplClass_InsertTemplateAction(TemplClass *tmclass, TemplateAction *action) { + action->source_ref = *CPrep_CurStreamElement(); + action->next = tmclass->actions; + tmclass->actions = action; +} + +void CTemplClass_RegisterUsingDecl(TemplClass *tmclass, TypeTemplDep *type, AccessType access) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_USINGDECL; + action->u.usingdecl.type = type; + action->u.usingdecl.access = access; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *di) { + TemplateFriend *tfriend; + TemplateAction *action; + + tfriend = galloc(sizeof(TemplateFriend)); + memclrw(tfriend, sizeof(TemplateFriend)); + + if (tk == '{' && IS_TYPE_FUNC(di->thetype)) { + di->qual |= Q_INLINE; + TYPE_FUNC(di->thetype)->flags |= FUNC_FLAGS_2 | FUNC_FLAGS_800000; + tfriend->fileoffset = cparser_fileoffset; + + CPrep_StreamGetBlock(&tfriend->stream, NULL, 1); + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; + } + + CDecl_PackDeclInfo(&tfriend->decl, di); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_FRIEND; + action->u.tfriend = tfriend; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *type, AccessType access, Boolean is_virtual) { + TemplateAction *action; + ClassList *insert_after; + + if ((insert_after = tmclass->theclass.bases)) { + while (insert_after->next) + insert_after = insert_after->next; + } + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_BASE; + action->u.base.type = type; + action->u.base.insert_after = insert_after; + action->u.base.access = access; + action->u.base.is_virtual = is_virtual; + + CTemplClass_InsertTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *enumtype) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMTYPE; + action->u.enumtype = enumtype; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *objenumconst, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMERATOR; + action->u.enumerator.objenumconst = objenumconst; + action->u.enumerator.initexpr = initexpr ? CInline_CopyExpression(initexpr, CopyMode1) : NULL; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectInit(TemplClass *tmclass, Object *object, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTINIT; + action->u.objectinit.object = object; + action->u.objectinit.initexpr = CInline_CopyExpression(initexpr, CopyMode1); + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *refobj) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTDEF; + action->u.refobj = refobj; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_CompleteClass(TemplClass *templ, DeclE *de) { + templ->lex_order_count = de->x8; + if (de->xC) + templ->flags |= TEMPLCLASS_FLAGS_1; + templ->theclass.flags |= CLASS_FLAGS_2; +} + +static TemplClassInst *CTemplClass_NewInstance(TemplClass *templ, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + ObjTypeTag *tag; + NameSpace *nspace; + HashNameNode *name; + + CError_ASSERT(288, !templ->pspec_owner); + + inst = galloc(sizeof(TemplClassInst)); + memclrw(inst, sizeof(TemplClassInst)); + + inst->next = templ->instances; + templ->instances = inst; + + if (templ->templ__params) + name = CMangler_TemplateInstanceName(templ->theclass.classname, oargs ? oargs : inst_args); + else + name = templ->theclass.classname; + + inst->inst_args = inst_args; + inst->oargs = oargs; + inst->parent = templ->inst_parent; + + nspace = CScope_NewListNameSpace(name, 1); + nspace->theclass = TYPE_CLASS(inst); + if (templ->templ_parent && templ->inst_parent) { + nspace->parent = TYPE_CLASS(templ->inst_parent)->nspace; + } else { + NameSpace *scan = templ->theclass.nspace->parent; + while (scan->is_templ) + scan = scan->parent; + nspace->parent = scan; + } + + inst->theclass.type = TYPECLASS; + inst->theclass.flags = CLASS_FLAGS_800; + inst->theclass.nspace = nspace; + inst->theclass.classname = templ->theclass.classname; + inst->theclass.mode = templ->theclass.mode; + inst->theclass.eflags = templ->theclass.eflags; + inst->templ = templ; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + tag->type = TYPE(inst); + CScope_AddObject(nspace, templ->theclass.classname, OBJ_BASE(tag)); + + return inst; +} + +TemplClassInst *CTemplClass_GetInstance(TemplClass *tmclass, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + + for (inst = tmclass->instances; inst; inst = inst->next) { + CError_ASSERT(353, !oargs); + + if (CTemplTool_EqualArgs(inst_args, inst->oargs ? inst->oargs : inst->inst_args)) + return inst; + } + + return CTemplClass_NewInstance(tmclass, inst_args, oargs); +} + +TemplateMember *CTemplClass_DefineMember(TemplClass *tmclass, Object *object, FileOffsetInfo *foi, TStream *stream) { + TemplateMember *member; + + for (member = tmclass->members; member; member = member->next) { + if (member->object == object) { + CError_Error(CErrorStr333, object); + return member; + } + } + + member = galloc(sizeof(TemplateMember)); + memclrw(member, sizeof(TemplateMember)); + member->next = tmclass->members; + tmclass->members = member; + + member->params = NULL; + member->object = object; + member->fileoffset = *foi; + member->stream = *stream; + + return member; +} + +static void CTemplClass_ParseBody(TemplClass *templ, short mode, SInt32 *offset) { + DeclInfo di; + + templ->align = copts.align_mode; + + memclrw(&di, sizeof(di)); + di.file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition(&di.file2, &di.x60); + di.x60 = *offset; + di.x28 = templ; + + CDecl_ParseClass(&di, mode, 1, 0); + + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di.thetype, NULL); + if (tk != ';') + CError_Error(CErrorStr123); + + CBrowse_NewTemplateClass(templ, di.file2, di.x60, CPrep_BrowserFileOffset() + 1); +} + +void CTemplClass_ParsePartialSpecialization(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + Type *type; + NameSpace *nspace; + TemplArg *args; + TemplPartialSpec *pspec; + TemplClass *templ; + TemplArg *arg; + TemplParam *param; + + nspace = what_is_this->nspace; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if (!(type = CScope_GetLocalTagType(nspace, tkidentifier))) { + CError_Error(CErrorStr140, tkidentifier->name); + return; + } + + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + if ((tk = lex()) != '<') + CError_FATAL(469); + + for (param = params; param; param = param->next) { + switch (param->pid.type) { + case TPT_TYPE: + if (!param->data.typeparam.type) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_NONTYPE: + if (!param->data.paramdecl.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_TEMPLATE: + if (!param->data.templparam.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + default: + CError_FATAL(501); + } + + break; + } + + args = CTempl_ParseUncheckTemplArgs(TEMPL_CLASS(type)->templ__params, 0); + tk = lex(); + + arg = args; + param = TEMPL_CLASS(type)->templ__params; + while (1) { + if (!arg) { + if (!param) + break; + CError_Error(CErrorStr344); + return; + } + if (!param) { + CError_Error(CErrorStr344); + return; + } + if (param->pid.type != arg->pid.type) { + CError_Error(CErrorStr344); + return; + } + arg = arg->next; + param = param->next; + } + + if (CTemplTool_IsSameTemplate(TEMPL_CLASS(type)->templ__params, args)) + CError_Error(CErrorStr344); + + for (pspec = TEMPL_CLASS(type)->pspecs; pspec; pspec = pspec->next) { + if (CTemplTool_EqualParams(pspec->templ->templ__params, params, 0) && CTemplTool_EqualArgs(pspec->args, args)) + break; + } + + if (!pspec) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->templ__params = params; + CDecl_DefineClass(nspace, TEMPL_CLASS(type)->theclass.classname, TYPE_CLASS(templ), mode, 0, 0); + + templ->theclass.flags = CLASS_FLAGS_100; + templ->pspec_owner = TEMPL_CLASS(type); + + pspec = galloc(sizeof(TemplPartialSpec)); + memclrw(pspec, sizeof(TemplPartialSpec)); + + pspec->templ = templ; + pspec->args = CTemplTool_MakeGlobalTemplArgCopy(args); + pspec->next = TEMPL_CLASS(type)->pspecs; + TEMPL_CLASS(type)->pspecs = pspec; + } else { + if ((pspec->templ->theclass.flags & CLASS_FLAGS_2) && tk != ';') { + CError_Error(CErrorStr132, TEMPL_CLASS(type)->theclass.classname->name); + return; + } + + if (tk == ':' || tk == '{') + CTemplTool_EqualParams(pspec->templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(pspec->templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +void CTemplClass_ParseClass(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + TemplClass *templ; + NameSpace *nspace; + Type *type; + UInt8 classDeclSpec = 0; + + nspace = what_is_this->nspace; + if ((tk = lex()) == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&classDeclSpec); + + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + type = CScope_GetLocalTagType(nspace, tkidentifier); + if (!type) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ__params = params; + CDecl_DefineClass(nspace, tkidentifier, TYPE_CLASS(templ), mode, 0, 1); + templ->theclass.flags = CLASS_FLAGS_100; + templ->theclass.eflags = classDeclSpec; + + tk = lex(); + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_100)) { + TemplateAction *action; + + templ->templ_parent = TEMPL_CLASS(nspace->theclass); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(templ->templ_parent, action); + } + } else { + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + templ = TEMPL_CLASS(type); + if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + CTemplTool_MergeDefaultArgs(templ->templ__params, params); + templ->theclass.eflags |= classDeclSpec; + + tk = lex(); + + if ((templ->theclass.flags & CLASS_FLAGS_2) && tk != ';') { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + if (tk != ';') + CTemplTool_EqualParams(templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +static Boolean CTemplClass_TypeParamCompare(TemplArg *arg, Type *type, UInt32 qual) { + return is_typesame(type, arg->data.typeparam.type) && arg->data.typeparam.qual == qual; +} + +static TemplArg *CTemplClass_PartialTemplateArgMatch(TemplPartialSpec *pspec, TemplArg *args, Boolean flag) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec->templ->templ__params, NULL, 1)) + return NULL; + + argA = pspec->args; + argB = args; + while (1) { + if (!argA) { + if (argB) + return NULL; + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return NULL; + } + + if (flag) + return CTemplTool_MakeTemplArgList(&info); + else + return args; + } + + if (!argB) + return NULL; + + if (argA->pid.type != argB->pid.type) + return NULL; + + switch (argA->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.typeparam.type)) { + if (!CTempl_DeduceType( + argA->data.typeparam.type, argA->data.typeparam.qual, + argB->data.typeparam.type, argB->data.typeparam.qual, + info.args, 0, 0 + )) + return NULL; + } else { + if ( + !is_typesame(argA->data.typeparam.type, argB->data.typeparam.type) || + argA->data.typeparam.qual != argB->data.typeparam.qual + ) + return NULL; + } + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argA->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argA); + CError_ASSERT(789, i >= 0); + + if (info.args[i].is_deduced) { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return NULL; + } else { + info.args[i].data.paramdecl.expr = argB->data.paramdecl.expr; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, argA->data.paramdecl.expr)) + return NULL; + } + break; + + case TPT_TEMPLATE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.ttargtype)) { + if (!CTempl_DeduceType( + argA->data.ttargtype, 0, + argB->data.ttargtype, 0, + info.args, 0, 0 + )) + return NULL; + } else { + if (!is_typesame(argA->data.ttargtype, argB->data.ttargtype)) + return NULL; + } + break; + + default: + CError_FATAL(830); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsAtLeastAsSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec2->templ->templ__params, NULL, 1)) + return 0; + + argA = pspec1->args; + argB = pspec2->args; + + while (1) { + if (!argA) { + CError_ASSERT(856, !argB); + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + } + + return 1; + } + + CError_ASSERT(865, argB); + CError_ASSERT(866, argA->pid.type == argB->pid.type); + + switch (argA->pid.type) { + case TPT_TYPE: + if (!CTempl_DeduceType( + argB->data.typeparam.type, argB->data.typeparam.qual, + argA->data.typeparam.type, argA->data.typeparam.qual, + info.args, 0, 0 + )) + return 0; + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argB->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argB); + CError_ASSERT(907, i >= 0); + + if (info.args[i].is_deduced) { + if (argA->data.paramdecl.expr) { + if (!info.args[i].data.paramdecl.expr || !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return 0; + } else { + if (info.args[i].data.paramdecl.expr || argA->pid.index != info.args[i].pid.index) + return 0; + } + } else { + info.args[i].data.paramdecl.expr = argA->data.paramdecl.expr; + info.args[i].pid.index = argA->pid.index; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if ( + !argA->data.paramdecl.expr || + !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, argB->data.paramdecl.expr) + ) + return 0; + } + break; + + case TPT_TEMPLATE: + if (!CTempl_DeduceType( + argB->data.ttargtype, 0, + argA->data.ttargtype, 0, + info.args, 0, 0 + )) + return 0; + break; + + default: + CError_FATAL(955); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsMoreSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + return CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec1, pspec2) && + !CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec2, pspec1); +} + +typedef struct PSpecList { + struct PSpecList *next; + TemplPartialSpec *pspec; +} PSpecList; + +static PSpecList *CTemplClass_FindMostSpecializedPartialSpecializations(PSpecList *list) { + PSpecList **array; + PSpecList *scan; + int i; + int j; + int count; + + scan = list; + count = 0; + while (scan) { + scan = scan->next; + count++; + } + + array = lalloc(sizeof(PSpecList *) * count); + for (i = 0, scan = list; scan; scan = scan->next) + array[i++] = scan; + + for (i = 0; i < count; i++) { + if (array[i]) { + for (j = 0; j < count; j++) { + if (array[j] && i != j && CTemplClass_PartialClassIsMoreSpecialized(array[i]->pspec, array[j]->pspec)) + array[j] = NULL; + } + } + } + + for (i = 0, list = NULL; i < count; i++) { + if (array[i]) { + if (!list) + list = array[i]; + else + array[j]->next = array[i]; + array[i]->next = NULL; + j = i; + } + } + + return list; +} + +Boolean CTemplClass_FindPartialTemplate(TemplArg *args, TemplClass **resultTempl, TemplArg **resultArgs) { + TemplPartialSpec *pspec; + PSpecList *list; + TemplClassInst *inst; + + for (inst = (*resultTempl)->instances; inst; inst = inst->next) { + if (inst->is_instantiated || inst->is_specialized) { + if (CTemplTool_EqualArgs(args, inst->oargs ? inst->oargs : inst->inst_args)) + return 0; + } + } + + list = NULL; + for (pspec = (*resultTempl)->pspecs; pspec; pspec = pspec->next) { + if (CTemplClass_PartialTemplateArgMatch(pspec, args, 0)) { + PSpecList *entry = lalloc(sizeof(PSpecList)); + entry->next = list; + entry->pspec = pspec; + list = entry; + } + } + + if (list) { + if (list->next) { + list = CTemplClass_FindMostSpecializedPartialSpecializations(list); + if (list->next) + CError_Error(CErrorStr346); + } + + if (!list->pspec->templ->templ__params) { + *resultTempl = list->pspec->templ; + *resultArgs = NULL; + return 1; + } + + *resultTempl = list->pspec->templ; + *resultArgs = CTemplClass_PartialTemplateArgMatch(list->pspec, args, 1); + return *resultArgs != NULL; + } else { + return 0; + } +} + +TemplClass *CTemplClass_DefineNestedClass(TemplClass *parent, HashNameNode *name, short mode) { + TemplateAction *action; + TemplClass *templ; + + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ_parent = parent; + templ->templ__params = NULL; + CDecl_DefineClass(parent->theclass.nspace, name, TYPE_CLASS(templ), mode, 0, 1); + + templ->theclass.flags = CLASS_FLAGS_100; + templ->align = copts.align_mode; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(parent, action); + + return templ; +} + +static void CTemplClass_CopyNestedClass(TypeDeduce *deduce, TemplClass *templ) { + ObjTypeTag *tag; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + + if (!templ->templ__params) { + TemplClassInst *inst = CTemplClass_NewInstance(templ, NULL, NULL); + inst->parent = deduce->inst; + inst->theclass.nspace->parent = deduce->inst->theclass.nspace; + + tag->type = TYPE(inst); + } else { + TemplClass *copy = galloc(sizeof(TemplClass)); + memclrw(copy, sizeof(TemplClass)); + + copy->next = ctempl_templates; + ctempl_templates = copy; + + copy->theclass = templ->theclass; + copy->templ_parent = deduce->tmclass; + copy->inst_parent = deduce->inst; + copy->templ__params = templ->templ__params; + copy->members = NULL; + copy->instances = NULL; + copy->pspecs = NULL; + copy->actions = templ->actions; + copy->lex_order_count = templ->lex_order_count; + copy->align = templ->align; + copy->flags = templ->flags; + + tag->type = TYPE(copy); + } + + CScope_AddObject(deduce->inst->theclass.nspace, templ->theclass.classname, OBJ_BASE(tag)); +} + +static void CTemplClass_CopyBaseClasses(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + TemplateAction *action; + ClassList *newBase; + ClassList *templbase; + ClassList *instbase; + ClassList *base; + UInt32 qual = 0; + + for (base = templ->theclass.bases; base; base = base->next) { + ClassList *scan; + newBase = galloc(sizeof(ClassList)); + *newBase = *base; + newBase->next = NULL; + + if ((scan = inst->theclass.bases)) { + while (1) { + if (scan->base == newBase->base) { + CError_Error(CErrorStr131); + break; + } + if (!scan->next) { + scan->next = newBase; + break; + } + scan = scan->next; + } + } else { + inst->theclass.bases = newBase; + } + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_BASE) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(action, &save); + + newBase = galloc(sizeof(ClassList)); + memclrw(newBase, sizeof(ClassList)); + + newBase->base = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, action->u.base.type, &qual)); + newBase->access = action->u.base.access; + newBase->is_virtual = action->u.base.is_virtual; + + if (IS_TYPE_CLASS(newBase->base)) { + if (newBase->base->size == 0) { + CDecl_CompleteType(TYPE(newBase->base)); + IsCompleteType(TYPE(newBase->base)); + } + + if (CDecl_CheckNewBase(TYPE_CLASS(inst), newBase->base, newBase->is_virtual)) { + if (action->u.base.insert_after) { + templbase = templ->theclass.bases; + instbase = inst->theclass.bases; + while (1) { + CError_ASSERT(1222, templbase && instbase); + + if (templbase == action->u.base.insert_after) { + newBase->next = instbase->next; + instbase->next = newBase; + break; + } + + templbase = templbase->next; + instbase = instbase->next; + } + } else { + newBase->next = inst->theclass.bases; + inst->theclass.bases = newBase; + } + } + } else { + CError_Error(CErrorStr131); + } + + CTemplClass_RestoreActionErrorRef(&save); + } + } + + if (inst->theclass.flags & CLASS_FLAGS_20) + CDecl_MakeVBaseList(TYPE_CLASS(inst)); +} + +static void CTemplClass_CopyEnum(TypeDeduce *deduce, TemplateAction *action) { + TypeEnum *destenum; + TypeEnum *srcenum; + ObjEnumConst **destptr; + ObjEnumConst *src; + TemplateAction *scanaction; + + srcenum = action->u.enumtype; + destenum = galloc(sizeof(TypeEnum)); + memclrw(destenum, sizeof(TypeEnum)); + + destenum->type = TYPEENUM; + destenum->size = srcenum->size; + destenum->nspace = deduce->inst->theclass.nspace; + destenum->enumtype = srcenum->enumtype; + destenum->enumname = srcenum->enumname; + + if (destenum->enumname) + CScope_DefineTypeTag(destenum->nspace, destenum->enumname, TYPE(destenum)); + + src = srcenum->enumlist; + destptr = &destenum->enumlist; + while (src) { + ObjEnumConst *dest; + + dest = galloc(sizeof(ObjEnumConst)); + *dest = *src; + + *destptr = dest; + dest->next = NULL; + dest->type = TYPE(destenum); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + src = src->next; + destptr = &(*destptr)->next; + } + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR && scanaction->u.enumerator.objenumconst->type == TYPE(srcenum)) { + CTemplClass_NewDefAction(deduce, action)->enumtype = destenum; + return; + } + } +} + +static void CTemplClass_CompleteEnumType(TypeDeduce *deduce, TemplateAction *action, TypeEnum *destenum) { + TypeEnum *srcenum; + ObjEnumConst *dest; + TemplateAction *scanaction; + ENode *expr; + ObjEnumConst *src; + + srcenum = action->u.enumtype; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR) { + src = scanaction->u.enumerator.objenumconst; + if (src->type == TYPE(srcenum)) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(scanaction, &save); + + dest = destenum->enumlist; + while (dest) { + if (dest->name == src->name) + break; + dest = dest->next; + } + + CError_ASSERT(1332, dest); + + if (scanaction->u.enumerator.initexpr) { + expr = CTemplTool_DeduceExpr(deduce, scanaction->u.enumerator.initexpr); + if (!ENODE_IS(expr, EINTCONST)) { + CError_Error(CErrorStr124); + CTemplClass_RestoreActionErrorRef(&save); + break; + } + } else { + CError_ASSERT(1347, expr); + expr->data.intval = CInt64_Add(expr->data.intval, cint64_one); + } + + dest->val = expr->data.intval; + dest->type = expr->rtype; + CTemplClass_RestoreActionErrorRef(&save); + } + } + } + + CDecl_ComputeUnderlyingEnumType(destenum); +} + +static void CTemplClass_CopyObjMemberVarPath(TypeDeduce *deduce, ObjMemberVarPath *ivar) { + ObjMemberVarPath *copy; + + copy = galloc(sizeof(ObjMemberVarPath)); + *copy = *ivar; + + if (copy->path && copy->path->type == TYPE(deduce->tmclass)) { + copy->path = CClass_GetPathCopy(copy->path, 1); + copy->path->type = TYPE(deduce->inst); + } + + CScope_AddObject(deduce->inst->theclass.nspace, copy->name, OBJ_BASE(copy)); +} + +static void CTemplClass_CopyIVars(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + ObjMemberVar *src; + ObjMemberVar *dest; + ObjMemberVar **destptr; + TemplateAction *scanaction; + + src = templ->theclass.ivars; + destptr = &inst->theclass.ivars; + + while (src) { + CError_ASSERT(1397, !src->has_path); + + dest = galloc(sizeof(ObjMemberVar)); + *dest = *src; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) { + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + break; + } + } + + if (!scanaction) { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + if (dest->type->size == 0) { + CDecl_CompleteType(dest->type); + IsCompleteType(dest->type); + } + } + + if (dest->name && dest->name != no_name_node) + CScope_AddObject(inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + *destptr = dest; + destptr = &dest->next; + src = src->next; + } +} + +static void CTemplClass_CopyObjType(TypeDeduce *deduce, ObjType *src, HashNameNode *name) { + TemplateAction *scanaction; + NameSpaceObjectList *list; + NameSpaceObjectList *newlist; + ObjType *dest; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjType)); + *dest = *src; + + if (scanaction) + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + if ((list = CScope_FindName(deduce->inst->theclass.nspace, name)) && list->object->otype == OT_TYPETAG) { + CError_ASSERT(1470, list->next == NULL); + + newlist = galloc(sizeof(NameSpaceObjectList)); + newlist->object = list->object; + newlist->next = NULL; + + list->object = OBJ_BASE(dest); + list->next = newlist; + } else { + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); + } +} + +static void CTemplClass_CopyObjTypeTag(TypeDeduce *deduce, ObjTypeTag *src, HashNameNode *name) { + UInt32 qual = 0; + ObjTypeTag *dest = galloc(sizeof(ObjTypeTag)); + + *dest = *src; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &qual); + + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyMemberTemplate(TypeDeduce *deduce, Object *src) { + TemplateFunction *desttempl; + Object *dest; + TemplateFunction *srctempl; + TemplateAction *action; + + srctempl = src->u.func.u.templ; + CError_ASSERT(1516, srctempl && srctempl->params); + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + desttempl = galloc(sizeof(TemplateFunction)); + *desttempl = *srctempl; + + desttempl->next = ctempl_templatefuncs; + ctempl_templatefuncs = desttempl; + + desttempl->unk4 = srctempl; + + dest = galloc(sizeof(Object)); + *dest = *src; + + dest->u.func.u.templ = desttempl; + dest->nspace = deduce->inst->theclass.nspace; + + CError_ASSERT(1541, !deduce->x15); + deduce->x15 = 1; + deduce->nindex = srctempl->params->pid.nindex; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + deduce->x15 = 0; + + CError_ASSERT(1553, IS_TYPE_FUNC(dest->type)); + + TYPE_FUNC(dest->type)->flags |= FUNC_FLAGS_100000; + + if ( + (TYPE_FUNC(dest->type)->flags & FUNC_FLAGS_1000) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1560, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyObject(TypeDeduce *deduce, Object *src) { + ObjectTemplated *dest; + TemplateAction *action; + TemplateAction *action2; + Boolean flag; + + flag = 1; + if (src->nspace != deduce->tmclass->theclass.nspace) { + CError_ASSERT(1587, src->datatype == DALIAS); + flag = 0; + } + + if (IS_TEMPL_FUNC(src->type)) { + CTemplClass_CopyMemberTemplate(deduce, src); + return; + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjectTemplated)); + dest->object = *src; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->object.type = CTemplTool_DeduceTypeCopy(deduce, dest->object.type, &dest->object.qual); + + if (flag) + dest->object.nspace = deduce->inst->theclass.nspace; + + dest->object.qual |= Q_400000; + dest->parent = src; + + if (IS_TYPE_FUNC(dest->object.type)) + TYPE_FUNC(dest->object.type)->flags &= ~FUNC_FLAGS_2; + + switch (dest->object.datatype) { + case DDATA: + dest->object.u.data.linkname = NULL; + for (action2 = deduce->tmclass->actions; action2; action2 = action2->next) { + if (action2->type == TAT_OBJECTINIT && action2->u.objectinit.object == src) { + CTemplClass_NewDefAction(deduce, action2)->refobj = OBJ_BASE(dest); + break; + } + } + break; + + case DABSOLUTE: + break; + + case DFUNC: + case DVFUNC: + dest->object.u.func.linkname = NULL; + CError_ASSERT(1650, IS_TYPE_FUNC(dest->object.type)); + CError_ASSERT(1651, !dest->object.u.func.u.templ && !dest->object.u.func.defargdata); + + if ( + (TYPE_FUNC(dest->object.type)->flags & FUNC_FLAGS_1000) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1657, TYPE_FUNC(dest->object.type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->object.type)->args->next; + TYPE_FUNC(dest->object.type)->args->next = arg; + } + + if (TYPE_FUNC(dest->object.type)->flags & FUNC_FLAGS_40) { + CError_ASSERT(1665, IS_TYPE_FUNC(src->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + CError_ASSERT(1668, action); + return; + } + } + + break; + + case DINLINEFUNC: + break; + + case DALIAS: + if (dest->object.u.alias.member && dest->object.u.alias.member->type == TYPE(deduce->tmclass)) { + dest->object.u.alias.member = CClass_GetPathCopy(dest->object.u.alias.member, 1); + dest->object.u.alias.member->type = TYPE(deduce->inst); + } + break; + + case DLOCAL: + case DEXPR: + CError_FATAL(1688); + + default: + CError_FATAL(1691); + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->object.name, OBJ_BASE(dest)); +} + +static void CTemplClass_CompleteObject(TypeDeduce *deduce, TemplateAction *action, ObjBase *refobj) { + if (refobj->otype == OT_MEMBERVAR) { + ObjMemberVar *ivar = OBJ_MEMBER_VAR(refobj); + ivar->type = CTemplTool_DeduceTypeCopy(deduce, ivar->type, &ivar->qual); + + if (ivar->type->size == 0) { + CDecl_CompleteType(ivar->type); + if (copts.experimental) { + if (ivar->next || ivar->type->size != 0 || !IS_TYPE_ARRAY(ivar->type)) + IsCompleteType(ivar->type); + } else { + IsCompleteType(ivar->type); + } + } + } else if (refobj->otype == OT_TYPE) { + ObjType *obj = OBJ_TYPE(refobj); + obj->type = CTemplTool_DeduceTypeCopy(deduce, obj->type, &obj->qual); + } else { + Object *dest; + Object *src; + + CError_ASSERT(1737, refobj->otype == OT_OBJECT); + + dest = OBJECT(refobj); + src = OBJECT(action->u.refobj); + + if (IS_TEMPL_FUNC(src->type)) { + TemplateFunction *templ = src->u.func.u.templ; + CError_ASSERT(1747, templ); + CError_ASSERT(1748, !deduce->x15); + + deduce->x15 = 1; + deduce->nindex = templ->params->pid.nindex; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + deduce->x15 = 0; + + CError_ASSERT(1753, IS_TYPE_FUNC(dest->type)); + TYPE_FUNC(dest->type)->flags |= FUNC_FLAGS_100000; + } else { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + dest->qual |= Q_400000; + + if (IS_TYPE_FUNC(dest->type)) + TYPE_FUNC(dest->type)->flags &= ~FUNC_FLAGS_2; + + switch (dest->datatype) { + case DFUNC: + case DVFUNC: + CError_ASSERT(1769, IS_TYPE_FUNC(dest->type)); + if (TYPE_FUNC(dest->type)->flags & FUNC_FLAGS_40) { + CError_ASSERT(1772, IS_TYPE_FUNC(dest->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + dest->name = CMangler_ConversionFuncName( + TYPE_FUNC(dest->type)->functype, TYPE_FUNC(dest->type)->qual); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + } + } + + if ((TYPE_FUNC(dest->type)->flags & FUNC_FLAGS_1000) && deduce->x17) { + FuncArg *arg; + CError_ASSERT(1786, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + break; + } + } + } +} + +static void CTemplClass_CompleteObjectInit(TypeDeduce *deduce, TemplateAction *action, Object *object) { + ENode *expr = CTemplTool_DeduceExpr(deduce, action->u.objectinit.initexpr); + + if (ENODE_IS(expr, EINTCONST) && (object->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(object->type)) { + object->u.data.u.intconst = expr->data.intval; + object->qual |= Q_10000 | Q_20000; + } else { + CError_Error(CErrorStr354, object->name->name); + } +} + +static void CTemplClass_CopyNameSpace(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + NameSpaceName *nsname; + NameSpaceObjectList *list; + + CError_ASSERT(1830, !templ->theclass.nspace->is_hash); + + for (nsname = templ->theclass.nspace->data.list; nsname; nsname = nsname->next) { + for (list = &nsname->first; list; list = list->next) { + switch (list->object->otype) { + case OT_ENUMCONST: + break; + case OT_MEMBERVAR: + if (OBJ_MEMBER_VAR(list->object)->has_path) + CTemplClass_CopyObjMemberVarPath(deduce, OBJ_MEMBER_VAR_PATH(list->object)); + break; + case OT_TYPE: + CTemplClass_CopyObjType(deduce, OBJ_TYPE(list->object), nsname->name); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_FATAL(1854); + case OT_OBJECT: + CTemplClass_CopyObject(deduce, OBJECT(list->object)); + break; + default: + CError_FATAL(1861); + } + } + } +} + +static void CTemplClass_CopyUsingDecl(TypeDeduce *deduce, TypeTemplDep *type, AccessType access) { + TypeClass *tclass; + UInt32 qual = 0; + + CError_ASSERT(1878, IS_TYPE_TEMPLATE(type) && type->dtype == TEMPLDEP_QUALNAME); + + tclass = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, TYPE(type->u.qual.type), &qual)); + if (!IS_TYPE_CLASS(tclass)) { + CError_Error(CErrorStr340, type->u.qual.name->name); + return; + } + + CDecl_CompleteType(TYPE(tclass)); + CScope_AddClassUsingDeclaration(TYPE_CLASS(deduce->inst), tclass, type->u.qual.name, access); +} + +static void CTemplClass_CopyFriend(TypeDeduce *deduce, TemplateFriend *tfriend) { + TemplArg *arg; + Object *funcobj; + Boolean flag; + CScopeSave saveScope; + DeclInfo di; + + CDecl_UnpackDeclInfo(&di, &tfriend->decl); + + if (CTemplTool_IsTemplateArgumentDependentType(di.thetype)) + di.thetype = CTemplTool_DeduceTypeCopy(deduce, di.thetype, &di.qual); + + if (di.expltargs) { + di.expltargs = CTemplTool_MakeGlobalTemplArgCopy(di.expltargs); + for (arg = di.expltargs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + break; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + arg->data.paramdecl.expr = CTemplTool_DeduceExpr(deduce, arg->data.paramdecl.expr); + break; + case TPT_TEMPLATE: + default: + CError_FATAL(1930); + } + } + } + + if (IS_TYPE_FUNC(di.thetype)) { + CScope_SetNameSpaceScope(CScope_FindGlobalNS(deduce->inst->theclass.nspace), &saveScope); + funcobj = CDecl_GetFunctionObject(&di, NULL, &flag, 0); + CScope_RestoreScope(&saveScope); + + if (funcobj) { + CDecl_AddFriend(TYPE_CLASS(deduce->inst), funcobj, NULL); + if (tfriend->stream.tokens) + CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(deduce->inst), &tfriend->fileoffset, &tfriend->stream, 0); + } else { + CError_Error(CErrorStr201); + } + } else { + CError_ASSERT(1963, IS_TYPE_CLASS(di.thetype)); + CDecl_AddFriend(TYPE_CLASS(deduce->inst), NULL, TYPE_CLASS(di.thetype)); + } +} + +Boolean CTempl_InstantiateTemplateClass(TypeClass *tclass) { + TemplClassInst *inst; + ParserTryBlock *tryBlock; + TemplateAction *action; + DefAction *defAction; + UInt8 saveAlignMode; + + TypeDeduce deduce; + TemplStack stack; + CScopeSave saveScope; + DeclE declE; + TemplClass *templ; + TStreamElement *saveErrorRef; + TemplArg *inst_args; + + CError_ASSERT(1989, tclass->flags & CLASS_FLAGS_800); + + if (tclass->flags & CLASS_FLAGS_2) + return 1; + + inst = TEMPL_CLASS_INST(tclass); + if (inst->is_specialized) + return 0; + + templ = inst->templ; + if (!(templ->flags & TEMPLCLASS_FLAGS_2)) + templ = CTemplClass_GetMasterTemplate(templ); + + if (templ->pspecs && CTemplClass_FindPartialTemplate(inst->inst_args, &templ, &inst_args)) { + CError_ASSERT(2013, !inst->oargs); + inst->templ = templ; + inst->oargs = inst->inst_args; + inst->inst_args = inst_args; + } + + if (!(templ->theclass.flags & CLASS_FLAGS_2)) + return 0; + + if (inst->is_instantiated) + return 0; + + inst->is_instantiated = 1; + CScope_SetClassScope(tclass, &saveScope); + CTemplTool_PushInstance(&stack, tclass, NULL); + + tryBlock = trychain; + trychain = NULL; + + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = templ; + deduce.inst = inst; + deduce.params = templ->templ__params; + deduce.args = inst->inst_args; + + CError_ASSERT(2045, !templ->theclass.sominfo); + CError_ASSERT(2047, !templ->theclass.objcinfo); + CError_ASSERT(2049, !templ->theclass.vtable); + + inst->theclass.flags |= templ->theclass.flags & + (CLASS_FLAGS_ABSTRACT | CLASS_FLAGS_10 | CLASS_FLAGS_20 | CLASS_FLAGS_40 | CLASS_FLAGS_2000); + + CTemplClass_CopyBaseClasses(&deduce, inst, templ); + + deduce.x17 = (inst->theclass.flags & CLASS_FLAGS_20) && !(templ->theclass.flags & CLASS_FLAGS_20); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyNestedClass(&deduce, action->u.tclasstype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMTYPE: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyEnum(&deduce, action); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_FRIEND: + case TAT_ENUMERATOR: + case TAT_BASE: + case TAT_OBJECTINIT: + case TAT_USINGDECL: + case TAT_OBJECTDEF: + break; + default: + CError_FATAL(2094); + } + } + + CTemplClass_CopyIVars(&deduce, inst, templ); + CTemplClass_CopyNameSpace(&deduce, inst, templ); + + CError_ASSERT(2105, !templ->theclass.friends); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + break; + case TAT_ENUMTYPE: + for (defAction = deduce.defActions; defAction; defAction = defAction->next) { + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteEnumType(&deduce, action, defAction->enumtype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_FRIEND: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyFriend(&deduce, action->u.tfriend); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMERATOR: + break; + case TAT_BASE: + break; + case TAT_OBJECTINIT: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2136, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObjectInit(&deduce, action, OBJECT(defAction->refobj)); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_USINGDECL: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyUsingDecl(&deduce, action->u.usingdecl.type, action->u.usingdecl.access); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_OBJECTDEF: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2156, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObject(&deduce, action, defAction->refobj); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + } + } + + memclrw(&declE, sizeof(declE)); + declE.x8 = templ->lex_order_count; + declE.xC = templ->flags & TEMPLCLASS_FLAGS_1; + + saveAlignMode = copts.align_mode; + copts.align_mode = templ->align; + CDecl_CompleteClass(&declE, TYPE_CLASS(inst)); + copts.align_mode = saveAlignMode; + + if (templ->theclass.align > inst->theclass.align) { + inst->theclass.align = templ->theclass.align; + inst->theclass.size += CABI_StructSizeAlignValue(TYPE(inst), inst->theclass.size); + } + + CTemplTool_PopInstance(&stack); + CScope_RestoreScope(&saveScope); + trychain = tryBlock; + + return 1; +} diff --git a/compiler_and_linker/unsorted/CTemplateFunc.c b/compiler_and_linker/unsorted/CTemplateFunc.c index e69de29..847b103 100644 --- a/compiler_and_linker/unsorted/CTemplateFunc.c +++ b/compiler_and_linker/unsorted/CTemplateFunc.c @@ -0,0 +1,1383 @@ +#include "compiler/CTemplateFunc.h" +#include "compiler/CABI.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" + +static Boolean ctempl_conversion_deduction; +static UInt8 ctempl_explicitargs_nindex; +static int ctempl_explicitargs_num; +static Boolean ctempl_explicitargs_all; + +// forward decls +static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); +static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); + +static void CTemplFunc_SetupTypeDeduce(TypeDeduce *deduce, TemplateFunction *templ, TemplArg *args) { + memclrw(deduce, sizeof(TypeDeduce)); + if (templ->tfunc->nspace->theclass && (templ->tfunc->nspace->theclass->flags & CLASS_FLAGS_100)) + deduce->tmclass = TEMPL_CLASS(templ->tfunc->nspace->theclass); + deduce->params = templ->params; + deduce->args = args; +} + +Boolean CTempl_CanDeduceFunc(Object *object, TypeFunc *tfunc, TemplArg *args) { + DeduceInfo info; + int i; + + if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object)->params, args, 0)) { + if (CTempl_DeduceType(object->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) { + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + } + return 1; + } + } + + return 0; +} + +static TemplFuncInstance *CTempl_GetCreateFuncInstance(Object *funcobj, TemplArg *args, Object *object2) { + TemplFuncInstance *inst; + TemplateFunction *templ; + Object *instobj; + TemplParam *param; + TemplArg *arg; + TemplArg *last; + short paramCount; + short i; + TypeDeduce deduce; + + templ = CTemplTool_GetFuncTempl(funcobj); + + paramCount = 0; + param = templ->params; + while (param) { + param = param->next; + paramCount++; + } + + for (i = 1, arg = args; i < paramCount; i++, arg++) + arg->next = arg + 1; + arg->next = NULL; + + for (inst = templ->instances; inst; inst = inst->next) { + if (CTemplTool_EqualArgs(inst->args, args)) { + if (object2) + inst->object = object2; + return inst; + } + } + + inst = galloc(sizeof(TemplFuncInstance)); + memclrw(inst, sizeof(TemplFuncInstance)); + + for (i = 0, arg = NULL; i < paramCount; i++) { + if (arg) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + arg = last; + } + + *last = *args; + last->next = NULL; + args++; + + if (last->pid.type == TPT_NONTYPE) { + CError_ASSERT(114, last->data.paramdecl.expr); + last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); + } + } + + inst->args = arg; + inst->next = templ->instances; + templ->instances = inst; + + if (!object2) { + instobj = CParser_NewFunctionObject(NULL); + instobj->access = funcobj->access; + instobj->nspace = funcobj->nspace; + instobj->sclass = funcobj->sclass; + instobj->qual = funcobj->qual | Q_80000; + instobj->name = templ->name; + instobj->u.func.inst = inst; + + CTemplFunc_SetupTypeDeduce(&deduce, templ, inst->args); + if (funcobj->nspace->theclass && (funcobj->nspace->theclass->flags & CLASS_FLAGS_800)) { + deduce.tmclass = TEMPL_CLASS_INST(funcobj->nspace->theclass)->templ; + deduce.inst = TEMPL_CLASS_INST(funcobj->nspace->theclass); + } + + instobj->type = CTemplTool_DeduceTypeCopy(&deduce, funcobj->type, &instobj->qual); + inst->object = instobj; + + if (IS_TYPE_FUNC(instobj->type)) { + TYPE_FUNC(instobj->type)->flags &= ~FUNC_FLAGS_2; + if (TYPE_FUNC(instobj->type)->flags & FUNC_FLAGS_1000) { + FuncArg *funcarg; + CError_ASSERT(152, TYPE_FUNC(instobj->type)->flags & FUNC_FLAGS_METHOD); + CError_ASSERT(153, funcarg = TYPE_FUNC(instobj->type)->args); + + if (TYPE_METHOD(instobj->type)->theclass->flags & CLASS_FLAGS_20) + CError_ASSERT(156, funcarg = funcarg->next); + + if (funcarg->next) + CDecl_CheckCtorIntegrity(funcarg->next, TYPE_METHOD(instobj->type)->theclass); + } + } + + if ((instobj->qual & Q_INLINE) && templ->stream.tokens) + CInline_AddTemplateFunctionAction(instobj, templ, inst); + + } else { + inst->object = object2; + } + + return inst; +} + +TemplFuncInstance *CTempl_CheckFuncInstance(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2) { + DeduceInfo info; + int i; + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object1)->params, args, 1)) + return NULL; + + if (!CTempl_DeduceType(object1->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) + return NULL; + + i = 0; + while (i < info.maxCount) { + if (!info.args[i++].is_deduced) + return NULL; + } + + return CTempl_GetCreateFuncInstance(object1, info.args, object2); +} + +TemplFuncInstance *CTempl_DeduceFunc(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2, Boolean flag) { + return CTempl_CheckFuncInstance(object1, tfunc, args, object2); +} + +static Boolean CTempl_FuncIsAtLeastAsSpecialized(Object *func1, Object *func2) { + int i; + FuncArg *arg1; + FuncArg *arg2; + Type *type1; + Type *type2; + UInt32 qual1; + UInt32 qual2; + DeduceInfo info; + + arg1 = TYPE_FUNC(func2->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) + arg1 = arg1->next; + + i = 0; + while (1) { + if (!arg1) + break; + CError_ASSERT(231, arg1->type != &stvoid); + if (arg1 == &elipsis) + break; + if (arg1 == &oldstyle) + break; + arg1 = arg1->next; + i++; + } + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(func2)->params, NULL, 0)) + return 0; + + arg1 = TYPE_FUNC(func1->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func1->type))) + arg1 = arg1->next; + + arg2 = TYPE_FUNC(func2->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) + arg2 = arg2->next; + + while (i > 0) { + if (!arg1) + break; + if (arg1 == &elipsis) + break; + if (arg1 == &oldstyle) + break; + + CError_ASSERT(255, arg2); + + type1 = arg1->type; + qual1 = arg1->qual & (Q_CONST | Q_VOLATILE); + qual2 = arg2->qual & (Q_CONST | Q_VOLATILE); + type2 = arg2->type; + + if (!CTemplTool_IsTemplateArgumentDependentType(type2)) { + if (IS_TYPE_REFERENCE(type1)) + type1 = TPTR_TARGET(type1); + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + + if (IS_TYPE_REFERENCE(type2)) + type2 = TPTR_TARGET(type2); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + + if (!is_typesame(type1, type2) || qual1 != qual2) + return 0; + } else { + if (!CTempl_DeduceType(type2, qual2, type1, qual1, info.args, 0, 0)) + return 0; + } + + arg1 = arg1->next; + arg2 = arg2->next; + i--; + } + + return 1; +} + +Boolean CTempl_FuncIsMoreSpecialized(Object *object1, Object *object2) { + return CTempl_FuncIsAtLeastAsSpecialized(object1, object2) && !CTempl_FuncIsAtLeastAsSpecialized(object2, object1); +} + +Object *CTempl_PartialOrdering(Object *object, ObjectList *list, int count) { + int i; + int j; + Object **array; + ObjectList *scan; + Object *arrayBuffer[16]; + + for (count = 1, scan = list; scan; scan = scan->next) { + if (IS_TEMPL_FUNC(scan->object->type)) + count++; + } + + if (count > 16) + array = lalloc(sizeof(Object *) * count); + else + array = arrayBuffer; + + array[0] = object; + for (i = 1, scan = list; scan; scan = scan->next) { + if (IS_TEMPL_FUNC(scan->object->type)) + array[i++] = scan->object; + } + + for (i = 0; i < count; i++) { + if (array[i]) { + for (j = 0; j < count; j++) { + if (array[j] && i != j && CTempl_FuncIsMoreSpecialized(array[i], array[j])) + array[j] = NULL; + } + } + } + + object = NULL; + + for (i = 0; i < count; i++) { + if (array[i]) { + if (object) + return NULL; + object = array[i]; + } + } + + return object; +} + +int CTempl_GetTemplateArgumentExpressionIndex(TemplArg *arg) { + CError_ASSERT(529, arg->data.paramdecl.expr); + + if (ENODE_IS(arg->data.paramdecl.expr, ETEMPLDEP) && arg->data.paramdecl.expr->data.templdep.subtype == TDE_PARAM) + return arg->data.paramdecl.expr->data.templdep.u.pid.index; + + return -1; +} + +static Type *CTempl_GetSpecifiedType(TemplateFunction *templ, Type *type, UInt32 qual, TemplArg *args, UInt32 *resultQual) { + TypeDeduce deduce; + + CTemplFunc_SetupTypeDeduce(&deduce, templ, args); + *resultQual = qual; + return CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); +} + +static Boolean CTempl_DeduceTemplateArgs(TemplArg *args1, TemplArg *args2, TemplArg *argArray) { + int index; + + while (1) { + if (!args1) + return !args2; + if (!args2) + return 0; + + if (args1->pid.type != args2->pid.type) + return 0; + + switch (args1->pid.type) { + case TPT_TYPE: + if (!CTempl_DeduceType1( + args1->data.typeparam.type, args1->data.typeparam.qual, + args2->data.typeparam.type, args2->data.typeparam.qual, + argArray, 1 + )) + return 0; + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(args1->data.paramdecl.expr)) { + index = CTempl_GetTemplateArgumentExpressionIndex(args1); + if (index < 0) + return 1; + + if (argArray[index].is_deduced) { + if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, argArray[index].data.paramdecl.expr)) + return 0; + } else { + argArray[index].data.paramdecl.expr = args2->data.paramdecl.expr; + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + } + } else { + if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, args1->data.paramdecl.expr)) + return 0; + } + break; + + case TPT_TEMPLATE: + if (!IS_TEMPL_CLASS(args2->data.ttargtype)) + return 0; + + index = args1->pid.index; + if (argArray[index].is_deduced) { + if (args2->data.ttargtype != argArray[index].data.ttargtype) + return 0; + } else { + argArray[index].data.ttargtype = args2->data.ttargtype; + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + break; + + default: + CError_FATAL(640); + } + + args1 = args1->next; + args2 = args2->next; + } +} + +static Boolean CTempl_DeduceTemplDepTemplate(TemplClass *templ1, TemplArg *args1, TemplClass *templ2, TemplArg *args2, TemplArg *argArray) { + if (templ1 != templ2) + return 0; + + return CTempl_DeduceTemplateArgs(args2, args1, argArray); +} + +static Boolean CTempl_DeduceTemplateType(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray) { + TemplClassInst *scan; + + for (scan = templ->instances; scan; scan = scan->next) { + if (scan == inst) + return CTempl_DeduceTemplateArgs(args, scan->oargs ? scan->oargs : scan->inst_args, argArray); + } + + return 0; +} + +static Boolean CTempl_DeduceTemplateTypeBase(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray, Boolean flag) { + ClassList *base; + + if (CTempl_DeduceTemplateType(templ, args, inst, argArray)) + return 1; + + if (flag) { + for (base = inst->theclass.bases; base; base = base->next) { + if (CTempl_DeduceTemplateType(templ, args, TEMPL_CLASS_INST(base->base), argArray)) { + ctempl_conversion_deduction = 1; + return 1; + } + } + + for (base = inst->theclass.bases; base; base = base->next) { + if (CTempl_DeduceTemplateTypeBase(templ, args, TEMPL_CLASS_INST(base->base), argArray, 1)) { + ctempl_conversion_deduction = 1; + return 1; + } + } + } + + return 0; +} + +static Boolean CTempl_DeduceQualTemplate(TypeTemplDep *type1, TemplArg *args1, Type *type2, TemplArg *argArray) { + int index; + + if (type1->dtype == TEMPLDEP_ARGUMENT && type1->u.pid.type == TPT_TEMPLATE) { + index = type1->u.pid.index; + if (IS_TEMPL_CLASS_INST(type2)) { + if (argArray[index].is_deduced) { + if (argArray[index].data.ttargtype != TYPE(TEMPL_CLASS_INST(type2)->templ)) + return 0; + } else { + argArray[index].data.ttargtype = TYPE(TEMPL_CLASS_INST(type2)->templ); + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + + return CTempl_DeduceTemplateArgs(args1, TEMPL_CLASS_INST(type2)->inst_args, argArray); + } + + if (IS_TYPE_TEMPLATE(type2)) { + if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) { + if (argArray[index].is_deduced) { + if (argArray[index].data.ttargtype != TYPE(TYPE_TEMPLATE(type2)->u.templ.templ)) + return 0; + } else { + argArray[index].data.ttargtype = TYPE(TYPE_TEMPLATE(type2)->u.templ.templ); + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + + return CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.templ.args, argArray); + } + + if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_QUALTEMPL) { + return + CTempl_DeduceTypeTemplDep(type1, 0, TYPE(TYPE_TEMPLATE(type2)->u.qualtempl.type), 0, argArray, 1) && + CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.qualtempl.args, argArray); + } + } + } + + return 0; +} + +static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { + Type *tmptype; + UInt32 tmpqual; + short index; + Boolean f; + UInt32 modqual; + + switch (type1->dtype) { + case TEMPLDEP_ARGUMENT: + index = type1->u.pid.index; + tmptype = type2; + if (type1->u.pid.type == TPT_TEMPLATE) { + if (argArray[index].is_deduced) { + if (!is_typesame(tmptype, argArray[index].data.ttargtype)) + return 0; + } else { + argArray[index].data.ttargtype = type2; + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + return 1; + } + + switch (type2->type) { + case TYPEPOINTER: + tmpqual = qual2; + f = 0; + qual2 = TPTR_QUAL(type2); + modqual = qual2; + + if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { + modqual &= ~Q_CONST; + f = 1; + } + if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { + modqual &= ~Q_VOLATILE; + f = 1; + } + + if (f) { + tmptype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(tmptype) = *TYPE_POINTER(type2); + TPTR_QUAL(tmptype) = modqual; + } + + if (flag && (qual2 | modqual) != (qual1 | modqual)) + return 0; + + break; + + case TYPEMEMBERPOINTER: + tmpqual = qual2; + f = 0; + qual2 = TYPE_MEMBER_POINTER(type2)->qual; + modqual = qual2; + + if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { + modqual &= ~Q_CONST; + f = 1; + } + if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { + modqual &= ~Q_VOLATILE; + f = 1; + } + + if (f) { + tmptype = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(tmptype) = *TYPE_MEMBER_POINTER(type2); + TYPE_MEMBER_POINTER(tmptype)->qual = modqual; + } + + if (flag && (qual2 | modqual) != (qual1 | modqual)) + return 0; + + break; + + default: + tmpqual = 0; + if ((qual2 & Q_CONST) && !(qual1 & Q_CONST)) + tmpqual |= Q_CONST; + if ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE)) + tmpqual |= Q_VOLATILE; + + if (flag && (qual2 | tmpqual) != (qual1 | tmpqual)) + return 0; + } + + if (argArray[index].is_deduced) { + if (!is_typesame(tmptype, argArray[index].data.typeparam.type) || tmpqual != argArray[index].data.typeparam.qual) + return 0; + } else { + argArray[index].data.typeparam.type = tmptype; + argArray[index].data.typeparam.qual = tmpqual; + argArray[index].pid.type = TPT_TYPE; + argArray[index].is_deduced = 1; + } + return 1; + + case TEMPLDEP_QUALNAME: + return 1; + + case TEMPLDEP_TEMPLATE: + if (IS_TYPE_CLASS(type2)) + return CTempl_DeduceTemplateTypeBase( + type1->u.templ.templ, type1->u.templ.args, + TEMPL_CLASS_INST(type2), argArray, 0); + + if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) + return CTempl_DeduceTemplDepTemplate( + TYPE_TEMPLATE(type2)->u.templ.templ, TYPE_TEMPLATE(type2)->u.templ.args, + type1->u.templ.templ, type1->u.templ.args, + argArray + ); + + return 0; + + case TEMPLDEP_ARRAY: + if (IS_TYPE_ARRAY(type2)) { + SInt32 elements; + + if (!CTempl_DeduceType1(type1->u.array.type, qual1, TPTR_TARGET(type2), qual2, argArray, flag)) + return 0; + + if (ENODE_IS(type1->u.array.index, EINTCONST)) { + CError_ASSERT(961, TPTR_TARGET(type2)->size); + return (type2->size / TPTR_TARGET(type2)->size) == CInt64_GetULong(&type1->u.array.index->data.intval); + } + + if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) + return 1; + + CError_ASSERT(970, TPTR_TARGET(type2)->size); + + elements = type2->size / TPTR_TARGET(type2)->size; + index = type1->u.array.index->data.templdep.u.pid.index; + if (argArray[index].is_deduced) { + CError_ASSERT(976, ENODE_IS(argArray[index].data.paramdecl.expr, EINTCONST)); + return elements == CInt64_GetULong(&argArray[index].data.paramdecl.expr->data.intval); + } else { + argArray[index].data.paramdecl.expr = intconstnode(CABI_GetPtrDiffTType(), elements); + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + return 1; + } + } else if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_ARRAY) { + if (!CTempl_DeduceType1(type1->u.array.type, qual1, TYPE_TEMPLATE(type2)->u.array.type, qual2, argArray, flag)) + return 0; + + if (ENODE_IS(type1->u.array.index, EINTCONST)) { + return ENODE_IS(TYPE_TEMPLATE(type2)->u.array.index, EINTCONST) && + CInt64_Equal(type1->u.array.index->data.intval, TYPE_TEMPLATE(type2)->u.array.index->data.intval); + } + + if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) + return 1; + + index = type1->u.array.index->data.templdep.u.pid.index; + if (argArray[index].is_deduced) { + return CTemplTool_EqualExprTypes(TYPE_TEMPLATE(type2)->u.array.index, argArray[index].data.paramdecl.expr); + } else { + argArray[index].data.paramdecl.expr = TYPE_TEMPLATE(type2)->u.array.index; + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + return 1; + } + } + + return 0; + + case TEMPLDEP_QUALTEMPL: + return CTempl_DeduceQualTemplate(type1->u.qualtempl.type, type1->u.qualtempl.args, type2, argArray); + + case TEMPLDEP_BITFIELD: + default: + CError_FATAL(1022); + return 1; + } +} + +static Boolean CTempl_DeduceFuncType(TypeFunc *tfunc1, TypeFunc *tfunc2, TemplArg *argArray) { + FuncArg *arg1; + FuncArg *arg2; + Type *type2; + Type *type1; + UInt32 qual2; + UInt32 qual1; + + arg1 = tfunc1->args; + arg2 = tfunc2->args; + + if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc1) && !IS_TYPEFUNC_METHOD(tfunc2)) { + CError_ASSERT(1045, arg1); + arg1 = arg1->next; + } + + while (1) { + if (arg1 == NULL) + return !arg2; + if (arg1 == &oldstyle) + return arg2 == &oldstyle; + if (arg1 == &elipsis) + return arg2 == &elipsis; + + if (arg2 == NULL || arg2 == &oldstyle || arg2 == &elipsis) + return 0; + + qual2 = arg2->qual; + type2 = CParser_RemoveTopMostQualifiers(arg2->type, &qual2); + + qual1 = arg1->qual; + type1 = CParser_RemoveTopMostQualifiers(arg1->type, &qual1); + + if (!CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, 1)) + return 0; + + arg1 = arg1->next; + arg2 = arg2->next; + } +} + +static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { + while (1) { + switch (type1->type) { + case TYPETEMPLATE: + return CTempl_DeduceTypeTemplDep(TYPE_TEMPLATE(type1), qual1, type2, qual2, argArray, flag); + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + return type1 == type2; + + case TYPEMEMBERPOINTER: + if (type1->type != type2->type || TYPE_MEMBER_POINTER(type1)->qual != TYPE_MEMBER_POINTER(type2)->qual) + return 0; + if (!CTempl_DeduceType1(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray, flag)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + case TYPEARRAY: + if (type2->type != TYPEARRAY) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEPOINTER: + if (type2->type != TYPEPOINTER || TPTR_QUAL(type1) != TPTR_QUAL(type2)) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEFUNC: + if (type1->type != type2->type) + return 0; + + if (CTempl_DeduceType1(TYPE_FUNC(type1)->functype, TYPE_FUNC(type1)->qual, TYPE_FUNC(type2)->functype, TYPE_FUNC(type2)->qual, argArray, flag)) + return CTempl_DeduceFuncType(TYPE_FUNC(type1), TYPE_FUNC(type2), argArray); + + return 0; + + default: + CError_FATAL(1124); + } + } +} + +static Boolean CTempl_DeduceType2(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + while (1) { + switch (type1->type) { + case TYPEPOINTER: + if (type2->type != TYPEPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEMEMBERPOINTER: + if (type2->type != TYPEMEMBERPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) + return 0; + if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + default: + if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) + return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); + return 0; + } + } +} + +static Boolean CTempl_DeduceType3(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + Boolean flag = 0; + + while (1) { + switch (type1->type) { + case TYPEPOINTER: + flag = 1; + if (type2->type != TYPEPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEMEMBERPOINTER: + flag = 1; + if (type2->type != TYPEMEMBERPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) + return 0; + if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + default: + if (!flag) + return 0; + if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) + return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); + return 0; + } + } +} + +static Boolean CTempl_DeduceType4(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + if (IS_TYPE_POINTER_ONLY(type1)) { + if (!IS_TYPE_POINTER_ONLY(type2)) + return 0; + + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type1), TPTR_QUAL(type2))) + return 0; + + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + } + + if (IS_TYPE_TEMPLATE(type1) && TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_TEMPLATE && IS_TYPE_CLASS(type2)) { + if (CParser_IsSameOrMoreCVQualified(qual1, qual2)) + return CTempl_DeduceTemplateTypeBase( + TYPE_TEMPLATE(type1)->u.templ.templ, + TYPE_TEMPLATE(type1)->u.templ.args, + TEMPL_CLASS_INST(type2), + argArray, + 1); + else + return 0; + } + + return 0; +} + +Boolean CTempl_DeduceType(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag1, Boolean flag2) { + Boolean flag31; + Boolean flag8; + + flag31 = 0; + flag8 = 1; + + if (flag1 || flag2) { + if (IS_TYPE_REFERENCE(type1)) { + type1 = TPTR_TARGET(type1); + flag31 = 1; + } else { + switch (type2->type) { + case TYPEFUNC: + type2 = CDecl_NewPointerType(type2); + break; + case TYPEARRAY: + type2 = CDecl_NewPointerType(TPTR_TARGET(type2)); + break; + } + + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + } + flag8 = 0; + } + + if (CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, flag8)) + return 1; + + if (flag1 || flag2) { + if (flag31 && CTempl_DeduceType2(type1, qual1, type2, qual2, argArray)) + return 1; + if (CTempl_DeduceType3(type1, qual1, type2, qual2, argArray)) + return 1; + if (flag1 && CTempl_DeduceType4(type1, qual1, type2, qual2, argArray)) + return 1; + } + + return 0; +} + +static Boolean CTempl_TypeNeedsDeduction(Type *type) { + FuncArg *arg; + Boolean result; + + while (1) { + switch (type->type) { + case TYPETEMPLATE: + switch (TYPE_TEMPLATE(type)->dtype) { + case TEMPLDEP_ARGUMENT: + if ( + TYPE_TEMPLATE(type)->u.pid.index >= ctempl_explicitargs_num || + TYPE_TEMPLATE(type)->u.pid.nindex != ctempl_explicitargs_nindex + ) + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_QUALNAME: + CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); + return 1; + + case TEMPLDEP_TEMPLATE: + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_ARRAY: + CTempl_TypeNeedsDeduction(TYPE_TEMPLATE(type)->u.array.type); + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_QUALTEMPL: + CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qualtempl.type)); + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_BITFIELD: + default: + CError_FATAL(1357); + } + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + return 0; + + case TYPEMEMBERPOINTER: + result = 0; + if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty1)) + result = 1; + if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty2)) + result = 1; + return result; + + case TYPEPOINTER: + case TYPEARRAY: + type = TPTR_TARGET(type); + continue; + + case TYPEFUNC: + result = 0; + for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis; arg = arg->next) { + if (CTempl_TypeNeedsDeduction(arg->type)) + result = 1; + } + + if (CTempl_TypeNeedsDeduction(TYPE_FUNC(type)->functype)) + result = 1; + return result; + + default: + CError_FATAL(1389); + } + } +} + +static Boolean CTempl_MatchTemplFunc(Object *object, DeduceInfo *info, FuncArg *args, ENodeList *exprs, Match13 *match13ptr) { + Match13 match13; + int i; + + memclrw(&match13, sizeof(match13)); + + while (1) { + if (!args || args->type == &stvoid) { + if (!exprs) + break; + return 0; + } + + if (args == &elipsis) + break; + if (args == &oldstyle) + break; + + if (!exprs) { + if (args->dexpr) + break; + return 0; + } + + ctempl_explicitargs_nindex = info->x12C; + ctempl_explicitargs_num = info->count; + ctempl_explicitargs_all = 1; + + if (CTempl_TypeNeedsDeduction(args->type)) { + if (!ctempl_explicitargs_all) { + UInt32 cv2; + UInt32 cv1; + Type *type2; + Type *type1; + UInt32 qual2; + UInt32 qual1; + + type1 = args->type; + qual1 = args->qual & (Q_CONST | Q_VOLATILE); + + type2 = exprs->node->rtype; + qual2 = ENODE_QUALS(exprs->node); + + if (IS_TYPE_REFERENCE(type1)) { + type1 = TPTR_TARGET(type1); + cv1 = CParser_GetCVTypeQualifiers(type1, qual1); + cv2 = CParser_GetCVTypeQualifiers(type2, qual2); + if ( + (!(cv1 & Q_CONST) && (cv2 & Q_CONST)) || + (!(cv1 & Q_VOLATILE) && (cv2 & Q_VOLATILE)) + ) + return 0; + + if (!(cv1 & Q_CONST) && !CExpr_IsLValue(exprs->node)) + return 0; + } + + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + + if (ENODE_IS(exprs->node, EOBJREF) && IS_TEMPL_FUNC(exprs->node->data.objref->type)) + return 0; + + if (ENODE_IS(exprs->node, EOBJLIST)) { + NameSpaceObjectList *list; + + for (list = exprs->node->data.objlist.list; list; list = list->next) { + if (list->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(list->object)->type)) + break; + } + + if (list) + return 0; + + if (IS_TYPE_FUNC(type2)) + type2 = CDecl_NewPointerType(type2); + } + + ctempl_conversion_deduction = 0; + if (!CTempl_DeduceType(type1, qual1, type2, qual2, info->args, 1, 0)) + return 0; + + if (ctempl_conversion_deduction) + match13.anotherm5.x4++; + else + match13.anotherm5.x0++; + + if (IS_TYPE_POINTER_ONLY(args->type)) + CExpr_MatchCV(type2, qual2, args->type, args->qual, &match13); + + } else { + Type *type; + UInt32 qual; + + type = CTempl_GetSpecifiedType(CTemplTool_GetFuncTempl(object), args->type, args->qual, info->args, &qual); + if (type && !CExpr_MatchAssign(type, qual, exprs->node, &match13)) + return 0; + } + } else { + if (copts.old_argmatch && !CExpr_MatchAssign(args->type, args->qual, exprs->node, &match13)) + return 0; + } + + exprs = exprs->next; + args = args->next; + } + + for (i = 0; i < info->maxCount; i++) { + if (!info->args[i].is_deduced) + return 0; + info->args[i].next = &info->args[i + 1]; + } + info->args[info->maxCount].next = NULL; + + return CExpr_MatchCompare(object, match13ptr, &match13); +} + +void CTempl_FuncMatch(NameSpaceObjectList *list, TemplArg *args, ENodeList *argexprs, Match13 *match13ptr, ENode *expr) { + Object *obj; + Object *success; + Object *object1; + FuncMatchArgs funcMatchArgs; + DeduceInfo info; + DeduceInfo info2; + + object1 = match13ptr->obj; + success = NULL; + while (list) { + obj = OBJECT(list->object); + if ( + obj->otype == OT_OBJECT && + IS_TEMPL_FUNC(obj->type) && + CExpr_GetFuncMatchArgs(obj, argexprs, expr, &funcMatchArgs) && + CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(obj)->params, args, 0) && + CTempl_MatchTemplFunc(obj, &info, funcMatchArgs.args, funcMatchArgs.exprs, match13ptr) + ) + { + info2 = info; + if (info.args == info.argBuffer) + info2.args = info2.argBuffer; + success = obj; + } + list = list->next; + } + + if (success) { + if (match13ptr->list) { + ENodeList *argexpr = argexprs; + int argexprcount = 0; + while (argexpr) { + argexpr = argexpr->next; + argexprcount++; + } + + obj = CTempl_PartialOrdering(match13ptr->obj, match13ptr->list, argexprcount); + if (!obj) { + CError_OverloadedFunctionError(match13ptr->obj, match13ptr->list); + match13ptr->list = NULL; + if (object1) + match13ptr->obj = object1; + else + match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; + } else { + NameSpaceObjectList mylist; + mylist.next = NULL; + mylist.object = OBJ_BASE(obj); + memclrw(match13ptr, sizeof(Match13)); + CTempl_FuncMatch(&mylist, args, argexprs, match13ptr, expr); + } + } else { + match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; + } + } else { + match13ptr->obj = object1; + } +} + +static Boolean CExpr_DeduceFromObjList(FuncArg *arg, NameSpaceObjectList *list, DeduceInfo *info) { + TemplArg *savebuf; + NameSpaceObjectList *scan; + SInt32 size; + + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(scan->object)->type)) + return 0; + } + + size = sizeof(TemplArg) * info->maxCount; + savebuf = lalloc(size); + + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { + Object *obj; + + memcpy(savebuf, info->args, size); + + obj = OBJECT(scan->object); + if (CTempl_DeduceType( + arg->type, arg->qual & (Q_CONST | Q_VOLATILE), + obj->type, obj->qual, + savebuf, 1, 0 + )) + { + memcpy(info->args, savebuf, size); + return 1; + } + } + } + + return 0; +} + +Object *CTempl_DeduceFromFunctionCall(Object *funcobj, TemplArg *templargs, ENodeList *argexprs) { + DeduceInfo info; + FuncArg *arg; + int i; + + CError_ASSERT(1655, IS_TEMPL_FUNC(funcobj->type)); + + if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, templargs, 0)) { + arg = TYPE_FUNC(funcobj->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(funcobj->type))) { + CError_ASSERT(1664, arg); + arg = arg->next; + } + + while (1) { + if (!arg || arg->type == &stvoid) { + if (argexprs) + return NULL; + break; + } + + if (arg == &elipsis) + break; + if (arg == &oldstyle) + break; + + if (!argexprs) { + if (arg->dexpr) + break; + return NULL; + } + + ctempl_explicitargs_nindex = info.x12C; + ctempl_explicitargs_num = info.count; + ctempl_explicitargs_all = 1; + + if (CTempl_TypeNeedsDeduction(arg->type) && !ctempl_explicitargs_all) { + ENode *node = argexprs->node; + + if (ENODE_IS(node, EOBJREF) && IS_TEMPL_FUNC(node->data.objref->type)) + return NULL; + + if (ENODE_IS(node, EOBJLIST)) { + if (!CExpr_DeduceFromObjList(arg, node->data.objlist.list, &info)) + return NULL; + } else { + if (!CTempl_DeduceType( + arg->type, arg->qual & (Q_CONST | Q_VOLATILE), + node->rtype, ENODE_QUALS(node), + info.args, 1, 0)) + return NULL; + } + } + + argexprs = argexprs->next; + arg = arg->next; + } + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + info.args[i].next = &info.args[i + 1]; + } + info.args[info.maxCount].next = NULL; + + return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; + } else { + return NULL; + } +} + +Object *CTempl_DeduceFromConversion(Object *funcobj, Type *type, UInt32 qual) { + DeduceInfo info; + int i; + + CError_ASSERT(1745, IS_TEMPL_FUNC(funcobj->type)); + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, NULL, 0)) + return NULL; + + ctempl_explicitargs_nindex = info.x12C; + ctempl_explicitargs_num = info.count; + ctempl_explicitargs_all = 1; + + if (!CTempl_TypeNeedsDeduction(TYPE_FUNC(funcobj->type)->functype)) + return NULL; + + if (!CTempl_DeduceType(TYPE_FUNC(funcobj->type)->functype, TYPE_FUNC(funcobj->type)->qual, type, qual, info.args, 0, 1)) + return NULL; + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + info.args[i].next = &info.args[i + 1]; + } + info.args[info.maxCount].next = NULL; + + return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; +} + +static int CTemplFunc_TemplateNestLevel(NameSpace *nspace) { + int level = 0; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_900)) + level++; + nspace = nspace->parent; + } + + return level; +} + +static Boolean CTemplFunc_SameFuncType(TypeFunc *a, TypeFunc *b) { + FuncArg *arg1; + FuncArg *arg2; + + CError_ASSERT(1800, IS_TYPE_FUNC(a) && IS_TYPE_FUNC(b)); + + if (!is_typesame(a->functype, b->functype)) + return 0; + + if (a->qual != b->qual) + return 0; + + if ((a->flags & (FUNC_FLAGS_PASCAL | FUNC_FLAGS_F0000000)) != (b->flags & (FUNC_FLAGS_PASCAL | FUNC_FLAGS_F0000000))) + return 0; + + arg1 = a->args; + if ((a->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(a)->x26) { + CError_ASSERT(1808, arg1); + arg1 = arg1->next; + } + + arg2 = b->args; + if ((b->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(b)->x26) { + CError_ASSERT(1814, arg2); + arg2 = arg2->next; + } + + return is_arglistsame(arg1, arg2); +} + +Object *CTempl_TemplateFunctionCheck(DeclInfo *di, NameSpaceObjectList *nsol) { + TemplArg *arg; + TemplFuncInstance *inst; + Object *object; + + for (arg = di->expltargs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + break; + continue; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + break; + continue; + default: + CError_FATAL(1844); + } + + break; + } + + if (arg) { + while (nsol) { + object = OBJECT(nsol->object); + if ( + object->otype == OT_OBJECT && + IS_TEMPL_FUNC(object->type) && + CTemplTool_IsSameTemplate(CTemplTool_GetFuncTempl(object)->params, di->expltargs) && + CTemplFunc_SameFuncType(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(di->thetype)) + ) + return OBJECT(nsol->object); + + nsol = nsol->next; + } + } else { + while (nsol) { + object = OBJECT(nsol->object); + if ( + object->otype == OT_OBJECT && + IS_TEMPL_FUNC(object->type) && + (inst = CTempl_DeduceFunc(object, TYPE_FUNC(di->thetype), di->expltargs, NULL, 1)) + ) + { + if (di->x3C) { + if (!(di->qual & Q_INLINE)) { + if (!inst->is_specialized) + inst->object->qual &= ~Q_INLINE; + } else { + inst->object->qual |= Q_INLINE; + } + + if (!inst->is_specialized && inst->is_instantiated) + CError_Error(CErrorStr335); + + if (di->x3C != (CTemplFunc_TemplateNestLevel(inst->object->nspace) + 1)) + CError_Warning(CErrorStr335); + + inst->is_specialized = 1; + di->x3C = 0; + } + + CTemplTool_MergeArgNames(TYPE_FUNC(di->thetype), TYPE_FUNC(inst->object->type)); + di->x38 = CTemplTool_GetFuncTempl(OBJECT(nsol->object)); + return inst->object; + } + nsol = nsol->next; + } + } + + CError_ResetErrorSkip(); + CError_Error(CErrorStr335); + di->x3C = 0; + return NULL; +} diff --git a/compiler_and_linker/unsorted/CTemplateNew.c b/compiler_and_linker/unsorted/CTemplateNew.c index e69de29..4fdfc37 100644 --- a/compiler_and_linker/unsorted/CTemplateNew.c +++ b/compiler_and_linker/unsorted/CTemplateNew.c @@ -0,0 +1,1881 @@ +#include "compiler/CTemplateNew.h" +#include "compiler/CBrowse.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/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateClass.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +TemplClass *ctempl_templates; +TemplateFunction *ctempl_templatefuncs; +TemplStack *ctempl_curinstance; +static jmp_buf ctempl_parseparse; +static Boolean ctempl_scanfuncparams; + +// forward decls +static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex); +static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag); + +void CTempl_Setup(void) { + ctempl_curinstance = NULL; + ctempl_templates = NULL; + ctempl_templatefuncs = NULL; + ctempl_instdepth = 0; + ctempl_scanfuncparams = 0; +} + +void CTempl_Cleanup(void) { +} + +static short CTempl_MemberParseLex(void) { + switch ((tk = lex())) { + case ';': + case '=': + case '{': + case '}': + longjmp(ctempl_parseparse, 1); + } + + return tk; +} + +static void CTempl_MemberParseTemplArgList(void) { + struct { + char ch; + char flag; + } stack[256]; + int pos; + + stack[0].ch = '>'; + stack[0].flag = 1; + pos = 0; + while (1) { + switch (CTempl_MemberParseLex()) { + case '<': + if (stack[pos].flag) { + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = '>'; + stack[pos].flag = 1; + } + continue; + case '(': + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = ')'; + stack[pos].flag = 0; + continue; + case '[': + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = ']'; + stack[pos].flag = 0; + continue; + case '>': + if (!(stack[pos].flag)) + continue; + case ')': + case ']': + break; + default: + continue; + } + + if (tk != stack[pos].ch) + longjmp(ctempl_parseparse, 1); + if (--pos < 0) + break; + } +} + +static Type *CTempl_MemberParseTempl(HashNameNode *name) { + Type *type; + + type = CScope_GetTagType(cscope_current, name); + if (!type || !IS_TEMPL_CLASS(type)) + longjmp(ctempl_parseparse, 1); + + CTempl_MemberParseTemplArgList(); + if (lookahead() != TK_COLON_COLON) + return NULL; + CTempl_MemberParseLex(); + + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + switch (lookahead()) { + case '(': + case ')': + case ';': + case '=': + case '[': + return type; + case TK_COLON_COLON: + CTempl_MemberParseLex(); + continue; + default: + return NULL; + } + break; + case '~': + case TK_OPERATOR: + return type; + default: + return NULL; + } + } +} + +static Boolean CTempl_ParseTemplateMember(void) { + HashNameNode *name; + SInt32 state; + + CPrep_UnLex(); + CPrep_TokenStreamGetState(&state); + + if (setjmp(ctempl_parseparse) == 0) { + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + name = tkidentifier; + switch (lookahead()) { + case '<': + CTempl_MemberParseLex(); + if (CTempl_MemberParseTempl(name)) { + CError_FATAL(228); + return 1; + } + break; + case TK_COLON_COLON: + CTempl_MemberParseLex(); + while (1) { + if (CTempl_MemberParseLex() != TK_IDENTIFIER) + break; + if (lookahead() != TK_COLON_COLON) + break; + CTempl_MemberParseLex(); + } + break; + } + break; + case 0: + return 0; + default: + continue; + } + break; + } + + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + name = tkidentifier; + if (CTempl_MemberParseLex() == '<') { + if (CTempl_MemberParseTempl(name)) { + CError_FATAL(265); + return 1; + } + } + break; + case 0: + return 0; + default: + continue; + } + break; + } + } + + CPrep_TokenStreamSetState(&state); + tk = lex(); + return 0; +} + +static Type *CTempl_ParseTemplArgType(UInt32 *resultQual) { + DeclInfo di; + + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.storageclass) + CError_Error(CErrorStr177); + if (di.x48) + CError_Error(CErrorStr121); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); + + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr121); + + CTemplTool_CheckTemplArgType(di.thetype); + + *resultQual = di.qual; + return di.thetype; +} + +static ENode *CTempl_ParseTemplArgExpr(Type *type, UInt32 qual) { + ENode *expr; + ENode *copy; + + disallowgreaterthan = 1; + if (copts.old_argmatch) + expr = conv_assignment_expression(); + else + expr = assignment_expression(); + disallowgreaterthan = 0; + + if (type && !CTemplTool_IsTemplateArgumentDependentType(type) && !IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { + expr = argumentpromotion(expr, type, qual, 1); + if (IS_TYPE_POINTER_ONLY(type)) { + if (ENODE_IS(expr, ETYPCON) && ENODE_IS(expr->data.monadic, EINTCONST)) + expr = expr->data.monadic; + if (ENODE_IS(expr, EINTCONST)) + expr->rtype = type; + } + } + + if (!IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { + if (!copts.old_argmatch) + expr = pointer_generation(expr); + + switch (expr->type) { + case EINTCONST: + break; + case EOBJREF: + if (CParser_HasInternalLinkage2(expr->data.objref)) + CError_Error(CErrorStr357); + break; + case EOBJLIST: + CError_Error(CErrorStr199); + expr = nullnode(); + break; + default: + CError_Error(CErrorStr371); + expr = nullnode(); + } + + copy = galloc(sizeof(ENode)); + *copy = *expr; + return copy; + } else { + return CInline_CopyExpression(expr, CopyMode1); + } +} + +static Type *CTempl_ParseTemplArgTempl(TemplParam *params) { + CScopeParseResult pr; + + if ( + (tk != TK_IDENTIFIER && tk != TK_COLON_COLON) || + !CScope_ParseDeclName(&pr) || + !pr.x8 + ) + { + CError_Error(CErrorStr121); + tk = lex(); + return NULL; + } + + if (IS_TEMPL_CLASS(pr.x8)) { + if (params && !CTemplTool_EqualParams(params->data.templparam.plist, TEMPL_CLASS(pr.x8)->templ__params, 0)) { + CError_Error(CErrorStr235); + tk = lex(); + return NULL; + } + } else { + if (!CTemplTool_IsTemplateArgumentDependentType(pr.x8)) + CError_Error(CErrorStr146); + } + + tk = lex(); + return pr.x8; +} + +static UInt8 CTempl_GetTemplateNestIndex(NameSpace *nspace) { + UInt8 count = 0; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_900)) + count++; + nspace = nspace->parent; + } + + return count; +} + +static TemplParam *CTempl_ParseParam(NameSpace *nspace, TemplParam *paramList, int index, UInt8 nindex) { + TemplParam *param; + DeclInfo di; + short startToken; + SInt32 savedState; + + param = galloc(sizeof(TemplParam)); + memclrw(param, sizeof(TemplParam)); + + param->pid.index = index; + param->pid.nindex = nindex; + + CPrep_TokenStreamGetState(&savedState); + + switch ((startToken = tk)) { + case TK_CLASS: + case TK_TYPENAME: + if ((tk = lex()) == TK_IDENTIFIER) { + param->name = tkidentifier; + tk = lex(); + } + + switch (tk) { + case ',': + case '>': + break; + case '=': + tk = lex(); + param->data.typeparam.type = CTempl_ParseTemplArgType(¶m->data.typeparam.qual); + break; + default: + param->name = NULL; + CPrep_TokenStreamSetState(&savedState); + tk = startToken; + goto defaultProc; + } + + param->pid.type = TPT_TYPE; + break; + + case TK_TEMPLATE: + if ((tk = lex()) != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + param->data.templparam.plist = CTempl_ParseParamList(nspace, 0); + + if (tk == '>') + tk = lex(); + else + CError_Error(CErrorStr231); + + if (tk == TK_CLASS) + tk = lex(); + else + CError_Error(CErrorStr121); + + if (tk == TK_IDENTIFIER) { + param->name = tkidentifier; + tk = lex(); + } + + if (tk == '=') { + tk = lex(); + param->data.templparam.defaultarg = CTempl_ParseTemplArgTempl(param); + } + + param->pid.type = TPT_TEMPLATE; + break; + + default: + defaultProc: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); + + scandeclarator(&di); + + switch (di.thetype->type) { + case TYPEARRAY: + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + break; + case TYPEFUNC: + di.thetype = CDecl_NewPointerType(di.thetype); + break; + case TYPEMEMBERPOINTER: + CError_Error(CErrorStr190); + di.thetype = TYPE(&stsignedint); + break; + case TYPEINT: + case TYPEENUM: + case TYPETEMPLATE: + case TYPEPOINTER: + break; + default: + CError_Error(CErrorStr229); + di.thetype = TYPE(&stsignedint); + } + + di.thetype = CParser_RemoveTopMostQualifiers(di.thetype, &di.qual); + param->name = di.name; + param->data.paramdecl.type = di.thetype; + param->data.paramdecl.qual = di.qual; + if (tk == '=') { + tk = lex(); + param->data.paramdecl.defaultarg = CTempl_ParseTemplArgExpr(di.thetype, di.qual); + } + + param->pid.type = TPT_NONTYPE; + break; + } + + if (param->name) + CTemplTool_InsertTemplateParameter(nspace, param); + + return param; +} + +static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex) { + TemplParam *params; + TemplParam **ptr; + TemplParam *param; + TemplParam *scan; + int index; + + params = NULL; + index = 0; + ptr = ¶ms; + + while (1) { + param = CTempl_ParseParam(nspace, params, index, nindex); + if (!param) + break; + + if (param->name) { + for (scan = params; scan; scan = scan->next) { + if (scan->name == param->name) + CError_Error(CErrorStr122, param->name->name); + } + } + + *ptr = param; + ptr = ¶m->next; + + if (tk != ',') + break; + + tk = lex(); + index++; + } + + if (!params) + CError_Error(CErrorStr229); + + return params; +} + +TemplArg *CTempl_ParseUncheckTemplArgs(TemplParam *params, Boolean is_global) { + TemplArg *args; + TemplArg *last; + int index; + + if (tk != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + if ((tk = lex()) == '>') + return NULL; + + args = NULL; + index = 0; + while (1) { + if (is_global) { + if (args) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + args = last; + } + } else { + if (args) { + last->next = lalloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + args = last; + } + } + + last->next = NULL; + + if (!params) { + Type *type; + UInt32 qual; + Boolean flag; + + last->pid.index = index; + last->pid.nindex = 0; + + if ((type = CParser_ParseTypeID(&qual, &flag))) { + if (flag) { + last->data.ttargtype = type; + last->pid.type = TPT_TEMPLATE; + } else { + last->data.typeparam.type = type; + last->data.typeparam.qual = qual; + last->pid.type = TPT_TYPE; + } + } else { + last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); + last->pid.type = TPT_NONTYPE; + } + } else { + last->pid = params->pid; + switch (last->pid.type) { + case TPT_TYPE: + last->data.typeparam.type = CTempl_ParseTemplArgType(&last->data.typeparam.qual); + break; + case TPT_NONTYPE: + last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); + break; + case TPT_TEMPLATE: + if (!(last->data.ttargtype = CTempl_ParseTemplArgTempl(params))) + return NULL; + break; + default: + CError_FATAL(674); + } + params = params->next; + } + + if (tk == '>') + return args; + + if (tk != ',') { + CError_Error(CErrorStr116); + return NULL; + } + + tk = lex(); + index++; + } +} + +static TemplArg *CTempl_ParseTemplArgs(TemplClass **resultTempl, TemplArg **resultArgs) { + TemplParam *param; + TemplParam *params; + TemplArg *args; + TemplArg **ptr; + TemplArg *arg; + + params = (*resultTempl)->templ__params; + *resultArgs = NULL; + + if (tk != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + + param = params; + args = NULL; + ptr = &args; + + while (param) { + arg = galloc(sizeof(TemplArg)); + memclrw(arg, sizeof(TemplArg)); + + *ptr = arg; + ptr = &arg->next; + + arg->pid = param->pid; + + if (tk != '>') { + switch (arg->pid.type) { + case TPT_TYPE: + arg->data.typeparam.type = CTempl_ParseTemplArgType(&arg->data.typeparam.qual); + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { + Type *type; + UInt32 qual; + + type = CTemplTool_DeduceArgDepType(args, param->data.paramdecl.type, param->data.paramdecl.qual, &qual); + arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(type, qual); + } else { + arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(param->data.paramdecl.type, param->data.paramdecl.qual); + } + break; + + case TPT_TEMPLATE: + if (!(arg->data.ttargtype = CTempl_ParseTemplArgTempl(param))) + return NULL; + break; + + default: + CError_FATAL(742); + } + + if (tk != '>') { + if (tk != ',') { + CError_Error(CErrorStr232); + return NULL; + } + + if ((tk = lex()) == '>') { + CError_Error(CErrorStr232); + return NULL; + } + } + } else { + switch (arg->pid.type) { + case TPT_TYPE: + if (!param->data.typeparam.type) { + CError_Error(CErrorStr232); + return NULL; + } + + arg->data.typeparam.type = param->data.typeparam.type; + arg->data.typeparam.qual = param->data.typeparam.qual; + + if (CTemplTool_IsTemplateArgumentDependentType(param->data.typeparam.type)) { + TypeDeduce deduce; + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = *resultTempl; + deduce.inst = NULL; + deduce.params = params; + deduce.args = args; + + arg->data.typeparam.qual = param->data.typeparam.qual; + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(&deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + break; + + case TPT_NONTYPE: + if (!param->data.paramdecl.defaultarg) { + CError_Error(CErrorStr232); + return NULL; + } + + if (IS_TYPE_TEMPLDEPEXPR(param->data.paramdecl.defaultarg->rtype)) { + TypeDeduce deduce; + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = *resultTempl; + deduce.inst = NULL; + deduce.params = params; + deduce.args = args; + + arg->data.paramdecl.expr = CInline_CopyExpression( + CTemplTool_DeduceExpr(&deduce, param->data.paramdecl.defaultarg), CopyMode1); + } else { + arg->data.paramdecl.expr = param->data.paramdecl.defaultarg; + } + break; + + case TPT_TEMPLATE: + if (!param->data.templparam.defaultarg) { + CError_Error(CErrorStr232); + return NULL; + } + + if (IS_TEMPL_CLASS(param->data.templparam.defaultarg)) { + arg->data.ttargtype = param->data.templparam.defaultarg; + break; + } + + if (CTemplTool_IsTemplateArgumentDependentType(param->data.templparam.defaultarg)) { + CError_Error(CErrorStr190); + return NULL; + } + + CError_FATAL(817); + + default: + CError_FATAL(820); + } + } + + param = param->next; + } + + if (tk != '>') { + CError_Error(CErrorStr231); + return NULL; + } + + if ((*resultTempl)->pspecs) + return args; + + return args; +} + +Type *CTempl_ParseTemplTemplParam(TypeTemplDep *type) { + TemplArg *args; + Type *newType; + + tk = lex(); + if (!(args = CTempl_ParseUncheckTemplArgs(NULL, 1))) { + CError_Error(CErrorStr121); + return TYPE(&stsignedint); + } + + newType = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL); + TYPE_TEMPLATE(newType)->u.qualtempl.type = type; + TYPE_TEMPLATE(newType)->u.qualtempl.args = args; + return newType; +} + +Type *CTempl_ClassGetType(TemplClass *templ) { + TemplClass *owner; + TemplArg *ownerArgs; + TemplArg *args; + Type *type; + + owner = templ; + if (templ->pspec_owner) + owner = templ->pspec_owner; + + if (!(args = CTempl_ParseTemplArgs(&owner, &ownerArgs))) + return &stvoid; + + if ((type = CTemplTool_IsDependentTemplate(owner, args))) + return type; + + return TYPE(CTemplClass_GetInstance(owner, args, ownerArgs)); +} + +static void CTempl_SetupClassParamNameSpace(DeclFucker *what_is_this, TypeClass *tclass) { + cscope_current = tclass->nspace; +} + +Boolean CTempl_IsQualifiedMember(DeclInfo *di, Type *type, NameSpace **resultnspace) { + if ( + TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME && + (type = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type))) + ) + { + *resultnspace = TYPE_CLASS(type)->nspace; + CError_ASSERT(948, di->fucker34 && (*resultnspace)->theclass); + + CTempl_SetupClassParamNameSpace(di->fucker34, (*resultnspace)->theclass); + di->fucker34 = NULL; + return 1; + } + + return 0; +} + +static void *CTempl_ParseMemberFunction(int unk1, int unk2, int unk3, Object *func) { + // no idea what should've been here, it's not called + + CError_ASSERT(974, TYPE_FUNC(func->type)->flags & FUNC_FLAGS_METHOD); + + return NULL; +} + +static void CTempl_ParseMember(TemplParam *params, TemplClass *templ, DeclInfo *di, SInt32 *startOffset) { + Object *object; + NameSpaceObjectList *nsol; + TStream stream; + CPrepFileInfo *file; + SInt32 offset; + Boolean saveForceLoc; + TemplateMember *member; + + if (templ->theclass.flags & CLASS_FLAGS_100) + di->thetype = CTemplTool_ResolveMemberSelfRefs(templ, di->thetype, &di->qual); + + if (IS_TYPE_FUNC(di->thetype)) { + Boolean flag; + if (!(object = CDecl_GetFunctionObject(di, NULL, &flag, 0))) { + CError_Error(CErrorStr140, di->name->name); + return; + } + + if (tk != '{' && tk != TK_TRY && tk != ':') { + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); + return; + } + + if ( + (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) && + (!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_100000) || object->u.func.u.templ->instances) + ) + CError_Error(CErrorStr333, object); + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800000 | FUNC_FLAGS_2; + + CPrep_StreamGetBlock(&stream, NULL, 1); + saveForceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + CPrep_BrowserFilePosition(&file, &offset); + gForceSourceLoc = saveForceLoc; + + if (file && file->recordbrowseinfo && *startOffset >= 0 && offset > *startOffset) + CBrowse_NewFunction(object, file, file, *startOffset, offset + 1); + } else { + if (!(nsol = CScope_GetLocalObject(templ->theclass.nspace, di->name))) { + CError_Error(CErrorStr140, di->name->name); + return; + } + + object = OBJECT(nsol->object); + if (object->otype != OT_OBJECT) { + CError_Error(CErrorStr122, di->name->name); + return; + } + + if ( + !is_typesame(di->thetype, object->type) || + (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) != (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) + ) + { + CError_Error(CErrorStr249, CError_GetObjectName(object), object->type, object->qual, di->thetype, di->qual); + return; + } + + CError_ASSERT(1070, object->datatype == DDATA); + + CPrep_StreamGetSemicolon(&stream, NULL); + } + + if (stream.tokens) { + if (IS_TEMPL_FUNC(object->type) != 0) { + if (!CTemplTool_EqualParams(object->u.func.u.templ->params, params, 0)) + CError_Error(CErrorStr235); + + object->u.func.u.templ->stream = stream; + } else { + if (!(templ->theclass.flags & CLASS_FLAGS_100)) { + CError_Error(CErrorStr190); + return; + } + + member = CTemplClass_DefineMember(templ, object, &cparser_fileoffset, &stream); + if (templ->templ__params) { + if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { + CError_Error(CErrorStr235); + return; + } + + member->params = params; + } + } + } +} + +static TemplateFunction *CTempl_DeclareTemplateFunction(DeclInfo *di, TemplParam *params, TypeClass *tclass, AccessType access, Boolean flag) { + TemplateFunction *templ; + Object *object; + + if (tclass) { + CError_ASSERT(1122, cscope_current->theclass); + di->thetype = TYPE(CDecl_MakeTypeMemberFunc(TYPE_FUNC(di->thetype), cscope_current->theclass, flag)); + } else { + access = ACCESSPUBLIC; + } + + templ = galloc(sizeof(TemplateFunction)); + memclrw(templ, sizeof(TemplateFunction)); + + templ->next = ctempl_templatefuncs; + ctempl_templatefuncs = templ; + + templ->params = params; + templ->name = di->name; + templ->deftoken = symdecltoken; + + object = CParser_NewFunctionObject(NULL); + object->access = access; + object->name = di->name; + object->u.func.linkname = CParser_GetUniqueName(); + object->type = di->thetype; + object->qual = di->qual | Q_80000; + object->sclass = di->storageclass; + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_100000; + object->u.func.u.templ = templ; + + if (di->qual & Q_INLINE) + object->sclass = TK_STATIC; + + templ->tfunc = object; + CScope_AddObject(cscope_current, di->name, OBJ_BASE(object)); + + return templ; +} + +static void CTempl_ParseTemplateFunction(TemplateFunction *templ, TypeClass *tclass, SInt32 *startOffset) { + Object *object; + CPrepFileInfo *file; + SInt32 offset; + Boolean saveForceLoc; + + object = templ->tfunc; + + if (tk == '{' || tk == ':' || tk == TK_TRY) { + if (tclass) { + object->qual |= Q_INLINE; + object->sclass = TK_STATIC; + } + + if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) + CError_Error(CErrorStr333, object); + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_2 | FUNC_FLAGS_800000; + + CPrep_StreamGetBlock(&templ->stream, NULL, 0); + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; + + saveForceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + CPrep_BrowserFilePosition(&file, &offset); + gForceSourceLoc = saveForceLoc; + + if (file && *startOffset >= 0 && offset > *startOffset) { + templ->srcfile = file; + templ->startoffset = *startOffset; + templ->endoffset = offset + 1; + if (cparamblkptr->browseOptions.recordTemplates && file->recordbrowseinfo) + CBrowse_NewTemplateFunc(templ); + } + + } else { + if (tk != ';') + CError_Error(CErrorStr121); + } +} + +static HashNameNode *CTempl_FindConversionFuncName(TypeClass *tclass, Type *type, UInt32 qual) { + Object *object; + CScopeObjectIterator iter; + + CScope_InitObjectIterator(&iter, tclass->nspace); + do { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + return NULL; + } while ( + !IS_TYPE_FUNC(object->type) || + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_40) || + (TYPE_FUNC(object->type)->qual & (Q_CONST | Q_VOLATILE)) != (qual & (Q_CONST | Q_VOLATILE)) || + !is_typesame(TYPE_FUNC(object->type)->functype, type) + ); + + return object->name; +} + +static void CTempl_ParseConversionFunctionTemplate(DeclInfo *di, DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access) { + tk = lex(); + if (!tclass) { + CError_Error(CErrorStr121); + return; + } + + tclass->flags |= CLASS_FLAGS_40; + CError_QualifierCheck(di->qual & ~Q_INLINE); + + conversion_type_name(di); + CDecl_NewConvFuncType(di); + + if (cscope_current->is_templ) { + CError_ASSERT(1260, cscope_current == what_is_this->nspace); + cscope_current = what_is_this->nspace->parent; + } + + CTempl_ParseTemplateFunction(CTempl_DeclareTemplateFunction(di, params, tclass, access, 0), tclass, startOffset); +} + +static void CTempl_ParseFunctionOrMemberTemplate(DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access, Boolean mysteryFlag) { + NameSpaceObjectList *nsol; + Object *object; + TemplParam *param; + TemplateFunction *templfunc; + Boolean disallowCVFlag; + TypeClass *tclass2; + Type *type; + UInt32 qual; + DeclInfo di; + + for (param = params; param; param = param->next) { + switch (param->pid.type) { + case TPT_TYPE: + if (param->data.typeparam.type) { + CError_Error(CErrorStr378); + param->data.typeparam.type = NULL; + } + break; + case TPT_NONTYPE: + if (param->data.paramdecl.defaultarg) { + CError_Error(CErrorStr378); + param->data.paramdecl.defaultarg = NULL; + } + break; + case TPT_TEMPLATE: + if (param->data.templparam.defaultarg) { + CError_Error(CErrorStr378); + param->data.templparam.defaultarg = NULL; + } + break; + default: + CError_FATAL(1317); + } + } + + disallowCVFlag = 0; + ctempl_scanfuncparams = 1; + + memclrw(&di, sizeof(di)); + di.x51 = mysteryFlag; + + if (tk == TK_OPERATOR) { + CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); + return; + } + + CParser_GetDeclSpecs(&di, 1); + if (tk == ';' && IS_TEMPL_CLASS(di.thetype)) + return; + + if (di.x10 || di.x14) { + TypeFunc *tfunc; + + if (di.x14) { + di.x10 = OBJECT(di.x14->object); + CError_ASSERT(1342, di.x10->otype == OT_OBJECT); + } + + CError_ASSERT(1344, IS_TYPE_FUNC(di.x10->type)); + + tfunc = TYPE_FUNC(di.x10->type); + if (tfunc->flags & FUNC_FLAGS_40) { + di.thetype = tfunc->functype; + di.qual |= tfunc->qual; + di.nspace = di.x10->nspace; + di.name = di.x10->name; + } else if (tfunc->flags & FUNC_FLAGS_1000) { + di.thetype = TYPE(&void_ptr); + di.nspace = di.x10->nspace; + di.name = di.x10->name; + } else { + CError_Error(CErrorStr121); + return; + } + + if ((tk = lex()) == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + if (IS_TYPE_FUNC(di.thetype)) + goto skipPastStuff; + } else { + CError_Error(CErrorStr114); + } + } + + if (di.storageclass) { + if (tclass) { + if (di.storageclass == TK_STATIC) + disallowCVFlag = 1; + else + CError_Error(CErrorStr177); + di.storageclass = 0; + } else { + if (di.storageclass != TK_STATIC && di.storageclass != TK_EXTERN) { + CError_Error(CErrorStr177); + di.storageclass = 0; + } + } + } + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_ASM | Q_PASCAL | Q_INLINE | Q_EXPLICIT | Q_20000 | Q_OVERLOAD | Q_ALIGNED_MASK)); + + if (tk == TK_OPERATOR && di.x4A) { + CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); + return; + } + + if (!di.x53) { + if (tclass && IS_TYPE_CLASS(di.thetype) && TYPE_CLASS(di.thetype) == tclass && tk == '(') { + CError_ASSERT(1418, cscope_current == tclass->nspace); + CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_EXPLICIT)); + + di.thetype = TYPE(&void_ptr); + di.x4B = 1; + + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + if (TYPE_FUNC(di.thetype)->args && !TYPE_FUNC(di.thetype)->args->next && TYPE_FUNC(di.thetype)->args->type == TYPE(tclass)) { + CError_Error(CErrorStr239); + TYPE_FUNC(di.thetype)->args = NULL; + } + + if (tclass->flags & CLASS_FLAGS_20) + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_1000; + di.name = constructor_name_node; + + what_is_this->nspace->tparams = NULL; + + CTempl_ParseTemplateFunction( + CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag), + tclass, startOffset); + + return; + } else { + CError_Error(CErrorStr241); + } + } + + if (IS_TYPE_TEMPLATE(di.thetype)) { + if ( + tk == '(' && + TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && + (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(di.thetype)->u.qual.type)))) && + TYPE_TEMPLATE(di.thetype)->u.qual.name == tclass2->classname + ) + { + if (tclass) + CError_Error(CErrorStr229); + + di.thetype = TYPE(&void_ptr); + di.x4B = 1; + + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + di.name = constructor_name_node; + if (tclass2->flags & CLASS_FLAGS_20) + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_1000; + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr241); + } + + return; + } + + if ( + tk == TK_COLON_COLON && + TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_TEMPLATE && + (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(di.thetype))) + ) + { + if (tclass) + CError_Error(CErrorStr229); + + if ((tk = lex()) == '~') { + if ( + (tk = lex()) != TK_IDENTIFIER || + tkidentifier != tclass2->classname || + (tk = lex()) != '(' + ) + { + if (tk == '<') { + DeclInfo di2; + + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass2->classname; + + memclrw(&di2, sizeof(di2)); + CParser_GetDeclSpecs(&di2, 0); + if (tk != '(') + CError_Error(CErrorStr241); + + if (di2.thetype != TYPE(tclass2) && (!IS_TYPE_TEMPLATE(di2.thetype) || CTemplTool_IsTemplate( + TYPE_TEMPLATE(di2.thetype)) != TEMPL_CLASS(tclass2))) + { + CError_Error(CErrorStr241); + } + } else { + CError_Error(CErrorStr241); + } + } + + di.thetype = TYPE(&void_ptr); + + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + if (tclass2->sominfo) + di.qual |= Q_VIRTUAL; + else + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + di.name = destructor_name_node; + TYPE_FUNC(di.thetype)->flags |= FUNC_FLAGS_2000; + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr241); + } + } else if (tk == TK_OPERATOR) { + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + if (CMangler_OperatorName((tk = lex()))) { + CError_Error(CErrorStr349); + return; + } + + CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_VIRTUAL)); + conversion_type_name(&di); + + type = di.thetype; + qual = di.qual; + CDecl_NewConvFuncType(&di); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + di.name = CTempl_FindConversionFuncName(tclass2, type, qual); + if (!di.name) { + CError_Error(CErrorStr150, "conversion function"); + return; + } + } + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr121); + } + + return; + } + + if (TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && !di.x49) + CError_Warning(CErrorStr355); + } + } + + di.x30 = params; + di.fucker34 = what_is_this; + scandeclarator(&di); + ctempl_scanfuncparams = 0; + +skipPastStuff: + if (cscope_current->is_templ) { + CError_ASSERT(1589, cscope_current == what_is_this->nspace); + what_is_this->nspace->tparams = NULL; + } + + if (!di.name) { + CError_Error(CErrorStr229); + return; + } + + if (di.nspace) { + if (di.nspace->theclass) { + if (tclass) + CError_Error(CErrorStr229); + CTempl_ParseMember(params, TEMPL_CLASS(di.nspace->theclass), &di, startOffset); + return; + } + + if (!IS_TYPE_FUNC(di.thetype)) { + CError_Error(CErrorStr229); + return; + } + + CScope_FindName(di.nspace, di.name); + } else { + if (!IS_TYPE_FUNC(di.thetype)) { + CError_Error(CErrorStr229); + return; + } + + CScope_FindName(cscope_current, di.name); + } + + nsol = CScope_FindName(di.nspace ? di.nspace : cscope_current, di.name); + while (nsol) { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TEMPL_FUNC(object->type)) { + templfunc = CTemplTool_GetFuncTempl(object); + if (CTemplTool_EqualParams(templfunc->params, params, 0) && is_typesame(object->type, di.thetype)) { + if (tk != ';' && templfunc->stream.tokens) + CError_Error(CErrorStr234); + + if (tk == '{' || tk == ':' || tk == TK_TRY) + CError_ASSERT(1654, CTemplTool_EqualParams(templfunc->params, params, 1)); + + if (di.qual & Q_INLINE) + object->qual |= Q_INLINE; + TYPE_FUNC(object->type)->args = TYPE_FUNC(di.thetype)->args; + break; + } + } + nsol = nsol->next; + } + + if (!nsol) { + if (di.nspace) + CError_Error(CErrorStr229); + templfunc = CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag); + } + + CTempl_ParseTemplateFunction(templfunc, tclass, startOffset); +} + +static void CTempl_ExplicitInstantiation(void) { + Boolean flag; + short saveToken; + Object *object; + DeclInfo di; + + memclrw(&di, sizeof(di)); + di.x51 = 1; + flag = 1; + + if (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__dont_instantiate")) { + flag = 0; + tk = lex(); + } + + switch (tk) { + case TK_STRUCT: + case TK_UNION: + case TK_CLASS: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + if (tk == ';') { + if (IS_TEMPL_CLASS_INST(di.thetype)) { + CTempl_InstantiateTemplateClass(TYPE_CLASS(di.thetype)); + if ((TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_2) && !(TYPE_CLASS(di.thetype)->eflags & CLASS_EFLAGS_IMPORT)) { + if (flag) + CTempl_GenClassInstance(TEMPL_CLASS_INST(di.thetype), 1); + else + TEMPL_CLASS_INST(di.thetype)->is_extern = 1; + } else { + CError_Error(CErrorStr136, TYPE_CLASS(di.thetype), 0); + } + } else { + CError_Error(CErrorStr238); + } + return; + } + break; + default: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + } + + di.x51 = 1; + + scandeclarator(&di); + + saveToken = tk; + + di.x38 = NULL; + if ( + di.name && + IS_TYPE_FUNC(di.thetype) && + (object = CDecl_GetFunctionObject(&di, di.nspace, NULL, 1)) && + IS_TYPE_FUNC(object->type) && + object->u.func.inst && + di.x38 + ) + { + if (!flag) + object->u.func.inst->is_extern = 1; + else + CTempl_GenFuncInstance(di.x38, object->u.func.inst, 1); + } else { + CError_Error(CErrorStr238); + } + + if (saveToken != ';') + CError_Error(CErrorStr123); +} + +static void CTempl_ExplicitSpecialization(void) { + Boolean flag; + TemplParam *params; + int counter; + DeclFucker what_is_this; + DeclInfo di; + + flag = 0; + counter = 1; + while (tk == TK_TEMPLATE) { + if ((tk = lex()) != '<') { + CError_Error(CErrorStr230); + break; + } + + if ((tk = lex()) != '>') { + if (!flag) { + what_is_this.nspace = cscope_current; + what_is_this.mystery4 = NULL; + cscope_current->tparams = NULL; + flag = 1; + } + + params = CTempl_ParseParamList(what_is_this.nspace, counter); + if (tk != '>') + CError_Error(CErrorStr231); + } else { + if (flag) + CError_Error(CErrorStr335); + } + + counter++; + tk = lex(); + } + + if (flag) { + SInt32 startOffset = -1; + CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, NULL, &startOffset, ACCESSPUBLIC, 1); + return; + } + + memclrw(&di, sizeof(di)); + di.x3C = counter; + di.x51 = 1; + CParser_GetDeclSpecs(&di, 1); + + if (tk == ';') { + if (IS_TEMPL_CLASS_INST(di.thetype)) + TEMPL_CLASS_INST(di.thetype)->is_specialized = 1; + else + CError_Error(CErrorStr335); + } else { + scandeclaratorlist(&di); + if ((tk != ';' && tk != '}') || di.x3C) + CError_Error(CErrorStr335); + } + + if (flag) + what_is_this.nspace->tparams = NULL; +} + +void CTempl_Parse(TemplClass *templ, AccessType access) { + TemplParam *params; + UInt8 i; + short mode; + Boolean flag; + UInt8 classDeclSpec; + SInt32 startOffset; + SInt32 savedState; + CScopeSave savedScope; + DeclFucker what_is_this; + + startOffset = CPrep_BrowserFileOffset(); + CScope_GetScope(&savedScope); + + if ((tk = lex()) != '<') { + if (templ) + CError_Error(CErrorStr238); + CTempl_ExplicitInstantiation(); + CScope_RestoreScope(&savedScope); + return; + } + + if ((tk = lex()) == '>') { + if (templ) + CError_Error(CErrorStr335); + tk = lex(); + CTempl_ExplicitSpecialization(); + CScope_RestoreScope(&savedScope); + return; + } + + what_is_this.nspace = cscope_current; + what_is_this.mystery4 = NULL; + cscope_current->tparams = NULL; + i = CTempl_GetTemplateNestIndex(what_is_this.nspace); + + while (1) { + params = CTempl_ParseParamList(what_is_this.nspace, i); + if (tk != '>') + CError_Error(CErrorStr231); + + if ((tk = lex()) != TK_TEMPLATE) + break; + + if (templ) + CError_Error(CErrorStr121); + + if ((tk = lex()) != '<') + CError_Error(CErrorStr230); + else + tk = lex(); + + i++; + } + + switch (tk) { + case TK_CLASS: + mode = CLASS_MODE_2; + break; + case TK_UNION: + mode = CLASS_MODE_1; + break; + case TK_STRUCT: + mode = CLASS_MODE_0; + break; + default: + mode = -1; + } + + if (mode >= 0) { + classDeclSpec = 0; + flag = 0; + + CPrep_TokenStreamGetState(&savedState); + if ((tk = lex()) == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&classDeclSpec); + + if (tk == TK_IDENTIFIER) { + if ((tk = lex()) == '<') { + if (setjmp(ctempl_parseparse) == 0) { + CTempl_MemberParseTemplArgList(); + flag = 1; + tk = lex(); + } + } + + switch (tk) { + case ':': + case ';': + case '{': + CPrep_TokenStreamSetCurState(&savedState); + if (flag) + CTemplClass_ParsePartialSpecialization(&what_is_this, params, mode, &startOffset); + else + CTemplClass_ParseClass(&what_is_this, params, mode, &startOffset); + goto done; + } + } + + CPrep_TokenStreamSetCurState(&savedState); + } + + CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, TYPE_CLASS(templ), &startOffset, access, 0); + +done: + what_is_this.nspace->tparams = NULL; + CScope_RestoreScope(&savedScope); +} + +void CTempl_ParseInstanceScopeFunction(Object *funcobj, TemplClassInst *inst, TypeClass *tclass) { + TemplParam *params; + NameSpace *nspace; + TemplateMember *member; + Object *parent; + DeclInfo di; + CScopeSave savedScope; + TemplStack stack; + + params = inst->templ->templ__params; + if (funcobj->qual & Q_400000) { + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members, parent = OBJECT_TEMPL(funcobj)->parent; member; member = member->next) { + if (member->object == parent) { + if (member->params) + params = member->params; + break; + } + } + } + + CTemplTool_PushInstance(&stack, NULL, funcobj); + nspace = CTemplTool_InsertTemplateArgumentNameSpace(params, inst, &savedScope); + if (tclass) + cscope_current = tclass->nspace; + + memclrw(&di, sizeof(di)); + CFunc_ParseFuncDef(funcobj, &di, NULL, 0, 0, tclass ? cscope_current : NULL); + + CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); + CTemplTool_PopInstance(&stack); +} + +Boolean CTempl_GenFuncInstance(TemplateFunction *templ, TemplFuncInstance *inst, Boolean flag) { + Boolean saveDebugInfo; + NameSpace *nspace; + SInt32 streamState; + TemplStack stack; + DeclInfo di; + + if (!flag && copts.no_implicit_templates && inst->object->sclass != TK_STATIC) + return 0; + + if (inst->is_extern && !flag) + return 0; + + while (1) { + if (templ->stream.tokens) + break; + if (!templ->unk4) + break; + templ = templ->unk4; + } + + if (!templ->stream.tokens) { + if (flag) { + CError_SetErrorToken(&templ->deftoken); + CError_Error(CErrorStr233, inst->object); + } + return 0; + } + + inst->is_instantiated = 1; + + CPrep_StreamInsert(&templ->stream, &streamState); + + saveDebugInfo = copts.isGeneratingDebugInfo; + if (copts.nosyminline || !templ->deftoken.tokenfile) + copts.isGeneratingDebugInfo = 0; + + CError_ASSERT(2112, (tk = lex()) == '{' || tk == ':' || tk == TK_TRY); + + symdecltoken = *CPrep_CurStreamElement(); + + if (copts.isGeneratingDebugInfo) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, &templ->deftoken); + symdecloffset = cparser_fileoffset.tokenline; + } + + if (inst->object->sclass != TK_STATIC) + inst->object->qual |= Q_OVERLOAD; + + memclrw(&di, sizeof(di)); + di.file2 = templ->srcfile; + di.file = CPrep_BrowserCurrentFile(); + di.x60 = templ->startoffset; + + CTemplTool_PushInstance(&stack, NULL, inst->object); + CTemplTool_MergeArgNames(TYPE_FUNC(templ->tfunc->type), TYPE_FUNC(inst->object->type)); + + nspace = CTemplTool_SetupTemplateArgumentNameSpace(templ->params, inst->args, 0); + nspace->parent = inst->object->nspace; + inst->object->nspace = nspace; + + CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); + CFunc_ParseFuncDef(inst->object, &di, NULL, 0, 0, nspace); + CTemplTool_RemoveOuterTemplateArgumentNameSpace(nspace); + + inst->object->nspace = nspace->parent; + + CTemplTool_PopInstance(&stack); + + CPrep_StreamRemove(&templ->stream, &streamState); + copts.isGeneratingDebugInfo = saveDebugInfo; + + if (di.file->recordbrowseinfo) + CBrowse_NewFunction(inst->object, di.file, di.file2, di.x60, templ->endoffset); + + return 1; +} + +void CTempl_InstantiateMember(TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb, Object *object, Boolean flag) { + Boolean saveDebugInfo; + NameSpace *nspace; + Boolean saveSourceLoc; + + DeclInfo di; + CScopeSave savedScope; + TemplStack stack; + SInt32 savedState; + + if (!flag && copts.no_implicit_templates) + return; + + CTemplTool_PushInstance(&stack, NULL, object); + nspace = CTemplTool_InsertTemplateArgumentNameSpace( + tmemb->params ? tmemb->params : templ->templ__params, inst, &savedScope); + CPrep_StreamInsert(&tmemb->stream, &savedState); + + saveSourceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + symdecltoken.tokenoffset = tmemb->startoffset; + tk = lex(); + + symdecltoken = *CPrep_CurStreamElement(); + + saveDebugInfo = copts.isGeneratingDebugInfo; + if (copts.isGeneratingDebugInfo) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, &symdecltoken); + symdecloffset = cparser_fileoffset.tokenline; + } + + if (object->sclass != TK_STATIC) + object->qual |= Q_OVERLOAD; + + memclrw(&di, sizeof(di)); + di.file2 = tmemb->srcfile; + di.file = CPrep_BrowserCurrentFile(); + di.x60 = tmemb->startoffset; + + switch (object->datatype) { + case DFUNC: + case DVFUNC: + CTemplTool_MergeArgNames(TYPE_FUNC(tmemb->object->type), TYPE_FUNC(object->type)); + CFunc_ParseFuncDef(object, &di, TYPE_CLASS(inst), 0, 0, NULL); + break; + + case DDATA: + CDecl_CompleteType(object->type); + CInit_InitializeData(object); + break; + + default: + CError_FATAL(2227); + } + + CTemplTool_PopInstance(&stack); + CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); + CPrep_StreamRemove(&tmemb->stream, &savedState); + copts.isGeneratingDebugInfo = saveDebugInfo; + gForceSourceLoc = saveSourceLoc; +} + +static Boolean CTempl_GenMemberInstance(TemplClassInst *inst, ObjectTemplated *objtempl, Boolean flag) { + TemplateMember *member; + Object *parent = objtempl->parent; + + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { + if (member->object == parent) { + CTempl_InstantiateMember(inst->templ, inst, member, OBJECT(objtempl), flag); + return 1; + } + } + + if (flag) + CError_Warning(CErrorStr233, objtempl); + return 0; +} + +static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag) { + Object *object; + Boolean result; + CScopeObjectIterator iter; + + result = 0; + + if (!flag && copts.no_implicit_templates) + return 0; + if (!flag && inst->is_extern) + return 0; + + CScope_InitObjectIterator(&iter, inst->theclass.nspace); + while ((object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) { + if (IS_TYPE_FUNC(object->type) && object->datatype != DALIAS) { + if ( + (flag || (object->flags & OBJECT_FLAGS_2)) && + !(TYPE_FUNC(object->type)->flags & (FUNC_FLAGS_2 | FUNC_FLAGS_100)) && + CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) && + (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_2) + ) + result = 1; + } else { + if ( + !inst->x49 && + object->datatype == DDATA && + !(object->qual & Q_10000) && + !(object->flags & OBJECT_FLAGS_4) && + CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) + ) + result = 1; + } + } + + inst->x49 = 1; + return result; +} + +Boolean CTempl_Instantiate(void) { + Boolean result = 0; + TemplClass *templ; + TemplClassInst *inst; + TemplPartialSpec *pspec; + TemplFuncInstance *instf; + TemplateFunction *templf; + + for (templ = ctempl_templates; templ; templ = templ->next) { + for (inst = templ->instances; inst; inst = inst->next) { + if ( + (inst->theclass.flags & CLASS_FLAGS_800) && + !inst->is_specialized && + CTempl_GenClassInstance(inst, 0) + ) + result = 1; + } + + for (pspec = templ->pspecs; pspec; pspec = pspec->next) { + for (inst = pspec->templ->instances; inst; inst = inst->next) { + if ( + (inst->theclass.flags & CLASS_FLAGS_800) && + !inst->is_specialized && + CTempl_GenClassInstance(inst, 0) + ) + result = 1; + } + } + } + + for (templf = ctempl_templatefuncs; templf; templf = templf->next) { + for (instf = templf->instances; instf; instf = instf->next) { + if ( + !instf->is_instantiated && + !instf->is_specialized && + (instf->object->flags & OBJECT_FLAGS_2) && + !(TYPE_FUNC(instf->object->type)->flags & FUNC_FLAGS_2) + ) + { + instf->is_instantiated = 1; + if (CTempl_GenFuncInstance(templf, instf, 0)) + result = 1; + } + } + } + + return result; +} + +Boolean CTempl_InlineFunctionCheck(Object *funcobj) { + TemplClassInst *inst; + TemplateMember *member; + Object *parent; + + CError_ASSERT(2422, IS_TYPE_FUNC(funcobj->type) && (funcobj->qual & Q_400000)); + + if (!(TYPE_FUNC(funcobj->type)->flags & FUNC_FLAGS_2)) { + inst = TEMPL_CLASS_INST(TYPE_METHOD(funcobj->type)->theclass); + if (!inst->is_specialized) { + parent = OBJECT_TEMPL(funcobj)->parent; + if (parent->qual & Q_INLINE) { + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { + funcobj->qual |= Q_INLINE; + if (member->object == parent) { + CTemplTool_MergeArgNames(TYPE_FUNC(member->object->type), TYPE_FUNC(funcobj->type)); + CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(inst), &member->fileoffset, &member->stream, 0); + return 1; + } + } + } + } + } + + return 0; +} diff --git a/compiler_and_linker/unsorted/CTemplateTools.c b/compiler_and_linker/unsorted/CTemplateTools.c index e69de29..1d79ce0 100644 --- a/compiler_and_linker/unsorted/CTemplateTools.c +++ b/compiler_and_linker/unsorted/CTemplateTools.c @@ -0,0 +1,1962 @@ +#include "compiler/CTemplateTools.h" +#include "compiler/CABI.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateClass.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CompilerTools.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" + +short ctempl_instdepth; + +void CTemplTool_PushInstance(TemplStack *stack, TypeClass *tmclass, Object *func) { + if (tmclass) { + stack->u.theclass = tmclass; + stack->is_func = 0; + } else { + stack->u.func = func; + stack->is_func = 1; + } + stack->next = ctempl_curinstance; + ctempl_curinstance = stack; + + if (++ctempl_instdepth >= 64) + CError_ErrorTerm(CErrorStr314); +} + +void CTemplTool_PopInstance(TemplStack *stack) { + CError_ASSERT(53, ctempl_curinstance == stack); + + ctempl_curinstance = stack->next; + if (--ctempl_instdepth < 0) + ctempl_instdepth = 0; +} + +ENode *CTempTool_GetPTMTemplArgExpr(ENode *expr, Type *type) { + NameSpaceObjectList *list; + + CError_ASSERT(69, ENODE_IS(expr, EMEMBER)); + CError_ASSERT(70, IS_TYPE_MEMBERPOINTER(type)); + + if (!copts.cpp_extensions) { + if (!expr->data.emember->x11 || !expr->data.emember->pr_1D) + CError_Warning(CErrorStr331); + } + + type = TYPE_MEMBER_POINTER(type)->ty1; + for (list = expr->data.emember->list; list; list = list->next) { + if (list->object->otype == OT_MEMBERVAR) { + if (!is_typeequal(OBJ_MEMBER_VAR(list->object)->type, type)) + CError_Error(CErrorStr146); + return expr; + } + + if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { + if (expr->data.emember->list != list || list->next) { + // rewrite the EMEMBER to contain just one node + expr->data.emember->list = galloc(sizeof(NameSpaceObjectList)); + *expr->data.emember->list = *list; + expr->data.emember->list->next = NULL; + } + break; + } + } + + if (!list) + CError_Error(CErrorStr146); + + return expr; +} + +Boolean CTemplTool_InitDeduceInfo(DeduceInfo *info, TemplParam *params, TemplArg *args, Boolean flag) { + int i; + TemplArg *buffer; + TemplParam *param; + + if (!params) { + info->args = info->argBuffer; + info->maxCount = 0; + info->x12C = 0xFF; + return 1; + } + + memclrw(info, sizeof(DeduceInfo)); + + i = 0; + param = params; + while (param) { + param = param->next; + i++; + } + + if (i > 16) { + buffer = lalloc(i * sizeof(TemplArg)); + memclrw(buffer, i * sizeof(TemplArg)); + } else { + buffer = info->argBuffer; + } + info->args = buffer; + info->maxCount = i; + info->x12C = params->pid.nindex; + + for (param = params, i = 0; param; param = param->next, i++) + buffer[i].pid = param->pid; + + i = 0; + param = params; + while (args) { + if (!param || param->pid.type != args->pid.type) + return 0; + + buffer[i].data = args->data; + if (i > 0) + buffer[i - 1].next = &buffer[i]; + buffer[i].next = NULL; + buffer[i].is_deduced = 1; + info->count++; + + if (param->pid.type == TPT_NONTYPE && !CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { + if (CExpr_CanImplicitlyConvert(buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual)) { + buffer[i].data.paramdecl.expr = CExpr_AssignmentPromotion( + buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual, 0); + } else { + return 0; + } + } + + args = args->next; + param = param->next; + i++; + } + + if (flag) { + for (param = params, i = 0; param; param = param->next, i++) { + if (!buffer[i].is_deduced && !param->name) { + switch (param->pid.type) { + case TPT_TYPE: + buffer[i].data.typeparam.type = &stvoid; + break; + case TPT_NONTYPE: + buffer[i].data.paramdecl.expr = nullnode(); + break; + case TPT_TEMPLATE: + default: + CError_FATAL(208); + } + buffer[i].is_deduced = 1; + } + } + } + + return 1; +} + +void CTemplTool_InsertTemplateParameter(NameSpace *nspace, TemplParam *param) { + Type *type; + ObjType *obj; + NameSpaceName *nsn; + + type = CDecl_NewTemplDepType(TEMPLDEP_ARGUMENT); + TYPE_TEMPLATE(type)->u.pid = param->pid; + + obj = galloc(sizeof(ObjType)); + memclrw(obj, sizeof(ObjType)); + obj->otype = OT_TYPE; + obj->access = ACCESSPUBLIC; + obj->type = type; + + for (nsn = nspace->tparams; nsn; nsn = nsn->next) { + if (nsn->name == param->name) { + CError_Error(CErrorStr122, param->name->name); + return; + } + } + + nsn = galloc(sizeof(NameSpaceName)); + memclrw(nsn, sizeof(NameSpaceName)); + + nsn->name = param->name; + nsn->first.object = OBJ_BASE(obj); + + nsn->next = nspace->tparams; + nspace->tparams = nsn; +} + +TemplArg *CTemplTool_MakeTemplArgList(DeduceInfo *info) { + TemplArg *args; + TemplArg *last; + int i; + + for (i = 0; i < info->maxCount; i++) { + if (i) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + args = last = galloc(sizeof(TemplArg)); + } + + *last = info->args[i]; + } + + last->next = NULL; + return args; +} + +Boolean CTemplTool_IsIdenticalTemplArgList(TemplArg *args, TemplParam *params) { + while (args) { + if (!params) + return 0; + + CError_ASSERT(297, params->pid.type == args->pid.type); + + switch (args->pid.type) { + case TPT_TYPE: + if ( + !IS_TYPE_TEMPLATE(args->data.typeparam.type) || + TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex + ) + return 0; + break; + case TPT_NONTYPE: + if ( + !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || + args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || + args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index || + args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex + ) + return 0; + break; + case TPT_TEMPLATE: + if ( + !IS_TYPE_TEMPLATE(args->data.ttargtype) || + TYPE_TEMPLATE(args->data.ttargtype)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.ttargtype)->u.pid.index != params->pid.index || + TYPE_TEMPLATE(args->data.ttargtype)->u.pid.nindex != params->pid.nindex + ) + return 0; + break; + default: + CError_FATAL(331); + } + + args = args->next; + params = params->next; + } + + return !params; +} + +Type *CTemplTool_GetSelfRefTemplate(Type *type) { + TemplClass *templ; + TemplArg *args; + + CError_ASSERT(347, IS_TYPE_TEMPLATE(type)); + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_TEMPLATE) { + if (CTemplTool_IsIdenticalTemplArgList( + TYPE_TEMPLATE(type)->u.templ.args, + TYPE_TEMPLATE(type)->u.templ.templ->templ__params)) + return TYPE(TYPE_TEMPLATE(type)->u.templ.templ); + + if (TYPE_TEMPLATE(type)->u.templ.templ->pspecs) { + templ = TYPE_TEMPLATE(type)->u.templ.templ; + if ( + CTemplClass_FindPartialTemplate(TYPE_TEMPLATE(type)->u.templ.args, &templ, &args) && + CTemplTool_IsIdenticalTemplArgList(args, templ->templ__params) + ) + return TYPE(templ); + } + + return NULL; + } + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME) { + Type *t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); + if ( + t && + (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(type)->u.qual.name)) && + IS_TEMPL_CLASS(t) && + !TEMPL_CLASS(t)->templ__params + ) + return t; + + return NULL; + } + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALTEMPL) { + Type *t; + + CError_ASSERT(389, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->dtype == TEMPLDEP_QUALNAME); + + t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.type)); + if ( + t && + (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.name)) && + IS_TEMPL_CLASS(t) + ) + { + TemplClass *tm = TEMPL_CLASS(t); + if (CTemplTool_IsIdenticalTemplArgList(TYPE_TEMPLATE(type)->u.qualtempl.args, tm->templ__params)) + return TYPE(tm); + } + } + + return NULL; +} + +TemplateFunction *CTemplTool_GetFuncTempl(Object *object) { + while (object->datatype == DALIAS) + object = object->u.alias.object; + + CError_ASSERT(416, IS_TEMPL_FUNC(object->type)); + return object->u.func.u.templ; +} + +Boolean CTemplTool_ParamHasDefaultArg(TemplParam *param) { + switch (param->pid.type) { + case TPT_TYPE: + return param->data.typeparam.type != NULL; + case TPT_NONTYPE: + return param->data.paramdecl.defaultarg != NULL; + case TPT_TEMPLATE: + default: + CError_FATAL(438); + return 0; + } +} + +void CTemplTool_MergeDefaultArgs(TemplParam *dest, TemplParam *src) { + while (1) { + if (!dest) { + CError_ASSERT(455, !src); + return; + } + + CError_ASSERT(458, src); + CError_ASSERT(459, dest->pid.type == src->pid.type); + + switch (dest->pid.type) { + case TPT_TYPE: + if (!dest->data.typeparam.type && src->data.typeparam.type) + dest->data = src->data; + break; + case TPT_NONTYPE: + if (!dest->data.paramdecl.defaultarg && src->data.paramdecl.defaultarg) + dest->data = src->data; + break; + case TPT_TEMPLATE: + if (!dest->data.templparam.defaultarg && src->data.templparam.defaultarg) + dest->data = src->data; + break; + default: + CError_FATAL(484); + } + + dest = dest->next; + src = src->next; + } +} + +static FuncArg *CTemplTool_GetFirstRealArg(TypeFunc *tfunc) { + FuncArg *arg = tfunc->args; + + if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc)) { + CError_ASSERT(502, arg); + arg = arg->next; + if ((tfunc->flags & FUNC_FLAGS_1000) && (TYPE_METHOD(tfunc)->theclass->flags & CLASS_FLAGS_20)) { + CError_ASSERT(507, arg); + arg = arg->next; + } + } + + return arg; +} + +void CTemplTool_MergeArgNames(TypeFunc *src, TypeFunc *dest) { + FuncArg *destArg; + FuncArg *srcArg; + + CError_ASSERT(524, IS_TYPE_FUNC(dest) && IS_TYPE_FUNC(src)); + + srcArg = CTemplTool_GetFirstRealArg(src); + destArg = CTemplTool_GetFirstRealArg(dest); + + while (1) { + if (!srcArg || !destArg || srcArg == &elipsis || destArg == &elipsis) { + CError_ASSERT(531, srcArg == destArg); + break; + } + + destArg->name = srcArg->name; + srcArg = srcArg->next; + destArg = destArg->next; + } + + if (IS_TYPEFUNC_NONSTATIC_METHOD(dest)) { + CError_ASSERT(538, destArg = dest->args); + if (!destArg->name) + destArg->name = this_name_node; + } +} + +Boolean CTemplTool_EqualParams(TemplParam *a, TemplParam *b, Boolean copyNames) { + while (1) { + if (!a) + return !b; + if (!b) + return 0; + + if (a->pid.type != b->pid.type) + return 0; + + if (copyNames) + a->name = b->name; + + switch (a->pid.type) { + case TPT_TYPE: + break; + case TPT_NONTYPE: + if ( + !is_typesame(a->data.paramdecl.type, b->data.paramdecl.type) || + a->data.paramdecl.qual != b->data.paramdecl.qual + ) + return 0; + break; + case TPT_TEMPLATE: + break; + default: + CError_FATAL(576); + } + + a = a->next; + b = b->next; + } +} + +NameSpace *CTemplTool_SetupTemplateArgumentNameSpace(TemplParam *params, TemplArg *args, Boolean is_global) { + NameSpace *nspace; + Boolean clear_global; + ObjType *objType; + Object *object; + + clear_global = 0; + if (!is_global && trychain) { + clear_global = 1; + is_global = 1; + } + + nspace = CScope_NewListNameSpace(NULL, is_global); + nspace->is_templ = 1; + + if (clear_global) + nspace->is_global = 0; + + if (!params) + return nspace; + + while (params) { + CError_ASSERT(607, args); + + if (params->name) { + switch (args->pid.type) { + case TPT_TYPE: + if (is_global) { + objType = galloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } else { + objType = lalloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } + objType->otype = OT_TYPE; + objType->access = ACCESSPUBLIC; + objType->type = args->data.typeparam.type; + objType->qual = args->data.typeparam.qual; + CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); + break; + case TPT_NONTYPE: + if (is_global) { + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + } else { + object = lalloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + } + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->nspace = nspace; + object->name = params->name; + object->type = args->data.paramdecl.expr->rtype; + object->qual = ENODE_QUALS(args->data.paramdecl.expr); + object->datatype = DEXPR; + object->u.expr = args->data.paramdecl.expr; + if (IS_TYPE_REFERENCE(params->data.paramdecl.type)) { + CError_ASSERT(652, IS_TYPE_POINTER_ONLY(object->u.expr->rtype)); + object->u.expr = makemonadicnode(object->u.expr, EINDIRECT); + object->u.expr->rtype = TPTR_TARGET(params->data.paramdecl.type); + } + if (is_global) + object->u.expr = CInline_CopyExpression(object->u.expr, CopyMode1); + CScope_AddObject(nspace, params->name, OBJ_BASE(object)); + break; + case TPT_TEMPLATE: + if (is_global) { + objType = galloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } else { + objType = lalloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } + objType->otype = OT_TYPE; + objType->access = ACCESSPUBLIC; + objType->type = args->data.ttargtype; + objType->qual = 0; + CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); + break; + default: + CError_FATAL(681); + } + } + + params = params->next; + args = args->next; + } + + CError_ASSERT(685, !args); + + return nspace; +} + +void CTemplTool_SetupOuterTemplateArgumentNameSpace(NameSpace *nspace) { + NameSpace *newns; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_800)) { + newns = CTemplTool_SetupTemplateArgumentNameSpace( + TEMPL_CLASS_INST(nspace->theclass)->templ->templ__params, + TEMPL_CLASS_INST(nspace->theclass)->inst_args, + 0); + newns->parent = nspace->parent; + nspace->parent = newns; + } + + nspace = nspace->parent; + } +} + +NameSpace *CTemplTool_InsertTemplateArgumentNameSpace(TemplParam *params, TemplClassInst *inst, CScopeSave *save) { + NameSpace *nspace = CTemplTool_SetupTemplateArgumentNameSpace(params, inst->inst_args, 0); + + nspace->parent = inst->theclass.nspace->parent; + inst->theclass.nspace->parent = nspace; + + CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); + CScope_SetNameSpaceScope(inst->theclass.nspace, save); + + return nspace; +} + +void CTemplTool_RemoveOuterTemplateArgumentNameSpace(NameSpace *nspace) { + while (nspace->parent) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_FLAGS_800) && nspace->parent->is_templ) + nspace->parent = nspace->parent->parent; + nspace = nspace->parent; + } +} + +void CTemplTool_RemoveTemplateArgumentNameSpace(NameSpace *nspace, TemplClassInst *inst, CScopeSave *save) { + CTemplTool_RemoveOuterTemplateArgumentNameSpace(inst->theclass.nspace); + CScope_RestoreScope(save); +} + +Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type) { + FuncArg *arg; + + while (1) { + switch (type->type) { + case TYPETEMPLATE: + return 1; + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + return 0; + case TYPECLASS: + return (TYPE_CLASS(type)->flags & CLASS_FLAGS_100) ? 1 : 0; + case TYPEMEMBERPOINTER: + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_MEMBER_POINTER(type)->ty1)) + return 1; + type = TYPE_MEMBER_POINTER(type)->ty2; + continue; + case TYPEPOINTER: + case TYPEARRAY: + type = TPTR_TARGET(type); + continue; + case TYPEFUNC: + for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis && arg != &oldstyle; arg = arg->next) { + if (CTemplTool_IsTemplateArgumentDependentType(arg->type)) + return 1; + } + type = TYPE_FUNC(type)->functype; + continue; + case TYPEBITFIELD: + type = TYPE_BITFIELD(type)->bitfieldtype; + continue; + case TYPETEMPLDEPEXPR: + return 1; + default: + CError_FATAL(822); + } + } +} + +Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr) { + if (!expr) + return 0; + + if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) + return 1; + + return 0; +} + +Boolean CTemplTool_IsSameTemplate(TemplParam *params, TemplArg *args) { + while (1) { + if (!args) { + CError_ASSERT(850, !params); + return 1; + } + + CError_ASSERT(853, params && args->pid.type == params->pid.type); + + switch (args->pid.type) { + case TPT_TYPE: + if ( + !IS_TYPE_TEMPLATE(args->data.typeparam.type) || + TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || + args->data.typeparam.qual != 0 + ) + return 0; + break; + case TPT_NONTYPE: + if ( + !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || + args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || + args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex || + args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index + ) + return 0; + break; + case TPT_TEMPLATE: + if (!IS_TYPE_TEMPLATE(args->data.ttargtype)) + return 0; + break; + default: + CError_FATAL(886); + } + + args = args->next; + params = params->next; + } +} + +TemplClass *CTemplTool_IsTemplate(TypeTemplDep *ttd) { + if (ttd->dtype == TEMPLDEP_QUALNAME && ttd->u.qual.type->dtype == TEMPLDEP_TEMPLATE) + ttd = ttd->u.qual.type; + else if (ttd->dtype != TEMPLDEP_TEMPLATE) + return NULL; + + if (CTemplTool_IsSameTemplate(ttd->u.templ.templ->templ__params, ttd->u.templ.args)) + return ttd->u.templ.templ; + else + return NULL; +} + +Type *CTemplTool_IsDependentTemplate(TemplClass *tmclass, TemplArg *args) { + TemplParam *param; + TemplArg *arg; + Type *type; + + if (!tmclass->templ_parent || tmclass->inst_parent) { + arg = args; + param = tmclass->templ__params; + while (1) { + if (!arg) { + CError_ASSERT(988, !param); + return NULL; + } + + CError_ASSERT(991, param && arg->pid.type == param->pid.type); + + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + goto done; + break; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + goto done; + break; + case TPT_TEMPLATE: + if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) + goto done; + break; + default: + CError_FATAL(1008); + goto done; + } + + arg = arg->next; + param = param->next; + } + } +done: + if (cscope_current->theclass == TYPE_CLASS(tmclass) && CTemplTool_IsSameTemplate(tmclass->templ__params, args)) + return TYPE(tmclass); + + type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); + TYPE_TEMPLATE(type)->u.templ.templ = tmclass; + TYPE_TEMPLATE(type)->u.templ.args = args; + return type; +} + +Boolean CTemplTool_EqualExprTypes(ENode *a, ENode *b) { + Object *objA; + Object *objB; + + if (!a || !b) + return 0; + if (a->type != b->type) + return 0; + + switch (a->type) { + case EINTCONST: + return CInt64_Equal(a->data.intval, b->data.intval); + case EOBJREF: + objA = a->data.objref; + while (objA->datatype == DALIAS) + objA = objA->u.alias.object; + objB = b->data.objref; + while (objB->datatype == DALIAS) + objB = objB->u.alias.object; + return objA == objB; + case EMEMBER: + return a->data.emember->list == b->data.emember->list; + case ETEMPLDEP: + if (a->data.templdep.subtype != b->data.templdep.subtype) + return 0; + + switch (a->data.templdep.subtype) { + case TDE_PARAM: + return a->data.templdep.u.pid.nindex == b->data.templdep.u.pid.nindex && + a->data.templdep.u.pid.index == b->data.templdep.u.pid.index; + case TDE_SIZEOF: + case TDE_ALIGNOF: + return is_typesame(a->data.templdep.u.typeexpr.type, b->data.templdep.u.typeexpr.type); + case TDE_CAST: + return is_typesame(a->data.templdep.u.cast.type, b->data.templdep.u.cast.type) && + a->data.templdep.u.cast.qual == b->data.templdep.u.cast.qual; + case TDE_QUALNAME: + return is_typesame(TYPE(a->data.templdep.u.qual.type), TYPE(b->data.templdep.u.qual.type)) && + a->data.templdep.u.qual.name == b->data.templdep.u.qual.name; + case TDE_OBJ: + return a->data.templdep.u.obj == b->data.templdep.u.obj; + case TDE_ADDRESS_OF: + return CTemplTool_EqualExprTypes(a->data.templdep.u.monadic, b->data.templdep.u.monadic); + default: + CError_FATAL(1086); + } + case EMUL: + case EDIV: + case EMODULO: + 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 EROTL: + case EROTR: + return CTemplTool_EqualExprTypes(a->data.diadic.left, b->data.diadic.left) && + CTemplTool_EqualExprTypes(a->data.diadic.right, b->data.diadic.right); + case EMONMIN: + case EBINNOT: + case ELOGNOT: + return CTemplTool_EqualExprTypes(a->data.monadic, b->data.monadic); + case ECOND: + return CTemplTool_EqualExprTypes(a->data.cond.cond, b->data.cond.cond) && + CTemplTool_EqualExprTypes(a->data.cond.expr1, b->data.cond.expr1) && + CTemplTool_EqualExprTypes(a->data.cond.expr2, b->data.cond.expr2); + default: + CError_FATAL(1122); + return 0; + } +} + +ENode *CTempl_MakeTemplDepExpr(ENode *left, ENodeType nt, ENode *right) { + if (!IS_TYPE_TEMPLDEPEXPR(right->rtype)) { + right = pointer_generation(right); + if (!ENODE_IS(right, EINTCONST)) { + CError_Error(CErrorStr348); + right = nullnode(); + } + } + + if (left) { + if (!IS_TYPE_TEMPLDEPEXPR(left->rtype)) { + left = pointer_generation(left); + if (!ENODE_IS(left, EINTCONST)) { + CError_Error(CErrorStr348); + left = nullnode(); + } + } + + left = makediadicnode(left, right, nt); + } else { + left = makemonadicnode(right, nt); + } + + left->rtype = &sttemplexpr; + return left; +} + +void CTemplTool_CheckTemplArgType(Type *type) { + while (IS_TYPE_POINTER_ONLY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type)) { + if (IsTempName(TYPE_CLASS(type)->classname) || CScope_IsInLocalNameSpace(TYPE_CLASS(type)->nspace)) + CError_Error(CErrorStr232); + } +} + +Boolean CTemplTool_EqualArgs(TemplArg *a, TemplArg *b) { + while (a) { + if (!b || a->pid.type != b->pid.type) + return 0; + + switch (a->pid.type) { + case TPT_TYPE: + if ( + !is_typesame(a->data.typeparam.type, b->data.typeparam.type) || + a->data.typeparam.qual != b->data.typeparam.qual + ) + return 0; + break; + case TPT_NONTYPE: + if (!CTemplTool_EqualExprTypes(a->data.paramdecl.expr, b->data.paramdecl.expr)) + return 0; + break; + case TPT_TEMPLATE: + if (!is_typesame(a->data.ttargtype, b->data.ttargtype)) + return 0; + break; + default: + CError_FATAL(1215); + } + + a = a->next; + b = b->next; + } + + if (b) + return 0; + + return 1; +} + +TemplArg *CTemplTool_MakeGlobalTemplArgCopy(TemplArg *args) { + TemplArg *firstCopy; + TemplArg *copy; + + firstCopy = NULL; + while (args) { + if (firstCopy) { + copy->next = galloc(sizeof(TemplArg)); + copy = copy->next; + } else { + copy = galloc(sizeof(TemplArg)); + firstCopy = copy; + } + + *copy = *args; + if (copy->pid.type == TPT_NONTYPE && copy->data.paramdecl.expr) + copy->data.paramdecl.expr = CInline_CopyExpression(copy->data.paramdecl.expr, CopyMode1); + + args = args->next; + } + + return firstCopy; +} + +Boolean CTemplTool_TemplDepTypeCompare(TypeTemplDep *a, TypeTemplDep *b) { + if (a == b) + return 1; + if (a->dtype != b->dtype) + return 0; + + switch (a->dtype) { + case TEMPLDEP_ARGUMENT: + return a->u.pid.nindex == b->u.pid.nindex && + a->u.pid.index == b->u.pid.index; + case TEMPLDEP_QUALNAME: + return CTemplTool_TemplDepTypeCompare(a->u.qual.type, b->u.qual.type) && + a->u.qual.name == b->u.qual.name; + case TEMPLDEP_TEMPLATE: + return a->u.templ.templ == b->u.templ.templ && + CTemplTool_EqualArgs(a->u.templ.args, b->u.templ.args); + case TEMPLDEP_ARRAY: + return is_typesame(a->u.array.type, b->u.array.type) && + CTemplTool_EqualExprTypes(a->u.array.index, b->u.array.index); + case TEMPLDEP_QUALTEMPL: + return CTemplTool_TemplDepTypeCompare(a->u.qualtempl.type, b->u.qualtempl.type) && + CTemplTool_EqualArgs(a->u.qualtempl.args, b->u.qualtempl.args); + case TEMPLDEP_BITFIELD: + return is_typesame(a->u.bitfield.type, b->u.bitfield.type) && + CTemplTool_EqualExprTypes(a->u.bitfield.size, b->u.bitfield.size); + default: + CError_FATAL(1286); + return 0; + } +} + +Type *CTemplTool_DeduceArgDepType(TemplArg *args, Type *type, UInt32 qual, UInt32 *resultQual) { + TemplArg *arg; + + *resultQual = qual; + + if (IS_TYPE_TEMPLATE(type) && TYPE_TEMPLATE(type)->dtype == TEMPLDEP_ARGUMENT) { + arg = args; + while (1) { + if (!arg) + return NULL; + + if ( + arg->pid.index == TYPE_TEMPLATE(type)->u.pid.index && + arg->pid.nindex == TYPE_TEMPLATE(type)->u.pid.nindex + ) + break; + + arg = arg->next; + } + + CError_ASSERT(1314, arg->pid.type == TPT_TYPE); + *resultQual |= arg->data.typeparam.qual; + return arg->data.typeparam.type; + } + + return NULL; +} + +static TemplClassInst *CTemplTool_FindNestedClassInstance(TemplClass *a, TemplClass *b, TemplClassInst *c) { + TemplClass *array[32]; + TemplClassInst *inst; + int i; + + array[0] = a; + i = 0; + while (1) { + CError_ASSERT(1338, i < 32); + CError_ASSERT(1339, a = a->templ_parent); + + if (a == b) + break; + + CError_ASSERT(1341, a->templ__params == NULL); + + array[++i] = a; + } + + while (1) { + inst = array[i--]->instances; + while (1) { + CError_ASSERT(1350, inst); + if (inst->parent == c) + break; + inst = inst->next; + } + + c = inst; + if (i < 0) + break; + + if ((inst->theclass.flags & (CLASS_FLAGS_2 | CLASS_FLAGS_800)) == CLASS_FLAGS_800) + CTempl_InstantiateTemplateClass(inst); + } + + return inst; +} + +static TemplClassInst *CTemplTool_FindNestedClass(TemplClass *a, TemplClassInst *b, TemplClass *c) { + TemplClass *scan; + + while (1) { + for (scan = c->templ_parent; scan; scan = scan->templ_parent) { + if (scan == a) + return CTemplTool_FindNestedClassInstance(c, a, b); + } + + a = a->templ_parent; + if (!a) + break; + + b = b->parent; + CError_ASSERT(1377, b); + } + + return NULL; +} + +static Type *CTemplTool_FindTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { + TemplClass *scantempl; + TemplClass *dtempl; + TemplClassInst *scaninst; + TemplClassInst *dinst; + + dtempl = deduce->tmclass; + CError_ASSERT(1393, dtempl); + + dinst = deduce->inst; + if (!dinst) { + if (!dtempl->templ_parent || !dtempl->inst_parent) + return TYPE(templ); + + dtempl = dtempl->templ_parent; + dinst = deduce->tmclass->inst_parent; + } + + scantempl = dtempl; + scaninst = dinst; + while (1) { + if (scantempl == templ) + return TYPE(scaninst); + + if (!scantempl->templ_parent && scantempl->pspec_owner) + scantempl = scantempl->pspec_owner; + + scantempl = scantempl->templ_parent; + if (!scantempl) + break; + + CError_ASSERT(1416, scaninst = scaninst->parent); + } + + if (dtempl->flags & TEMPLCLASS_FLAGS_2) { + scantempl = TEMPL_CLASS(dtempl->theclass.nspace->theclass); + CError_ASSERT(1422, scantempl->theclass.flags & CLASS_FLAGS_100); + scaninst = dinst; + + while (1) { + if (scantempl == templ) + return TYPE(scaninst); + + scantempl = scantempl->templ_parent; + if (!scantempl) + break; + + CError_ASSERT(1430, scaninst = scaninst->parent); + } + } + + if (!templ->templ__params && (scaninst = CTemplTool_FindNestedClass(dtempl, dinst, templ))) + return TYPE(scaninst); + + CError_FATAL(1477); + return NULL; +} + +static ENode *CTemplTool_DeduceExprCheck(ENode *expr) { + if (expr->type != EINTCONST) { + CError_Error(CErrorStr348); + expr = nullnode(); + } + + return expr; +} + +static ENodeList *CTemplTool_DeduceExprList(TypeDeduce *deduce, ENodeList *list) { + ENodeList *resultList; + ENodeList *last; + + resultList = NULL; + while (list) { + if (resultList) { + last->next = lalloc(sizeof(ENodeList)); + last = last->next; + } else { + last = lalloc(sizeof(ENodeList)); + resultList = last; + } + + *last = *list; + last->node = CTemplTool_DeduceExpr(deduce, last->node); + + list = list->next; + } + + return resultList; +} + +ENode *CTemplTool_DeduceExpr(TypeDeduce *deduce, ENode *expr) { + TemplArg *arg; + TemplClassInst *inst; + ENode *newExpr; + NameSpaceObjectList *nsObjectList; + TStreamElement *saved; + CScopeParseResult pr; + Type *type; + UInt32 qual; + + if (!CTemplTool_IsTemplateArgumentDependentExpression(expr)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } + + switch (expr->type) { + case ETEMPLDEP: + switch (expr->data.templdep.subtype) { + case TDE_PARAM: + if (deduce->x15 && expr->data.templdep.u.pid.nindex == deduce->nindex) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } + + for (arg = deduce->args; arg; arg = arg->next) { + if ( + arg->pid.index == expr->data.templdep.u.pid.index && + arg->pid.nindex == expr->data.templdep.u.pid.nindex + ) + { + CError_ASSERT(1562, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); + newExpr = lalloc(sizeof(ENode)); + *newExpr = *arg->data.paramdecl.expr; + return newExpr; + } + } + + for (inst = deduce->inst; inst; inst = inst->parent) { + for (arg = inst->inst_args; arg; arg = arg->next) { + if ( + arg->pid.index == expr->data.templdep.u.pid.index && + arg->pid.nindex == expr->data.templdep.u.pid.nindex + ) + { + CError_ASSERT(1575, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); + newExpr = lalloc(sizeof(ENode)); + *newExpr = *arg->data.paramdecl.expr; + return newExpr; + } + } + } + + CError_FATAL(1582); + + case TDE_SIZEOF: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); + CDecl_CompleteType(type); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.typeexpr.type = type; + return newExpr; + } + + return intconstnode(CABI_GetSizeTType(), type->size); + + case TDE_ALIGNOF: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); + CDecl_CompleteType(type); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.typeexpr.type = type; + return newExpr; + } + + return intconstnode(CABI_GetSizeTType(), CMach_GetTypeAlign(type)); + + case TDE_CAST: + qual = expr->data.templdep.u.cast.qual; + type = CTemplTool_DeduceTypeCopy(deduce, expr->data.templdep.u.cast.type, &qual); + return CExpr_DoExplicitConversion(type, qual, CTemplTool_DeduceExprList(deduce, expr->data.templdep.u.cast.args)); + + case TDE_QUALNAME: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.qual.type), &qual); + + if (IS_TYPE_CLASS(type)) { + CDecl_CompleteType(type); + if (CScope_FindQualifiedClassMember(&pr, TYPE_CLASS(type), expr->data.templdep.u.qual.name)) + return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); + + CError_Error(CErrorStr150, expr->data.templdep.u.qual.name->name); + } else if (IS_TYPE_TEMPLATE(type) && !deduce->inst) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.qual.type = TYPE_TEMPLATE(type); + return newExpr; + } else { + CError_Error(CErrorStr340, expr->data.templdep.u.qual.name->name); + } + + return nullnode(); + + case TDE_OBJ: + type = CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(expr->data.templdep.u.obj->nspace->theclass)); + CError_ASSERT(1651, type && IS_TYPE_CLASS(type)); + + nsObjectList = CScope_GetLocalObject(TYPE_CLASS(type)->nspace, expr->data.templdep.u.obj->name); + CError_ASSERT(1654, nsObjectList); + + memclrw(&pr, sizeof(pr)); + pr.obj_10 = nsObjectList->object; + return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); + + case TDE_SOURCEREF: + CError_LockErrorPos(expr->data.templdep.u.sourceref.token, &saved); + newExpr = CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.sourceref.expr); + CError_UnlockErrorPos(&saved); + return newExpr; + + case TDE_ADDRESS_OF: + return getnodeaddress(CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.monadic), 1); + + default: + CError_FATAL(1671); + } + case EFUNCCALL: + newExpr = CExpr_PointerGeneration(CTemplTool_DeduceExpr(deduce, expr->data.funccall.funcref)); + return CExpr_MakeFunctionCall(newExpr, CTemplTool_DeduceExprList(deduce, expr->data.funccall.args)); + case ELOGNOT: + return CExpr_New_ELOGNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EMONMIN: + return CExpr_New_EMONMIN_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EBINNOT: + return CExpr_New_EBINNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EMUL: + case EDIV: + case EMODULO: + 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 EROTL: + case EROTR: + return CExpr_NewDyadicNode( + CTemplTool_DeduceExpr(deduce, expr->data.diadic.left), + expr->type, + CTemplTool_DeduceExpr(deduce, expr->data.diadic.right)); + case ECOND: + return CExpr_New_ECOND_Node( + CTemplTool_DeduceExpr(deduce, expr->data.cond.cond), + CTemplTool_DeduceExpr(deduce, expr->data.cond.expr1), + CTemplTool_DeduceExpr(deduce, expr->data.cond.expr2)); + default: + CError_FATAL(1727); + case EINTCONST: + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } +} + +ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr) { + TypeDeduce deduce; + + memclrw(&deduce, sizeof(deduce)); + CError_ASSERT(1747, IS_TYPE_FUNC(func->type)); + + if (func->u.func.inst) + deduce.args = func->u.func.inst->args; + + if ((TYPE_FUNC(func->type)->flags & FUNC_FLAGS_METHOD) && (TYPE_METHOD(func->type)->theclass->flags & CLASS_FLAGS_800)) { + deduce.inst = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass); + deduce.tmclass = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass)->templ; + } + + return CTemplTool_DeduceExpr(&deduce, expr); +} + +static TemplClass *CTemplTool_FindNestedTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { + TemplClass *dtempl; + TemplClassInst *dinst; + Type *type; + + if (templ->inst_parent) + return templ; + + CError_ASSERT(1776, (dtempl = deduce->tmclass) && (dinst = deduce->inst)); + + while (1) { + if ( + templ->templ_parent == dtempl && + (type = CScope_GetLocalTagType(dinst->theclass.nspace, templ->theclass.classname)) && + IS_TEMPL_CLASS(type) && + TEMPL_CLASS(type)->templ_parent == templ->templ_parent + ) + return TEMPL_CLASS(type); + + dtempl = dtempl->templ_parent; + if (!dtempl) + break; + + dinst = dinst->parent; + CError_ASSERT(1790, dinst); + } + + return templ; +} + +static Type *CTemplTool_DeduceClassInstanceCopy(TypeDeduce *deduce, TemplClass *templ, TemplArg *args) { + TemplArg *arg; + TemplArg *deducedArgs; + TemplArg *last; + TemplParam *param; + UInt32 qual; + Type *type; + + if (templ->templ_parent) + templ = CTemplTool_FindNestedTemplateInstance(deduce, templ); + + arg = args; + deducedArgs = NULL; + param = templ->templ__params; + + while (arg) { + if (deducedArgs) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + deducedArgs = last; + } + + *last = *arg; + + if (!param || param->pid.type != last->pid.type) { + CError_Error(CErrorStr374); + return &stvoid; + } + + last->pid = param->pid; + param = param->next; + + switch (last->pid.type) { + case TPT_TYPE: + last->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, last->data.typeparam.type, &last->data.typeparam.qual); + break; + + case TPT_NONTYPE: + if (!last->data.paramdecl.expr) { + CError_FATAL(1873); + } else if (CTemplTool_IsTemplateArgumentDependentExpression(last->data.paramdecl.expr)) { + last->data.paramdecl.expr = pointer_generation(CTemplTool_DeduceExpr(deduce, last->data.paramdecl.expr)); + last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); + } + break; + + case TPT_TEMPLATE: + qual = 0; + last->data.ttargtype = CTemplTool_DeduceTypeCopy(deduce, last->data.ttargtype, &qual); + break; + + default: + CError_FATAL(1891); + } + + arg = arg->next; + } + + for (arg = deducedArgs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + break; + continue; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + break; + + switch (arg->data.paramdecl.expr->type) { + case EINTCONST: + case EOBJLIST: + case EMEMBER: + break; + case EOBJREF: + if (CParser_HasInternalLinkage2(arg->data.paramdecl.expr->data.objref)) + CError_Error(CErrorStr357); + break; + default: + CError_Error(CErrorStr371); + arg->data.paramdecl.expr = nullnode(); + break; + } + continue; + + case TPT_TEMPLATE: + if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) + break; + continue; + + default: + CError_FATAL(1937); + } + + break; + } + + if (arg) { + type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); + TYPE_TEMPLATE(type)->u.templ.templ = templ; + TYPE_TEMPLATE(type)->u.templ.args = deducedArgs; + return type; + } + + if ((type = CTemplTool_IsDependentTemplate(templ, deducedArgs))) + return type; + + return TYPE(CTemplClass_GetInstance(templ, deducedArgs, NULL)); +} + +static TemplArg *CTemplTool_FindTemplArg(TemplArg *args, TemplParamID pid) { + while (args) { + if (args->pid.index == pid.index && args->pid.nindex == pid.nindex) { + CError_ASSERT(1984, pid.type == args->pid.type); + return args; + } + args = args->next; + } + + return NULL; +} + +static TemplArg *CTemplTool_DeduceTemplArg(TypeDeduce *deduce, TemplParamID pid) { + TemplClass *tmclass; + TemplClassInst *inst; + TemplArg *arg; + + if ((arg = CTemplTool_FindTemplArg(deduce->args, pid))) + return arg; + + tmclass = deduce->tmclass; + CError_ASSERT(2008, tmclass); + + inst = deduce->inst; + if (!inst) { + CError_ASSERT(2011, tmclass->templ_parent && tmclass->inst_parent); + inst = deduce->tmclass->inst_parent; + } + + while (1) { + if ((arg = CTemplTool_FindTemplArg(inst->inst_args, pid))) + return arg; + + inst = inst->parent; + CError_ASSERT(2022, inst); + } +} + +static Type *CTemplTool_DeduceArrayCopy(TypeDeduce *deduce, Type *type, ENode *index, UInt32 *resultQual) { + if (CTemplTool_IsTemplateArgumentDependentType(type)) + type = CTemplTool_DeduceTypeCopy(deduce, type, resultQual); + + index = CTemplTool_DeduceExpr(deduce, index); + + if (ENODE_IS(index, EINTCONST)) { + if (CInt64_IsNegative(&index->data.intval)) { + CError_Error(CErrorStr124); + index->data.intval = cint64_one; + } + + if (!CDecl_CheckArrayIntegr(type)) + type = TYPE(&stsignedchar); + + type = CDecl_NewArrayType(type, type->size * CInt64_GetULong(&index->data.intval)); + } else { + if (!deduce->x16) + CError_Error(CErrorStr124); + } + + return type; +} + +static Type *CTemplTool_DeduceBitfieldCopy(TypeDeduce *deduce, Type *type, ENode *size, UInt32 *resultQual) { + TypeBitfield *tbitfield; + short sizeval; + short maxsize; + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + UInt32 qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, type, &qual); + } + + if (!IS_TYPE_INT_OR_ENUM(type)) { + CError_Error(CErrorStr138); + type = TYPE(&stunsignedint); + } + + switch (type->size) { + case 1: + maxsize = 8; + break; + case 2: + maxsize = 16; + break; + case 4: + maxsize = 32; + break; + default: + CError_Error(CErrorStr138); + return type; + } + + if (!ENODE_IS(size, EINTCONST)) { + size = CTemplTool_DeduceExpr(deduce, size); + if (!ENODE_IS(size, EINTCONST)) { + CError_Error(CErrorStr124); + return type; + } + } + + sizeval = CInt64_GetULong(&size->data.intval); + if (sizeval > maxsize || CInt64_IsNegative(&size->data.intval)) { + CError_Error(CErrorStr138); + sizeval = 1; + } + + tbitfield = galloc(sizeof(TypeBitfield)); + memclrw(tbitfield, sizeof(TypeBitfield)); + + tbitfield->type = TYPEBITFIELD; + tbitfield->size = type->size; + tbitfield->bitfieldtype = type; + tbitfield->unkB = sizeval; + + return TYPE(tbitfield); +} + +static Type *CTemplTool_DeduceTemplDepType(TypeDeduce *deduce, TypeTemplDep *tdt, UInt32 *resultQual) { + Type *type; + UInt32 qual; + TemplArg *arg; + + qual = 0; + + if (deduce->x14) { + type = CTemplTool_GetSelfRefTemplate(TYPE(tdt)); + if (type && type == TYPE(deduce->tmclass)) + return type; + + switch (tdt->dtype) { + case TEMPLDEP_ARGUMENT: + return TYPE(tdt); + + case TEMPLDEP_QUALNAME: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); + if (type == TYPE(tdt->u.qual.type)) + return TYPE(tdt); + + if (!IS_TYPE_CLASS(type)) { + TypeTemplDep *tdtCopy; + CError_ASSERT(2157, IS_TYPE_TEMPLATE(type)); + tdtCopy = galloc(sizeof(TypeTemplDep)); + *tdtCopy = *tdt; + tdtCopy->u.qual.type = TYPE_TEMPLATE(type); + return TYPE(tdtCopy); + } else if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { + return type; + } else { + CError_Error(CErrorStr150, tdt->u.qual.name->name); + return TYPE(tdt); + } + + case TEMPLDEP_TEMPLATE: + for (arg = tdt->u.templ.args; arg; arg = arg->next) { + if (arg->pid.type == TPT_TYPE) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + return TYPE(tdt); + + case TEMPLDEP_ARRAY: + tdt->u.array.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.array.type, &qual); + return TYPE(tdt); + + case TEMPLDEP_QUALTEMPL: + tdt->u.qualtempl.type = TYPE_TEMPLATE(CTemplTool_DeduceTemplDepType(deduce, tdt->u.qualtempl.type, &qual)); + for (arg = tdt->u.qualtempl.args; arg; arg = arg->next) { + if (arg->pid.type == TPT_TYPE) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + return TYPE(tdt); + + case TEMPLDEP_BITFIELD: + tdt->u.bitfield.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.bitfield.type, &qual); + return TYPE(tdt); + } + } else { + switch (tdt->dtype) { + case TEMPLDEP_ARGUMENT: + if (deduce->x15 && tdt->u.pid.nindex == deduce->nindex) + return TYPE(tdt); + + arg = CTemplTool_DeduceTemplArg(deduce, tdt->u.pid); + if (arg->pid.type == TPT_TEMPLATE) { + CError_ASSERT(2222, IS_TEMPL_CLASS(arg->data.typeparam.type)); + *resultQual = arg->data.typeparam.qual; + return arg->data.typeparam.type; + } + + CError_ASSERT(2226, arg->pid.type == TPT_TYPE); + *resultQual = arg->data.typeparam.qual; + return arg->data.typeparam.type; + + case TEMPLDEP_QUALNAME: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); + if (IS_TYPE_CLASS(type)) { + CDecl_CompleteType(type); + if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { + return type; + } else { + CError_Error(CErrorStr150, tdt->u.qual.name->name); + } + } else { + if ((deduce->x15 || !deduce->inst) && IS_TYPE_TEMPLATE(type)) { + TypeTemplDep *tdtCopy = galloc(sizeof(TypeTemplDep)); + *tdtCopy = *tdt; + tdtCopy->u.qual.type = TYPE_TEMPLATE(type); + return TYPE(tdtCopy); + } else { + CError_Error(CErrorStr340, tdt->u.qual.name->name); + } + } + return TYPE(&stsignedint); + + case TEMPLDEP_TEMPLATE: + return CTemplTool_DeduceClassInstanceCopy(deduce, tdt->u.templ.templ, tdt->u.templ.args); + + case TEMPLDEP_ARRAY: + return CTemplTool_DeduceArrayCopy(deduce, tdt->u.array.type, tdt->u.array.index, resultQual); + + case TEMPLDEP_QUALTEMPL: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qualtempl.type), &qual); + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr121); + return TYPE(&stsignedint); + } + return CTemplTool_DeduceClassInstanceCopy(deduce, TEMPL_CLASS(type), tdt->u.qualtempl.args); + + case TEMPLDEP_BITFIELD: + return CTemplTool_DeduceBitfieldCopy(deduce, tdt->u.bitfield.type, tdt->u.bitfield.size, resultQual); + } + } + + CError_FATAL(2275); + return NULL; +} + +static Type *CTemplTool_DeduceTypeQualCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { + Type *innerType; + UInt32 qual; + UInt32 innerQual; + TypePointer *newPtr; + + qual = *resultQual; + + if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_TEMPLATE(TPTR_TARGET(type))) { + innerQual = 0; + innerType = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(TPTR_TARGET(type)), &innerQual); + + newPtr = galloc(sizeof(TypePointer)); + *newPtr = *TYPE_POINTER(type); + + if (IS_TYPE_POINTER_ONLY(innerType)) { + newPtr->target = galloc(sizeof(TypePointer)); + *TYPE_POINTER(newPtr->target) = *TYPE_POINTER(innerType); + *resultQual = innerQual & (Q_CONST | Q_VOLATILE); + TPTR_QUAL(newPtr->target) |= qual & (Q_CONST | Q_VOLATILE); + } else if (IS_TYPE_MEMBERPOINTER(innerType)) { + newPtr->target = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(newPtr->target) = *TYPE_MEMBER_POINTER(innerType); + *resultQual = innerQual & (Q_CONST | Q_VOLATILE); + TYPE_MEMBER_POINTER(newPtr->target)->qual |= qual & (Q_CONST | Q_VOLATILE); + } else { + newPtr->target = innerType; + *resultQual = (qual | innerQual) & (Q_CONST | Q_VOLATILE); + } + + return TYPE(newPtr); + } + + return CTemplTool_DeduceTypeCopy(deduce, type, resultQual); +} + +FuncArg *CTemplTool_DeduceArgCopy(TypeDeduce *deduce, FuncArg *args) { + FuncArg *resultArgs; + FuncArg *last; + + if (args == &oldstyle || args == &elipsis) + return args; + + resultArgs = NULL; + + while (args) { + if (args == &elipsis) { + last->next = args; + break; + } + + if (resultArgs) { + last->next = galloc(sizeof(FuncArg)); + last = last->next; + } else { + last = galloc(sizeof(FuncArg)); + resultArgs = last; + } + + *last = *args; + last->type = CTemplTool_DeduceTypeQualCopy(deduce, last->type, &last->qual); + CanCreateObject(last->type); + + args = args->next; + } + + return resultArgs; +} + +static ExceptSpecList *CTemplTool_DeduceExSpecCopy(TypeDeduce *deduce, ExceptSpecList *exspec) { + ExceptSpecList *copy; + + copy = galloc(sizeof(ExceptSpecList)); + *copy = *exspec; + + if (copy->type && CTemplTool_IsTemplateArgumentDependentType(copy->type)) + copy->type = CTemplTool_DeduceTypeCopy(deduce, copy->type, ©->qual); + + if (copy->next) + copy->next = CTemplTool_DeduceExSpecCopy(deduce, copy->next); + + return copy; +} + +Type *CTemplTool_DeduceTypeCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { + TemplClassInst *inst; + Type *deduced; + UInt32 qual2; + UInt32 qual; + + switch (type->type) { + case TYPETEMPLATE: + qual = 0; + deduced = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(type), &qual); + if (*resultQual & (Q_CONST | Q_VOLATILE)) { + if (IS_TYPE_POINTER_ONLY(deduced)) { + TypePointer *newPtr = galloc(sizeof(TypePointer)); + *newPtr = *TYPE_POINTER(deduced); + newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); + *resultQual &= ~(Q_CONST | Q_VOLATILE); + deduced = TYPE(newPtr); + } else if (IS_TYPE_MEMBERPOINTER(deduced)) { + TypeMemberPointer *newPtr = galloc(sizeof(TypeMemberPointer)); + *newPtr = *TYPE_MEMBER_POINTER(deduced); + newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); + *resultQual &= ~(Q_CONST | Q_VOLATILE); + deduced = TYPE(newPtr); + } + } + *resultQual |= qual; + return deduced; + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPESTRUCT: + return type; + + case TYPEENUM: + if ( + TYPE_ENUM(type)->nspace->theclass && + (TYPE_ENUM(type)->nspace->theclass->flags & CLASS_FLAGS_100) && + !deduce->x14 + ) + { + CError_ASSERT(2471, TYPE_ENUM(type)->enumname); + inst = TEMPL_CLASS_INST(CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(TYPE_ENUM(type)->nspace->theclass))); + CError_ASSERT(2473, inst && inst->theclass.type == TYPECLASS); + + CDecl_CompleteType(TYPE(inst)); + type = CScope_GetLocalTagType(inst->theclass.nspace, TYPE_ENUM(type)->enumname); + CError_ASSERT(2477, type); + return type; + } + return type; + + case TYPECLASS: + if (!deduce->x14) { + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_100) + return CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(type)); + + if (TYPE_CLASS(type)->nspace->theclass && (TYPE_CLASS(type)->nspace->theclass->flags & CLASS_FLAGS_100)) { + CError_ASSERT(2492, deduce->inst); + CError_ASSERT(2493, TYPE_CLASS(type)->classname); + + type = CScope_GetLocalTagType(deduce->inst->theclass.nspace, TYPE_CLASS(type)->classname); + CError_ASSERT(2496, type); + return type; + } + } + + return type; + + case TYPEARRAY: { + SInt32 elements; + + elements = TPTR_TARGET(type)->size; + if (elements > 0) + elements = type->size / elements; + + deduced = galloc(sizeof(TypePointer)); + *TYPE_POINTER(deduced) = *TYPE_POINTER(type); + TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); + + do { + type = TPTR_TARGET(type); + } while (IS_TYPE_ARRAY(type)); + + if (IS_TYPE_TEMPLATE(type)) { + CDecl_CompleteType(TPTR_TARGET(deduced)); + deduced->size = TPTR_TARGET(deduced)->size * elements; + } + + return deduced; + } + + case TYPEPOINTER: + deduced = galloc(sizeof(TypePointer)); + *TYPE_POINTER(deduced) = *TYPE_POINTER(type); + TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); + return deduced; + + case TYPEBITFIELD: + deduced = galloc(sizeof(TypeBitfield)); + *TYPE_BITFIELD(deduced) = *TYPE_BITFIELD(type); + TYPE_BITFIELD(deduced)->bitfieldtype = CTemplTool_DeduceTypeCopy(deduce, TYPE_BITFIELD(type)->bitfieldtype, resultQual); + return deduced; + + case TYPEMEMBERPOINTER: + deduced = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(deduced) = *TYPE_MEMBER_POINTER(type); + TYPE_MEMBER_POINTER(deduced)->ty1 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty1, resultQual); + qual2 = 0; + TYPE_MEMBER_POINTER(deduced)->ty2 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty2, &qual2); + + if ( + !IS_TYPE_CLASS(TYPE_MEMBER_POINTER(deduced)->ty2) && + !deduce->x14 && + !deduce->x15 && + !deduce->x16 + ) + { + CError_Error(CErrorStr232); + return TYPE_MEMBER_POINTER(deduced)->ty1; + } + return deduced; + + case TYPEFUNC: + if (TYPE_FUNC(type)->flags & FUNC_FLAGS_METHOD) { + qual2 = 0; + deduced = galloc(sizeof(TypeMethod)); + *TYPE_METHOD(deduced) = *TYPE_METHOD(type); + TYPE_METHOD(deduced)->x22 = 0; + TYPE_METHOD(deduced)->theclass = TYPE_CLASS(CTemplTool_DeduceTypeQualCopy(deduce, TYPE(TYPE_METHOD(type)->theclass), &qual2)); + CError_ASSERT(2556, IS_TYPE_CLASS(TYPE_METHOD(deduced)->theclass)); + } else { + deduced = galloc(sizeof(TypeFunc)); + *TYPE_FUNC(deduced) = *TYPE_FUNC(type); + } + + TYPE_FUNC(deduced)->flags &= ~FUNC_FLAGS_100000; + + qual2 = TYPE_FUNC(type)->qual; + TYPE_FUNC(deduced)->functype = CTemplTool_DeduceTypeQualCopy(deduce, TYPE_FUNC(type)->functype, &qual2); + TYPE_FUNC(deduced)->qual = qual2; + + TYPE_FUNC(deduced)->args = CTemplTool_DeduceArgCopy(deduce, TYPE_FUNC(type)->args); + if (TYPE_FUNC(type)->exspecs) + TYPE_FUNC(deduced)->exspecs = CTemplTool_DeduceExSpecCopy(deduce, TYPE_FUNC(type)->exspecs); + + CDecl_SetResultReg(TYPE_FUNC(deduced)); + return deduced; + + case TYPETEMPLDEPEXPR: + CError_Error(CErrorStr190); + return &stvoid; + + default: + CError_FATAL(2580); + return NULL; + } +} + +Type *CTemplTool_ResolveMemberSelfRefs(TemplClass *templ, Type *type, UInt32 *resultQual) { + TypeDeduce deduce; + + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = templ; + deduce.x14 = 1; + + if (IS_TYPE_FUNC(type)) { + TYPE_FUNC(type)->functype = CTemplTool_DeduceTypeCopy(&deduce, TYPE_FUNC(type)->functype, &TYPE_FUNC(type)->qual); + TYPE_FUNC(type)->args = CTemplTool_DeduceArgCopy(&deduce, TYPE_FUNC(type)->args); + CDecl_SetResultReg(TYPE_FUNC(type)); + } else { + type = CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); + } + + return type; +} + +Boolean CTemplTool_IsSameTemplateType(Type *a, Type *b) { + return CTemplTool_GetSelfRefTemplate(b) == a; +} diff --git a/compiler_and_linker/unsorted/CodeGen.c b/compiler_and_linker/unsorted/CodeGen.c index d87d80f..7b73bee 100644 --- a/compiler_and_linker/unsorted/CodeGen.c +++ b/compiler_and_linker/unsorted/CodeGen.c @@ -258,11 +258,9 @@ static void allocate_local_vregs(void) { vi->reg = 0; assign_register_by_type(&pic_base); pic_base_reg = vi->reg; -#line 497 - CError_ASSERT(pic_base_reg); + CError_ASSERT(497, pic_base_reg); } else { -#line 500 - CError_FATAL(); + CError_FATAL(500); } } else { pic_base_reg = 0; @@ -338,8 +336,7 @@ static void allocate_local_GPRs(void) { vi->reg = 0; assign_register_by_type(&pic_base); pic_base_reg = vi->reg; -#line 605 - CError_ASSERT(pic_base_reg); + CError_ASSERT(605, pic_base_reg); } else { pic_base_reg = 0; } @@ -398,8 +395,7 @@ static void allocate_local_GPRs(void) { break; assign_register_by_type(winning_obj); -#line 698 - CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + CError_ASSERT(698, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); } } @@ -452,8 +448,7 @@ static void allocate_local_FPRs(void) { break; assign_register_by_type(winning_obj); -#line 782 - CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + CError_ASSERT(782, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); } } @@ -504,8 +499,7 @@ static void allocate_local_VRs(void) { break; assign_register_by_type(winning_obj); -#line 846 - CError_ASSERT(Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + CError_ASSERT(846, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); } } @@ -534,8 +528,7 @@ void move_assigned_argument(Object *obj, short reg) { vi = Registers_GetVarInfo(obj); type = obj->type; -#line 901 - CError_ASSERT(obj->datatype == DLOCAL); + CError_ASSERT(901, obj->datatype == DLOCAL); if (!vi->used) return; @@ -547,8 +540,7 @@ void move_assigned_argument(Object *obj, short reg) { if (vi->reg != reg) emitpcode(PC_MR, vi->reg, reg); if (reg < GPRLimit) { -#line 916 - CError_FAIL((vi->regHi == reg) || (vi->reg == (reg + 1))); + CError_FAIL(916, (vi->regHi == reg) || (vi->reg == (reg + 1))); if (vi->regHi != (reg + 1)) emitpcode(PC_MR, vi->regHi, reg + 1); } else { @@ -558,8 +550,7 @@ void move_assigned_argument(Object *obj, short reg) { if (vi->regHi != reg) emitpcode(PC_MR, vi->regHi, reg); if (reg < GPRLimit) { -#line 931 - CError_FAIL((vi->reg == reg) || (vi->regHi == (reg + 1))); + CError_FAIL(931, (vi->reg == reg) || (vi->regHi == (reg + 1))); if (vi->reg != (reg + 1)) emitpcode(PC_MR, vi->reg, reg + 1); } else { @@ -595,8 +586,7 @@ void move_assigned_argument(Object *obj, short reg) { load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4); break; default: -#line 993 - CError_FATAL(); + CError_FATAL(993); } } else if (IS_TYPE_FLOAT(type)) { load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0); @@ -639,8 +629,7 @@ void move_assigned_argument(Object *obj, short reg) { load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); break; default: -#line 1095 - CError_FATAL(); + CError_FATAL(1095); } } } else if (!optimizing) { @@ -682,8 +671,7 @@ static void load_TOC_pointers(void) { emitpcode(PC_MR, vi->reg, opnd.reg); break; default: -#line 1206 - CError_FATAL(); + CError_FATAL(1206); } } } @@ -782,8 +770,7 @@ static void gotoexpression(ENode *expr) { if (opnd.optype != OpndType_GPR) Coerce_to_register(&opnd, TYPE(&void_ptr), 0); -#line 1397 - CError_ASSERT(opnd.optype == OpndType_GPR); + CError_ASSERT(1397, opnd.optype == OpndType_GPR); for (list = codelabellist; list; list = list->next) pcbranch(pclastblock, list->label->pclabel); @@ -854,8 +841,7 @@ static void returnstatement(ENode *expr, Boolean dont_branch) { static void capturestackpointer(Object *obj) { branch_label(makepclabel()); -#line 1568 - CError_ASSERT(obj->datatype == DLOCAL); + CError_ASSERT(1568, obj->datatype == DLOCAL); load_store_register(PC_STW, 1, local_base_register(obj), obj, 20); branch_label(makepclabel()); @@ -864,8 +850,7 @@ static void capturestackpointer(Object *obj) { static void resetstackpointer(Object *obj) { PCode *pc; -#line 1595 - CError_ASSERT(obj->datatype == DLOCAL); + CError_ASSERT(1595, obj->datatype == DLOCAL); branch_label(makepclabel()); @@ -1012,8 +997,7 @@ void CodeGen_Generator(Statement **statements, Object *func, UInt8 mysteryFlag, capturestackpointer(stmt->expr->data.objref); break; case ST_ENDCATCHDTOR: -#line 2056 - CError_ASSERT(stmt->expr->data.objref->datatype == DLOCAL); + CError_ASSERT(2056, stmt->expr->data.objref->datatype == DLOCAL); obj = stmt->expr->data.objref; add_immediate(3, local_base_register(obj), obj, 0); { @@ -1028,8 +1012,7 @@ void CodeGen_Generator(Statement **statements, Object *func, UInt8 mysteryFlag, if (stmt->expr) { // ... will need to understand inline ASM properly for this ... if (((WeirdInlineAsmThing *) stmt->expr)->x2 & 1) { -#line 2076 - CError_FATAL(); + CError_FATAL(2076); } else { branch_label(makepclabel()); InlineAsm_TranslateIRtoPCode(stmt); @@ -1037,16 +1020,13 @@ void CodeGen_Generator(Statement **statements, Object *func, UInt8 mysteryFlag, } break; case ST_BEGINLOOP: -#line 2086 - CError_FATAL(); + CError_FATAL(2086); break; case ST_ENDLOOP: -#line 2090 - CError_FATAL(); + CError_FATAL(2090); break; default: -#line 2094 - CError_FATAL(); + CError_FATAL(2094); } check_temp_registers(); } @@ -1168,8 +1148,7 @@ void CodeGen_GenVDispatchThunk(Object *thunkobj, Object *obj, SInt32 a, SInt32 b save_traceback = copts.traceback; CodeGen_InitialSanityCheck(); -#line 2270 - CError_ASSERT(b == 0); + CError_ASSERT(2270, b == 0); initpcode(); makepcblock(); @@ -1276,8 +1255,7 @@ void CodeGen_SOMStub(Object *a, Object *b, Object *c, SInt32 offset) { CodeGen_InitialSanityCheck(); memclrw(&opnd, sizeof(Operand)); -#line 2528 - CError_ASSERT(offset <= 0x7FFF); + CError_ASSERT(2528, offset <= 0x7FFF); initpcode(); makepcblock(); @@ -1296,8 +1274,7 @@ void CodeGen_SOMStub(Object *a, Object *b, Object *c, SInt32 offset) { Coerce_to_register(&opnd, TYPE(&void_ptr), 12); if (opnd.optype != OpndType_GPR) { -#line 2562 - CError_FATAL(); + CError_FATAL(2562); } else if (opnd.reg != 12) { emitpcode(PC_MR, 12, opnd.reg); } @@ -1933,19 +1910,19 @@ void CodeGen_UpdateBackEndOptions(void) { copts.global_optimizer = 1; } -void CodeGen_objc_method_self_offset() { +SInt32 CodeGen_objc_method_self_offset(ObjCMethod *meth) { // TODO objc } -void CodeGen_objc_method_sel_offset() { +SInt32 CodeGen_objc_method_sel_offset(ObjCMethod *meth) { // TODO objc } -void CodeGen_objc_method_arg_offset() { +SInt32 CodeGen_objc_method_arg_offset(ObjCMethod *meth, ObjCMethodArg *arg) { // TODO objc } -void CodeGen_objc_method_args_size() { +SInt32 CodeGen_objc_method_args_size(ObjCMethod *meth) { // TODO objc } @@ -2386,8 +2363,7 @@ char *CodeGen_ExpandSpecialMacro(Macro *macro) { if (!copts.ANSI_strict && macro == &ppcM) return "1"; if (macro == &_ppc_M) return "1"; -#line 4801 - CError_FATAL(); + CError_FATAL(4801); return "0"; } diff --git a/compiler_and_linker/unsorted/CodeMotion.c b/compiler_and_linker/unsorted/CodeMotion.c index 8ebcdf0..00e8015 100644 --- a/compiler_and_linker/unsorted/CodeMotion.c +++ b/compiler_and_linker/unsorted/CodeMotion.c @@ -155,8 +155,7 @@ static int isuniquedefinition(PCode *pcode, Loop *loop) { return 0; } } else { -#line 292 - CError_FATAL(); + CError_FATAL(292); } return 1; @@ -227,8 +226,7 @@ static int uniquelyreachesalluses(int defID, Loop *loop) { } } } else { -#line 382 - CError_FATAL(); + CError_FATAL(382); } return 1; @@ -331,8 +329,7 @@ static void moveinvariantcomputation(PCode *pcode, Loop *loop) { bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); } } else { -#line 545 - CError_FATAL(); + CError_FATAL(545); } } @@ -363,8 +360,7 @@ static int srawi_addze_maymove(PCode *pcode, Loop *loop) { return 0; } } else { -#line 582 - CError_FATAL(); + CError_FATAL(582); } if (!uniquelyreachesalluses(pcode->defID, loop)) @@ -486,8 +482,7 @@ static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode insertpreheaderblock(loop); pc3 = preheader->lastPCode; -#line 775 - CError_ASSERT(pc3->op == PC_B); + CError_ASSERT(775, pc3->op == PC_B); deletepcode(pc3); deletepcode(pc2); appendpcode(preheader, pc2); @@ -715,8 +710,7 @@ static void simpleunswitchloop(Loop *loop) { bestpath2 = pathiter1; } -#line 1192 - CError_ASSERT(bestpath2->block); + CError_ASSERT(1192, bestpath2->block); if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B) deletepcode(bestpath2->block->lastPCode); @@ -753,8 +747,7 @@ static void simpleunswitchloop(Loop *loop) { op23 = &loop->body->lastPCode->args[i]; } -#line 1250 - CError_ASSERT(op23 != NULL); + CError_ASSERT(1250, op23 != NULL); changesuccessor(loop->body, op23->data.label.label->block, path2_24->block); op23->data.label.label = path2_24->block->labels; @@ -765,8 +758,7 @@ static void simpleunswitchloop(Loop *loop) { op23 = &preheader21->lastPCode->args[i]; } -#line 1267 - CError_ASSERT(op23 != NULL); + CError_ASSERT(1267, op23 != NULL); changesuccessor(preheader21, op23->data.label.label->block, loop->body); op23->data.label.label = loop->body->labels; @@ -777,8 +769,7 @@ static void simpleunswitchloop(Loop *loop) { op23 = &loop->preheader->lastPCode->args[i]; } -#line 1284 - CError_ASSERT(op23 != NULL); + CError_ASSERT(1284, op23 != NULL); changesuccessor(loop->preheader, op23->data.label.label->block, headercopy); op23->data.label.label = headercopy->labels; @@ -884,8 +875,7 @@ static void moveinvariantsfromloop(Loop *loop) { } } } else { -#line 1434 - CError_FATAL(); + CError_FATAL(1434); } bitvectorsetbit(defID, myvec); diff --git a/compiler_and_linker/unsorted/Exceptions.c b/compiler_and_linker/unsorted/Exceptions.c index e69de29..80d0cc4 100644 --- a/compiler_and_linker/unsorted/Exceptions.c +++ b/compiler_and_linker/unsorted/Exceptions.c @@ -0,0 +1,857 @@ +#include "compiler/Exceptions.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CInit.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +static PCAction *pc_actions; +static PCAction *last_pc_action; +EANode *DAG[EAT_NACTIONS]; +static GList exceptmodule; +static OLinkList *except_refs; +static OLinkList *last_except_ref; + +static EANode *makeEAnode(ExceptionAction *ea) { + EANode *prev; + EANode *node; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->action == ea) + return node; + } + + if (ea->prev) + prev = makeEAnode(ea->prev); + else + prev = NULL; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->prev == prev && CExcept_ActionCompare(node->action, ea)) + return node; + } + + node = lalloc(sizeof(EANode)); + node->prev = prev; + node->action = ea; + node->count = 0; + node->xE = 0; + + node->dagListNext = DAG[ea->type]; + DAG[ea->type] = node; + + if (prev) + prev->count++; + return node; +} + +static void addrelocation(Object *obj, SInt32 offset) { + OLinkList *ref; + + ref = lalloc(sizeof(OLinkList)); + ref->next = NULL; + ref->obj = obj; + ref->offset = offset; + ref->somevalue = 0; + if (except_refs) + last_except_ref->next = ref; + else + except_refs = ref; + last_except_ref = ref; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct AABC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; +} AABC; + +typedef struct AACC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; +} AACC; + +typedef struct AABBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; +} AABBC; + +typedef struct AABCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; +} AABCC; + +typedef struct AACCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; +} AACCC; + +typedef struct AABBBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt16 e; + UInt32 f; +} AABBBC; + +typedef struct AABBCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; + UInt32 f; +} AABBCC; + +typedef struct AACCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; +} AACCCC; + +typedef struct AABCCCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AABCCCC; + +typedef struct AACCCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AACCCCC; + +typedef struct AAB { + UInt8 a; + UInt8 b; + UInt16 c; +} AAB; + +typedef struct AAC { + UInt8 a; + UInt8 b; + UInt32 c; +} AAC; + +typedef struct AA { + UInt8 a; + UInt8 b; +} AA; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void allocateactioninfo(EANode *node) { + ExceptionAction *ea; + SInt32 offset; + UInt32 flag26; + int reg; + int reg2; + + while (node && (node->xE == 0 || node->prev == NULL)) { + offset = exceptmodule.size; + if (node->xE == 0) + node->xE = offset; + + flag26 = node->prev ? 0 : 0x80; + + ea = node->action; + + switch (ea->type) { + case EAT_NOP: + CError_FATAL(146); + break; + case EAT_DESTROYLOCAL: { + if (local_is_16bit_offset(ea->data.destroy_local.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALCOND: { + reg = OBJECT_REG(ea->data.destroy_local_cond.cond); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_local_cond.cond)) && + local_is_16bit_offset(ea->data.destroy_local_cond.local) + ) + { + AABBC e; + e.a = flag26 | 3; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x12; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 10); + } + break; + } + case EAT_DESTROYLOCALOFFSET: { + if (local_is_16bit_offset(ea->data.destroy_local_offset.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.destroy_local_offset.offset + local_offset_16(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(ea->data.destroy_local_offset.offset + local_offset_32(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALPOINTER: { + reg = OBJECT_REG(ea->data.destroy_local_pointer.pointer); + if (reg || local_is_16bit_offset(ea->data.destroy_local_pointer.pointer)) { + AABC e; + e.a = flag26 | 4; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x13; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALARRAY: { + if (local_is_16bit_offset(ea->data.destroy_local_array.localarray)) { + AABBBC e; + e.a = flag26 | 5; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord16(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord16(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 8); + } else { + AACCCC e; + e.a = flag26 | 0x14; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord32(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBER: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 7; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x16; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYBASE: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 6; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x15; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYMEMBERCOND: { + reg = OBJECT_REG(ea->data.destroy_member_cond.cond); + reg2 = OBJECT_REG(ea->data.destroy_member_cond.objectptr); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_member_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.destroy_member_cond.objectptr)) + ) + { + AABBCC e; + e.a = flag26 | 8; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 10); + } else { + AACCCC e; + e.a = flag26 | 0x17; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBERARRAY: { + reg = OBJECT_REG(ea->data.destroy_member_array.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member_array.objectptr)) { + AABCCCC e; + e.a = flag26 | 9; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 16); + } else { + AACCCCC e; + e.a = flag26 | 0x18; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 18); + } + break; + } + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: { + reg = OBJECT_REG(ea->data.delete_pointer.pointerobject); + if (reg || local_is_16bit_offset(ea->data.delete_pointer.pointerobject)) { + AABC e; + e.a = flag26 | 0xA; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x19; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 6); + } + break; + } + case EAT_DELETEPOINTERCOND: { + reg = OBJECT_REG(ea->data.delete_pointer_cond.cond); + reg2 = OBJECT_REG(ea->data.delete_pointer_cond.pointerobject); + if ( + (reg || local_is_16bit_offset(ea->data.delete_pointer_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.delete_pointer_cond.pointerobject)) + ) + { + AABBC e; + e.a = flag26 | 0xB; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x1A; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 10); + } + break; + } + case EAT_CATCHBLOCK: { + AACCC e; + e.a = flag26 | 0x10; + e.b = 0; + e.c = 0; + if (ea->data.catch_block.catch_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.catch_block.catch_label->pclabel->block->codeOffset); + else + e.d = 0; + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + if (ea->data.catch_block.catch_typeid) + addrelocation(ea->data.catch_block.catch_typeid, offset + 2); + break; + } + case EAT_ACTIVECATCHBLOCK: { + if (local_is_16bit_offset(ea->data.active_catch_block.catch_info_object)) { + AAB e; + e.a = flag26 | 0xD; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } else { + AAC e; + e.a = flag26 | 0x1B; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } + break; + } + case EAT_SPECIFICATION: { + AABCC e; + int i; + + e.a = flag26 | 0xF; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.specification.unexp_ids); + if (ea->data.specification.unexp_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.specification.unexp_label->pclabel->block->codeOffset); + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.specification.unexp_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + + for (i = 0; i < ea->data.specification.unexp_ids; i++) { + addrelocation(ea->data.specification.unexp_id[i], 12 + i * 4 + offset); + AppendGListLong(&exceptmodule, 0); + } + break; + } + case EAT_TERMINATE: { + AA e; + e.a = flag26 | 0xE; + e.b = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + break; + } + default: + CError_FATAL(671); + } + + node = node->prev; + } + + if (node) { + AAB e; + e.a = 1; + e.b = 0; + e.c = CTool_EndianConvertWord16(node->xE); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } +} + +static UInt32 findPC(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + CError_ASSERT(704, FITS_IN_USHORT(pc)); + return pc; +} + +static UInt32 findPC_long(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + return pc; +} + +static void initializeexceptiontables(void) { + int i; + + for (i = 0; i < EAT_NACTIONS; i++) + DAG[i] = NULL; + + pc_actions = last_pc_action = NULL; + except_refs = last_except_ref = NULL; +} + +int countexceptionactionregisters(ExceptionAction *actions) { + int count = 0; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if (OBJECT_REG(actions->data.destroy_local_cond.cond)) + count++; + break; + case EAT_DESTROYLOCALPOINTER: + if (OBJECT_REG(actions->data.destroy_local_pointer.pointer)) + count++; + break; + case EAT_DESTROYMEMBER: + if (OBJECT_REG(actions->data.destroy_member.objectptr)) + count++; + break; + case EAT_DESTROYBASE: + if (OBJECT_REG(actions->data.destroy_base.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERCOND: + if (OBJECT_REG(actions->data.destroy_member_cond.cond)) + count++; + if (OBJECT_REG(actions->data.destroy_member_cond.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERARRAY: + if (OBJECT_REG(actions->data.destroy_member_array.objectptr)) + count++; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if (OBJECT_REG(actions->data.delete_pointer.pointerobject)) + count++; + break; + case EAT_DELETEPOINTERCOND: + if (OBJECT_REG(actions->data.delete_pointer_cond.cond)) + count++; + if (OBJECT_REG(actions->data.delete_pointer_cond.pointerobject)) + count++; + break; + } + actions = actions->prev; + } + + return count; +} + +void noteexceptionactionregisters(ExceptionAction *actions, PCodeArg *ops) { + Object *obj; + int reg; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYLOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_pointer.pointer))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYBASE: + if ((reg = OBJECT_REG(obj = actions->data.destroy_base.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERARRAY: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_array.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTERCOND: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + } + actions = actions->prev; + } +} + +void recordexceptionactions(PCode *instr, ExceptionAction *actions) { + PCAction *pca; + + if (!actions && (!last_pc_action || !last_pc_action->actions)) + return; + + pca = lalloc(sizeof(PCAction)); + pca->next = NULL; + pca->firstInstr = pca->lastInstr = instr; + pca->actions = actions; + pca->prev = last_pc_action; + if (last_pc_action) + last_pc_action->next = pca; + else + pc_actions = pca; + last_pc_action = pca; + + branch_label(makepclabel()); + while (actions) { + if (actions->type == EAT_CATCHBLOCK && actions->data.catch_block.catch_label->pclabel) + pcbranch(instr->block, actions->data.catch_block.catch_label->pclabel); + else if (actions->type == EAT_SPECIFICATION && actions->data.specification.unexp_label->pclabel) + pcbranch(instr->block, actions->data.specification.unexp_label->pclabel); + actions = actions->prev; + } +} + +void deleteexceptionaction(PCAction *pca) { + if (pca->prev) + pca->prev->next = pca->next; + else + pc_actions = pca->next; + + if (pca->next) + pca->next->prev = pca->prev; +} + +static int mergeexceptionactions(void) { + int count; + PCAction *pca; + PCAction *prev; + + if (!pc_actions) + return 0; + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->firstInstr->block->flags & fPCBlockFlag20) + deleteexceptionaction(pca); + } + + if (!(pca = pc_actions)) + return 0; + + while (pca) { + pca->node = pca->actions ? makeEAnode(pca->actions) : NULL; + pca = pca->next; + } + + prev = pc_actions; + for (pca = pc_actions->next; pca; pca = pca->next) { + if (pca->node == prev->node) { + prev->lastInstr = pca->lastInstr; + deleteexceptionaction(pca); + } else { + prev = pca; + } + } + + count = 0; + for (pca = pc_actions; pca; pca = pca->next) { + if (!pca->actions) + deleteexceptionaction(pca); + else + count++; + } + + return count; +} + +typedef struct ExceptionThing { + UInt32 x0; + UInt16 x4; + UInt16 x6; +} ExceptionThing; + +void dumpexceptiontables(Object *function, SInt32 codesize) { + PCAction *pca; + UInt32 insn_start; + UInt32 insn_count; + UInt16 *sh; + ExceptionThing *thing; + int count; + + count = mergeexceptionactions(); + InitGList(&exceptmodule, 256); + AppendGListNoData(&exceptmodule, 8 * count + 4); + AppendGListLong(&exceptmodule, 0); + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->node->count == 0 && pca->node->xE == 0) + allocateactioninfo(pca->node); + } + + sh = (UInt16 *) *exceptmodule.data; + if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[0] |= 4; + if (copts.altivec_vrsave) + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] << 11) | 0x400); + else + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] & 0x1F) << 11); + } else { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[1] = 0; + } + + thing = (ExceptionThing *) (sh + 2); + pca = pc_actions; + while (pca) { + insn_start = findPC_long(pca->firstInstr); + insn_count = (findPC_long(pca->lastInstr) - insn_start) / 4; + CError_ASSERT(1203, (insn_count & 0xFFFF0000) == 0); + thing->x0 = CTool_EndianConvertWord32(insn_start + 4); + thing->x4 = CTool_EndianConvertWord16(insn_count); + thing->x6 = CTool_EndianConvertWord16(pca->node->xE); + pca = pca->next; + thing++; + } + + LockGList(&exceptmodule); + ObjGen_DeclareExceptionTables(function, codesize, *exceptmodule.data, exceptmodule.size, except_refs); + FreeGList(&exceptmodule); +} diff --git a/compiler_and_linker/unsorted/FuncLevelAsmPPC.c b/compiler_and_linker/unsorted/FuncLevelAsmPPC.c index d054191..a1ea8cc 100644 --- a/compiler_and_linker/unsorted/FuncLevelAsmPPC.c +++ b/compiler_and_linker/unsorted/FuncLevelAsmPPC.c @@ -1,22 +1,393 @@ #include "compiler/FuncLevelAsmPPC.h" +#include "compiler/CCompiler.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CodeGen.h" +#include "compiler/Coloring.h" +#include "compiler/CompilerTools.h" +#include "compiler/uDump.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/InlineAsmRegisters.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" -void setup_assembly_argument(Object *obj, short i) { +static EntryPoint *entrypoints_head; +static EntryPoint **entrypoints_tail; + +void setup_assembly_argument(Object *obj, short reg) { + VarInfo *vi; + Type *type; + + vi = Registers_GetVarInfo(obj); + type = obj->type; + vi->used = 1; + + if (!requires_frame) { + if (is_register_object(obj)) { + if (!reg) + CError_Error(CErrorStr263, obj->name->name); + + if (TYPE_IS_8BYTES(type)) { + short regLo; + short regHi; + if (reg < 10) { + if (copts.little_endian) { + regLo = reg; + regHi = reg + 1; + } else { + regLo = reg + 1; + regHi = reg; + } + retain_GPR_pair(obj, regLo, regHi); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, regLo, obj); + } + } else if (IS_TYPE_FLOAT(type)) { + retain_register(obj, RegClass_FPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_FPR, reg, obj); + } else if (IS_TYPE_VECTOR(type)) { + retain_register(obj, RegClass_VR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_VR, reg, obj); + } else { + retain_register(obj, RegClass_GPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, reg, obj); + } + } + } else { + if (is_register_object(obj)) { + vi = Registers_GetVarInfo(obj); + if (!vi->reg) { + assign_register_by_type(obj); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, obj->name->name); + else + InlineAsm_InsertRegister(obj->name->name, vi->rclass, vi->reg, obj); + } + } + } } -void assign_local_addresses() { +void assign_local_addresses(void) { + VarInfo *vi; + ObjectList *list; + Object *object; + + for (list = locals; list; list = list->next) { + vi = CodeGen_GetNewVarInfo(); + list->object->u.var.info = vi; + list->object->flags |= OBJECT_FLAGS_UNUSED; + vi->used = 1; + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (is_register_object(object)) { + vi = Registers_GetVarInfo(object); + if (!vi->reg) { + assign_register_by_type(object); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, object->name->name); + else + InlineAsm_InsertRegister(object->name->name, vi->rclass, vi->reg, object); + } + } + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (OBJECT_REG(object) == 0) + assign_local_memory(object); + } } -static void FuncAsm_PreScanDirectives() { +static void FuncAsm_PreScanDirectives(void) { + SInt32 directive; + Boolean save_eoltokens; + + in_assembler = 1; + save_eoltokens = cprep_eoltokens; + cprep_eoltokens = 1; + + if (setjmp(InlineAsm_assemblererror) == 0) { + while (tk == TK_IDENTIFIER && (directive = InlineAsm_IsDirective(1))) { + InlineAsm_ProcessDirective(directive); + + if (tk == ';' || tk == TK_NEG7) { + CPrep_TokenStreamFlush(); + tk = lex(); + } else { + InlineAsm_SyntaxError(CErrorStr113); + } + + if (directive == IADirective_FrAlloc) { + requires_frame = 1; + break; + } else if (directive == IADirective_NoFrAlloc) { + user_responsible_for_frame = 1; + break; + } + } + } + + in_assembler = 0; + cprep_eoltokens = save_eoltokens; } -static void FuncAsm_AddEntryPoint() { +static void FuncAsm_AddEntryPoint(Statement *stmt, PCodeBlock *block) { + EntryPoint *ep; + IAEntryPoint *ia_ep; + + ia_ep = (IAEntryPoint *) stmt->expr; + ep = lalloc(sizeof(EntryPoint)); + memclrw(ep, sizeof(EntryPoint)); + + ep->object = ia_ep->x8; + ep->block = block; + + *entrypoints_tail = ep; + entrypoints_tail = &ep->next; + + block->flags |= fPCBlockFlag8000; } -void Assembler() { +void Assembler(Object *func) { + PCodeBlock *block; + Statement *stmt; + Boolean flag17; + Boolean flag16; + char *name; + InlineAsm *ia; + Boolean save_unusedvar; + Boolean save_unusedarg; + + flag17 = 0; + flag16 = 0; + + init_endian(); + init_stack_globals(func); + memclrw(asm_alloc_flags, sizeof(asm_alloc_flags)); + fralloc_parameter_area_size = 0; + user_responsible_for_frame = 0; + assembledinstructions = 0; + + entrypoints_head = NULL; + entrypoints_tail = &entrypoints_head; + + stmt = curstmt; + + if (func && func->name) + PrintProgressFunction(func->name->name); + + CodeGen_InitialSanityCheck(); + + if (func->qual & Q_INLINE) + PPCError_Warning(173); + + CheckCLabels(); + + if (fatalerrors) + return; + + if (copts.isGeneratingDebugInfo) + CPrep_SetSourceFile(&cparser_fileoffset); + + sm_section = SECT_TEXT; + + initpcode(); + + pclabel(prologue = makepcblock(), makepclabel()); + pclabel(block = makepcblock(), makepclabel()); + pcbranch(prologue, block->labels); + + resetTOCvarinfo(); + InlineAsm_InitializePPC(); + FuncAsm_PreScanDirectives(); + + disable_optimizer = 1; + + init_registers(); + assign_arguments_to_memory(func, 0, 0); + init_frame_sizes(0); + + if (copts.debuglisting) + DumpIR(stmt, func); + + cprep_eoltokens = 1; + in_assembler = 1; + + save_unusedvar = copts.warn_unusedvar; + save_unusedarg = copts.warn_unusedarg; + copts.warn_unusedvar = 0; + copts.warn_unusedarg = 0; + + InlineAsm_ScanFunction('}'); + + expandTOCreferences(&stmt->next); + + if (!anyerrors && copts.debuglisting) + DumpIR(stmt, func); + + in_assembler = 0; + cprep_eoltokens = 0; + + name = CMangler_GetLinkName(func)->name; + func->flags |= OBJECT_FLAGS_4; + + if (fralloc_parameter_area_size) + update_out_param_size(fralloc_parameter_area_size); + if (!user_responsible_for_frame) + process_arguments(move_assigned_argument, 0); + + branch_label(makepclabel()); + assign_labels(stmt->next); + + copts.warn_unusedvar = save_unusedvar; + copts.warn_unusedarg = save_unusedarg; + + for (stmt = stmt->next; stmt; stmt = stmt->next) { + current_statement = stmt; + switch (stmt->type) { + case ST_ASM: + if ((ia = (InlineAsm *) stmt->expr)) { + if (ia->flags & IAFlag1) { + if (ia->opcode == IADirective_Entry) { + branch_label(makepclabel()); + FuncAsm_AddEntryPoint(stmt, pclastblock); + } else if (ia->opcode == IADirective_FrFree) { + if (flag16) + PPCError_Error(188); + else + flag16 = 1; + + asm_alloc_flags[3] = 1; + asm_alloc_flags[4] = 1; + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fPCBlockFlag2; + + CheckCLabels(); + if (fatalerrors) + return; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + colorinstructions(func); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + compute_frame_sizes(); + generate_prologue(prologue, 0); + epilogue = pclastblock; + generate_epilogue(epilogue, 0); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + + flag17 = 1; + } + } else { + branch_label(makepclabel()); + asm_alloc_flags[6] = 0; + asm_alloc_flags[7] = 0; + InlineAsm_TranslateIRtoPCode(stmt); + asm_alloc_flags[4] = 0; + } + } + break; + case ST_LABEL: + if (!stmt->label->pclabel->resolved) + branch_label(stmt->label->pclabel); + break; + default: + CError_FATAL(525); + } + } + + current_statement = NULL; + + if (fatalerrors) + return; + CheckCLabels(); + if (fatalerrors) + return; + + if (!flag17) { + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fPCBlockFlag2; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + + if (!asm_alloc_flags[1]) { + colorinstructions(func); + if (fatalerrors) + return; + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + } + + compute_frame_sizes(); + if (asm_alloc_flags[1]) + no_frame_for_asm(); + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1]) { + generate_prologue(prologue, 0); + generate_epilogue(epilogue, !asm_alloc_flags[6] && !asm_alloc_flags[7]); + } + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + } + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1] && needs_frame()) { + if (asm_alloc_flags[3]) { + if (!asm_alloc_flags[5] || !asm_alloc_flags[6]) + PPCError_Warning(187, "blr"); + if (asm_alloc_flags[8]) + PPCError_Warning(186); + } else { + PPCError_Warning(185, "blr"); + } + } + + func->section = sm_section; + + if (copts.isGeneratingDebugInfo) + symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + + copts.peephole = 0; + if (pic_base_label) + pic_base_pcodelabel = pic_base_label->pclabel; + assemblefunction(func, entrypoints_head); + + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "[FUNCTION-LEVEL ASM] FINAL CODE"); + + CFunc_WarnUnused(); } -void SetupAssembler() { +void SetupAssembler(void) { } -void CleanupAssembler() { +void CleanupAssembler(void) { } diff --git a/compiler_and_linker/unsorted/FunctionCalls.c b/compiler_and_linker/unsorted/FunctionCalls.c index e69de29..e746989 100644 --- a/compiler_and_linker/unsorted/FunctionCalls.c +++ b/compiler_and_linker/unsorted/FunctionCalls.c @@ -0,0 +1,642 @@ +#include "compiler/FunctionCalls.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/InstrSelection.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/StackFrame.h" +#include "compiler/StructMoves.h" +#include "compiler/types.h" + +enum { + AIF_PassInGPR = 1, + AIF_PassInFPR = 2, + AIF_PassOnStack = 4, + AIF_ExtendTo32Bits = 8, + AIF_ForceDoublePrecision = 0x10, + AIF_PassInVR = 0x20, + AIF_PassMask = AIF_PassInGPR | AIF_PassInFPR | AIF_PassOnStack | AIF_PassInVR +}; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ArgInfo { + struct ArgInfo *next; + ENode *expr; + Operand opnd; + SInt32 offset; + short gpr; + short gprHi; + short fpr; + short vr; + short evaluated; + short flags; +} ArgInfo; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs); + +static ArgInfo *make_arginfo(ENode *expr) { + ArgInfo *info = lalloc(sizeof(ArgInfo)); + memclrw(info, sizeof(ArgInfo)); + + info->next = NULL; + info->expr = expr; + info->offset = -1; + info->gpr = -1; + info->gprHi = -1; + info->fpr = -1; + info->vr = -1; + info->evaluated = 0; + info->flags = 0; + + return info; +} + +static ArgInfo *analyze_arguments(ENode *funcref, ENodeList *arg_expr, FuncArg *arg, UInt32 *used_regs, Boolean *resultHasFloats, char has_varargs) { + ArgInfo *infos; + ArgInfo *info; + SInt32 displ; + SInt32 arg_size; + int gpr_counter; + int fpr_counter; + int vr_counter; + Type *type; + RegClass rclass; + Boolean spilledVectorFlag; + + infos = NULL; + displ = 0; + gpr_counter = 3; + fpr_counter = 1; + vr_counter = 2; + + for (rclass = 0; rclass < RegClassMax; rclass++) + used_regs[rclass] = 0; + *resultHasFloats = 0; + + while (arg_expr) { + if (arg_expr->node == funcref) { + arg_expr = arg_expr->next; + arg = arg->next; + continue; + } + + type = arg_expr->node->rtype; + if (infos) { + info->next = make_arginfo(arg_expr->node); + info = info->next; + } else { + infos = info = make_arginfo(arg_expr->node); + } + + arg_size = 0; + if (IS_TYPE_VECTOR(type)) { + if (arg == &elipsis) { + spilledVectorFlag = 1; + info->flags |= AIF_PassOnStack; + } else { + spilledVectorFlag = 0; + if (vr_counter <= 13) { + info->flags |= AIF_PassInVR; + info->vr = vr_counter; + used_regs[RegClass_VR] |= 1 << vr_counter; + } else { + spilledVectorFlag = 1; + info->flags |= AIF_PassOnStack; + } + } + + if (has_varargs) { + if (gpr_counter < 10) { + gpr_counter = ((gpr_counter - 2) & ~3) + 5; + if (arg == &elipsis && gpr_counter < 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= (15 << gpr_counter) & 0x7E0; + } + gpr_counter += 4; + } + spilledVectorFlag = 1; + } + + if (spilledVectorFlag) + arg_size = 16; + vr_counter++; + } else if (IS_TYPE_FLOAT(type)) { + *resultHasFloats = 1; + if (!arg || arg == &oldstyle) { + if (fpr_counter <= 13) { + info->flags |= AIF_PassInFPR; + info->fpr = fpr_counter; + used_regs[RegClass_FPR] |= 1 << fpr_counter; + } else { + info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; + } + arg_size = 8; + fpr_counter++; + gpr_counter += 2; + } else if (arg == &elipsis) { + if (gpr_counter < 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 3 << gpr_counter; + } else if (gpr_counter == 10) { + info->flags |= AIF_PassInGPR | AIF_PassOnStack | AIF_ForceDoublePrecision; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 3 << gpr_counter; + } else { + info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; + } + arg_size = 8; + fpr_counter++; + gpr_counter += 2; + } else { + if (fpr_counter <= 13) { + info->flags |= AIF_PassInFPR; + info->fpr = fpr_counter; + used_regs[RegClass_FPR] |= 1 << fpr_counter; + } else { + info->flags |= AIF_PassOnStack; + } + + if (type->size == 4) { + arg_size = 4; + gpr_counter++; + } else { + arg_size = 8; + gpr_counter += 2; + } + + fpr_counter++; + } + } else if (TYPE_IS_8BYTES(type)) { + if (gpr_counter <= 10) { + info->flags |= AIF_PassInGPR; + if (copts.little_endian) { + info->gpr = gpr_counter; + info->gprHi = gpr_counter + 1; + } else { + info->gpr = gpr_counter + 1; + info->gprHi = gpr_counter; + } + used_regs[RegClass_GPR] |= 1 << gpr_counter; + if ((gpr_counter + 1) <= 10) + used_regs[RegClass_GPR] |= 1 << (gpr_counter + 1); + } else { + info->flags |= AIF_PassOnStack; + } + + arg_size = 8; + gpr_counter += 2; + } else if (TYPE_FITS_IN_REGISTER(type)) { + if ((!arg || arg == &elipsis || arg == &oldstyle) && type->size < 4) + info->flags |= AIF_ExtendTo32Bits; + + if (gpr_counter <= 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 1 << gpr_counter; + } else { + info->flags |= AIF_PassOnStack; + } + + arg_size = 4; + gpr_counter++; + } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || + IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); + if (gpr_counter <= 10) { + if ((gpr_counter + gprs_needed - 1) <= 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= ((1 << gprs_needed) - 1) << gpr_counter; + } else { + info->flags |= AIF_PassInGPR | AIF_PassOnStack; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= ((1 << (11 - gpr_counter)) - 1) << gpr_counter; + } + } else { + info->flags |= AIF_PassOnStack; + } + + gpr_counter += gprs_needed; + arg_size = type->size; + } else { + CError_FATAL(421); + } + + displ = set_out_param_displ(displ, type, info->flags & AIF_PassOnStack, &info->offset, arg_size); + + arg_expr = arg_expr->next; + if (arg && arg != &elipsis && arg != &oldstyle) + arg = arg->next; + } + + update_out_param_size(displ); + + return infos; +} + +static void pass_in_memory(ArgInfo *info) { + Type *type; + Operand opnd; + + type = info->expr->rtype; + memclrw(&opnd, sizeof(Operand)); + + if (TYPE_FITS_IN_REGISTER(type)) { + if (TYPE_IS_8BYTES(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + coerce_to_register_pair(&info->opnd, type, 0, 0); + + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, low_offset + out_param_displ_to_offset(info->offset)); + load_store_register( + PC_STW, info->opnd.regHi, 1, + NULL, high_offset + out_param_displ_to_offset(info->offset)); + } else { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + if (info->flags & AIF_ExtendTo32Bits) + extend32(&info->opnd, type, 0); + ENSURE_GPR(&info->opnd, type, 0); + + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } + } else if (IS_TYPE_FLOAT(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + ENSURE_FPR(&info->opnd, type, 0); + + if (type->size == 4 && !(info->flags & AIF_ForceDoublePrecision)) { + load_store_register( + PC_STFS, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } else { + load_store_register( + PC_STFD, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } + } else if (IS_TYPE_VECTOR(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + ENSURE_VR(&info->opnd, type, 0); + + load_store_register( + PC_STVX, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } else { + opnd.optype = OpndType_IndirectGPR_ImmOffset; + opnd.reg = 1; + opnd.object = NULL; + opnd.immOffset = out_param_displ_to_offset(info->offset); + + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + move_block(&opnd, &info->opnd, type->size, CMach_ArgumentAlignment(type)); + } +} + +static void pass_in_register(ArgInfo *info) { + Type *type; + + type = info->expr->rtype; + + if ((info->flags & AIF_PassMask) == AIF_PassInFPR) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->fpr, 0, &info->opnd); + ENSURE_FPR(&info->opnd, type, info->fpr); + if (info->opnd.reg != info->fpr) + emitpcode(PC_FMR, info->fpr, info->opnd.reg); + } else if ((info->flags & AIF_PassMask) == AIF_PassInVR) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->vr, 0, &info->opnd); + ENSURE_VR(&info->opnd, type, info->vr); + if (info->opnd.reg != info->vr) + emitpcode(PC_VMR, info->vr, info->opnd.reg); + } else if (TYPE_FITS_IN_REGISTER(type)) { + if (TYPE_IS_8BYTES(type)) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->gpr, info->gprHi, &info->opnd); + coerce_to_register_pair(&info->opnd, type, info->gpr, info->gprHi); + if (copts.little_endian) { + if (info->gprHi > 10) { + load_store_register( + PC_STW, info->opnd.regHi, 1, + NULL, high_offset + out_param_displ_to_offset(info->offset)); + } + } else { + if (info->gpr > 10) { + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, low_offset + out_param_displ_to_offset(info->offset)); + } + } + } else { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->gpr, 0, &info->opnd); + if (info->flags & AIF_ExtendTo32Bits) + extend32(&info->opnd, type, info->gpr); + ENSURE_GPR(&info->opnd, type, info->gpr); + if (info->opnd.reg != info->gpr) + emitpcode(PC_MR, info->gpr, info->opnd.reg); + } + } else if (IS_TYPE_FLOAT(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (type->size != 4 && info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + load_store_register( + PC_LWZ, info->gpr + 1, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 4); + } else { + ENSURE_FPR(&info->opnd, type, 0); + load_store_register( + PC_STFD, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr + 1, 1, + NULL, out_param_displ_to_offset(info->offset) + 4); + } + } else if (IS_TYPE_VECTOR(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + load_store_register( + PC_LWZ, info->gpr + 1, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 4); + if ((info->gpr + 2) < 10) { + load_store_register( + PC_LWZ, info->gpr + 2, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 8); + load_store_register( + PC_LWZ, info->gpr + 3, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 12); + } + } else { + ENSURE_VR(&info->opnd, type, 0); + load_store_register( + PC_STVX, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr + 1, 1, + NULL, out_param_displ_to_offset(info->offset) + 4); + if ((info->gpr + 2) < 10) { + load_store_register( + PC_LWZ, info->gpr + 2, 1, + NULL, out_param_displ_to_offset(info->offset) + 8); + load_store_register( + PC_LWZ, info->gpr + 3, 1, + NULL, out_param_displ_to_offset(info->offset) + 12); + } + } + } else { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (type->size <= 4) { + if (info->opnd.optype == OpndType_IndirectSymbol) + coerce_to_addressable(&info->opnd); + + if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + } else if (info->opnd.optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + PC_LWZX, info->gpr, info->opnd.reg, + info->opnd.regOffset); + } + } else { + SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); + SInt32 i; + + make_addressable(&info->opnd, gprs_needed * 4, 12); + for (i = 0; i < gprs_needed; i++) { + if (info->opnd.reg != (info->gpr + i)) { + load_store_register( + PC_LWZ, info->gpr + i, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + i * 4); + } + } + + if (info->opnd.reg >= info->gpr && info->opnd.reg < (info->gpr + gprs_needed)) { + load_store_register( + PC_LWZ, info->opnd.reg, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + (info->opnd.reg - info->gpr) * 4); + } + } + } +} + +static void pass_in_register_and_memory(ArgInfo *info) { + Type *type; + int gpr; + SInt32 offset; + + type = info->expr->rtype; + gpr = info->gpr; + offset = 0; + while (offset < type->size && gpr <= 10) { + load_store_register( + PC_LWZ, gpr, 1, + NULL, offset + out_param_displ_to_offset(info->offset)); + gpr++; + offset += 4; + } +} + +static Boolean needs_TOC_reload(Object *func) { + return 0; +} + +static void load_virtual_function(TypeClass *tclass, SInt32 offset, int reg, Operand *opnd) { + if (tclass->flags & CLASS_FLAGS_1) { + load_store_register(PC_LWZ, 12, reg, NULL, 0); + load_store_register(PC_LWZ, 12, 12, NULL, tclass->vtable->offset); + } else { + load_store_register(PC_LWZ, 12, reg, NULL, tclass->vtable->offset); + } + load_store_register(PC_LWZ, 12, 12, NULL, offset); + opnd->optype = OpndType_GPR; + opnd->reg = 12; +} + +static void branch_subroutine_indirect(Object *func, Operand *addrOpnd, UInt32 *used_regs) { + if (addrOpnd->reg != 12) + emitpcode(PC_MR, 12, addrOpnd->reg); + + used_regs[RegClass_GPR] |= 1 << 12; + branch_subroutine(func, 1, used_regs); +} + +static void evaluate_nested_function_calls(ArgInfo *info) { + ArgInfo *scan; + + scan = info->next; + while (scan && !scan->expr->hascall) + scan = scan->next; + + if (scan) + evaluate_nested_function_calls(scan); + + if (info->expr->hascall) { + GEN_NODE(info->expr, &info->opnd); + info->evaluated = 1; + } +} + +void call_function(ENode *expr, Operand *output) { + ArgInfo *infos; // r31 + ENode *funcref = expr->data.funccall.funcref; // r27 + Type *resultType = expr->data.funccall.functype->functype; // r26 + ENode *node = NULL; // r25 + char has_varargs; // r24 + ArgInfo *info; // r22 + Operand opnd; + UInt32 used_regs[RegClassMax] = {0}; + Boolean has_floats; + FuncArg *arg; + + memclrw(&opnd, sizeof(Operand)); + + has_varargs = 0; + for (arg = expr->data.funccall.functype->args; arg; arg = arg->next) { + if (arg == &elipsis) { + has_varargs = 1; + break; + } + } + + if (expr->data.funccall.functype->flags & FUNC_FLAGS_80) { + if (CMach_PassResultInHiddenArg(resultType)) + node = expr->data.funccall.args->next->node; + else + node = expr->data.funccall.args->node; + } + + infos = analyze_arguments( + node, + expr->data.funccall.args, + expr->data.funccall.functype->args, + used_regs, + &has_floats, + has_varargs); + + if (infos) + evaluate_nested_function_calls(infos); + + if (funcref->hascall) { + GEN_NODE_TO_GPR(funcref, &opnd, TYPE(&void_ptr), 0); + } else if (node && node->hascall) { + GEN_NODE_TO_GPR(node, &opnd, TYPE(&void_ptr), 0); + } + + for (info = infos; info; info = info->next) { + if (info->flags & AIF_PassOnStack) + pass_in_memory(info); + } + for (info = infos; info; info = info->next) { + if ((info->flags & AIF_PassMask) == (AIF_PassInGPR | AIF_PassOnStack)) + pass_in_register_and_memory(info); + } + for (info = infos; info; info = info->next) { + int flag = info->flags & AIF_PassMask; + if ( + flag == AIF_PassInGPR || + flag == AIF_PassInFPR || + flag == AIF_PassInVR + ) + pass_in_register(info); + } + + if (funcref->type == EOBJREF) { + TypeClass *tclass; + SInt32 vfOffset; + if (CParser_IsVirtualFunction(funcref->data.objref, &tclass, &vfOffset)) { + load_virtual_function( + tclass, + vfOffset, + CMach_PassResultInHiddenArg(resultType) ? Register4 : Register3, + &opnd + ); + branch_subroutine_indirect_ctr(&opnd, used_regs); + } else if (node) { + if (!node->hascall) { + GEN_NODE_TO_REG(node, 12, 0, &opnd); + ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); + } + branch_subroutine_indirect(funcref->data.objref, &opnd, used_regs); + } else { + branch_subroutine(funcref->data.objref, needs_TOC_reload(funcref->data.objref), used_regs); + } + } else { + if (!funcref->hascall) + GEN_NODE_TO_REG(funcref, 12, 0, &opnd); + ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); + branch_subroutine_indirect_ctr(&opnd, used_regs); + } + + if (IS_TYPE_FLOAT(resultType)) { + output->optype = OpndType_FPR; + output->reg = used_virtual_registers[RegClass_FPR]++; + emitpcode(PC_FMR, output->reg, 1); + } else if (IS_TYPE_VECTOR(resultType)) { + output->optype = OpndType_VR; + output->reg = used_virtual_registers[RegClass_VR]++; + emitpcode(PC_VMR, output->reg, 2); + } else if (TYPE_FITS_IN_REGISTER(resultType)) { + if (resultType->size > 4) { + output->optype = OpndType_GPRPair; + output->reg = used_virtual_registers[RegClass_GPR]++; + output->regHi = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, output->reg, low_reg); + emitpcode(PC_MR, output->regHi, high_reg); + } else { + output->optype = OpndType_GPR; + output->reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, output->reg, 3); + } + } else { + output->optype = OpndType_Absolute; + output->immediate = 0; + } +} + +static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs) { + if (addrOpnd->reg != 12) + emitpcode(PC_MR, 12, addrOpnd->reg); + + emitpcode(PC_MTCTR, 12); + used_regs[RegClass_GPR] |= 1 << 12; + branch_subroutine_ctr(used_regs); +} diff --git a/compiler_and_linker/unsorted/GenStabs.c b/compiler_and_linker/unsorted/GenStabs.c index e69de29..0563efe 100644 --- a/compiler_and_linker/unsorted/GenStabs.c +++ b/compiler_and_linker/unsorted/GenStabs.c @@ -0,0 +1,1191 @@ +#include "compiler/GenStabs.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/MachO.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +enum { + StabType_Int = 1, + StabType_Char = 2, + StabType_Long = 3, + StabType_UInt = 4, + StabType_ULong = 5, + StabType_LongLong = 6, + StabType_ULongLong = 7, + StabType_Short = 8, + StabType_UShort = 9, + StabType_SChar = 10, + StabType_UChar = 11, + StabType_Float = 12, + StabType_Double = 13, + StabType_LongDouble = 14, + StabType_ComplexInt = 15, + StabType_ComplexFloat = 16, + StabType_ComplexDouble = 17, + StabType_ComplexLongDouble = 18, + StabType_VectorUChar = 19, + StabType_VectorSChar = 20, + StabType_VectorBChar = 21, + StabType_VectorUShort = 22, + StabType_VectorSShort = 23, + StabType_VectorBShort = 24, + StabType_VectorUInt = 25, + StabType_VectorSInt = 26, + StabType_VectorBInt = 27, + StabType_VectorFloat = 28, + StabType_VectorPixel = 29, + StabType_Bool = 30, + StabType_Void = 31, + StabType_WChar = 32, + StabType_VtblPtr = 33, + StabType_CharPtr = 34, + StabType_UCharPtr = 35, + StabType_Func = 36, + StabType_FuncPtr = 37, + StabType_CString = 38, + StabType_PString = 39 +}; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct StabType { + struct StabType *next; + int id; + Type *type; +} StabType; + +typedef struct StabClass { + struct StabClass *next; + int id; + int id2; + Type *type; +} StabClass; + +typedef struct IncompleteList { + struct IncompleteList *next; + Type *type; + StabType *listnode; + Boolean xC; +} IncompleteList; + +typedef struct HashedPath { + struct HashedPath *next; + char *str; + SInt32 id; +} HashedPath; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +int unnamedstructs; +static StabType *pointerlist; +static StabType *structlist; +static StabType *arraylist; +static StabType *enumlist; +static StabClass *classlist; +static IncompleteList *incomplete_list; +static int nexttypeid; +static int type_done; +static int first_file; +static GList func_nl; +static GList stab_string; +static UInt32 current_offset; +static UInt32 current_line; +static HashedPath *hashedpaths[32]; + +// forward decls +static Boolean stabtypeequal(Type *a, Type *b); +static void StabNestedType(Type *type); +static void output_stab_string(SInt32 (*func)(char *, SInt16, UInt32), SInt16 desc, UInt32 value); +static void StabAppendType(Type *type); +static SInt32 Output_FUN_Stab(char *str, SInt16 desc, UInt32 value); + +static short StabBasicType(short bt) { + switch (bt) { + case IT_BOOL: return StabType_Bool; + case IT_CHAR: return StabType_Char; + case IT_SCHAR: return StabType_SChar; + case IT_UCHAR: return StabType_UChar; + case IT_WCHAR_T: return StabType_WChar; + case IT_SHORT: return StabType_Short; + case IT_USHORT: return StabType_UShort; + case IT_INT: return StabType_Int; + case IT_UINT: return StabType_UInt; + case IT_LONG: return StabType_Long; + case IT_ULONG: return StabType_ULong; + case IT_LONGLONG: return StabType_LongLong; + case IT_ULONGLONG: return StabType_ULongLong; + case IT_FLOAT: return StabType_Float; + case IT_SHORTDOUBLE: return StabType_Double; + case IT_DOUBLE: return StabType_Double; + case IT_LONGDOUBLE: return StabType_Double; + default: + CError_FATAL(187); + return StabType_Int; + } +} + +static void StabAppendNameSpaceName(GList *glist, NameSpace *nspace, int num) { + char buf[16]; + + if (!nspace || num >= 9) { + AppendGListByte(glist, 'Q'); + AppendGListByte(glist, '0' + num); + } else { + while (nspace && !nspace->name) + nspace = nspace->parent; + + if (nspace) { + StabAppendNameSpaceName(glist, nspace->parent, num + 1); + sprintf(buf, "%d", strlen(nspace->name->name)); + AppendGListName(glist, buf); + AppendGListName(glist, nspace->name->name); + } else if (num > 1) { + StabAppendNameSpaceName(glist, NULL, num + 1); + } + } +} + +static void StabAppendName(GList *glist, NameSpace *nspace, HashNameNode *name) { + if (IsTempName(name)) { + unnamedstructs++; + } else { + while (nspace && !nspace->name) + nspace = nspace->parent; + if (nspace) + StabAppendNameSpaceName(glist, nspace, 1); + AppendGListName(glist, name->name); + } +} + +static SInt32 Output_LSYM_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_LSYM; + sym.section = NULL; + sym.desc = desc; + sym.value = value; + return ObjGen_OutputStab(&sym, -1); +} + +static int StabAppendNextTypeDefinition(void) { + char buf[48]; + sprintf(buf, "(0,%d)=", ++nexttypeid); + AppendGListName(&stab_string, buf); + return nexttypeid; +} + +static int namestarts(char *a, char *b) { + while (1) { + if (!*b) + return 1; + if (*b != tolower(*a)) + break; + a++; + b++; + } + + return 0; +} + +static int namecontains(char *a, char *b) { + char *aa; + char *bb; + + while (*a) { + aa = a; + bb = b; + while (1) { + if (!*bb) + return 1; + if (*bb != tolower(*aa)) + break; + aa++; + bb++; + } + a++; + } + + return 0; +} + +static void nested_local_array(Type *type) { + StabType *list; + + for (list = arraylist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return; + } + + StabNestedType(TPTR_TARGET(type)); +} + +static int local_array(Type *type) { + StabType *list; + char buf[32]; + + for (list = arraylist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return list->id; + } + + list = galloc(sizeof(StabType)); + list->next = pointerlist; + pointerlist = list; + list->type = type; + list->id = StabAppendNextTypeDefinition(); + + AppendGListName(&stab_string, "ar(0,1);0"); + sprintf(buf, ";%d;", (type->size / TPTR_TARGET(type)->size) - 1); + AppendGListName(&stab_string, buf); + StabAppendType(TPTR_TARGET(type)); + + return list->id; +} + +static Boolean stabtypeequal(Type *a, Type *b) { + while (1) { + if (a->type != b->type) + return 0; + + switch (a->type) { + case TYPEVOID: + case TYPEFUNC: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + return a == b; + case TYPEPOINTER: + a = TPTR_TARGET(a); + b = TPTR_TARGET(b); + break; + case TYPEARRAY: + if (a->size != b->size) + return 0; + a = TPTR_TARGET(a); + b = TPTR_TARGET(b); + break; + case TYPEMEMBERPOINTER: + return 0; + default: + CError_FATAL(393); + } + } +} + +static void nested_local_pointer(Type *type) { + StabType *list; + + for (list = pointerlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return; + } + + while (IS_TYPE_POINTER_ONLY(type)) + type = TPTR_TARGET(type); + StabNestedType(type); +} + +static int local_pointer(Type *type) { + StabType *list; + + for (list = pointerlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return list->id; + } + + list = galloc(sizeof(StabType)); + list->next = pointerlist; + pointerlist = list; + list->type = type; + list->id = StabAppendNextTypeDefinition(); + + AppendGListName(&stab_string, "*"); + for (type = TPTR_TARGET(type); IS_TYPE_POINTER_ONLY(type); type = TPTR_TARGET(type)) { + StabAppendNextTypeDefinition(); + AppendGListName(&stab_string, "*"); + } + StabAppendType(type); + + return list->id; +} + +static int local_enum_add(Type *type) { + ObjEnumConst *entry; + int id; + char buf[48]; + + id = StabAppendNextTypeDefinition(); + + AppendGListName(&stab_string, "e"); + for (entry = TYPE_ENUM(type)->enumlist; entry; entry = entry->next) { + AppendGListName(&stab_string, entry->name->name); + sprintf(buf, ":%d,", CInt64_GetULong(&entry->val)); + AppendGListName(&stab_string, buf); + } + AppendGListName(&stab_string, ";"); + + return id; +} + +static void nested_local_enum(Type *type) { + StabType *list; + + for (list = enumlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return; + } + + if (TYPE_ENUM(type)->enumname) { + stab_string.size = 0; + StabAppendName(&stab_string, TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname); + AppendGListName(&stab_string, ":T"); + + list = galloc(sizeof(StabType)); + list->next = enumlist; + enumlist = list; + list->type = type; + list->id = local_enum_add(type); + + output_stab_string(Output_LSYM_Stab, 0, 0); + } +} + +static int local_enum(Type *type) { + StabType *list; + + for (list = enumlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return list->id; + } + + list = galloc(sizeof(StabType)); + list->next = enumlist; + enumlist = list; + list->type = type; + list->id = local_enum_add(type); + + return list->id; +} + +static void local_struct_add(StabType *list) { + StructMember *member; + Type *type; + IncompleteList *incomplete; + char buf[80]; + + type = list->type; + if (type->size == 0) { + incomplete = galloc(sizeof(IncompleteList)); + incomplete->next = incomplete_list; + incomplete_list = incomplete; + incomplete->type = type; + incomplete->listnode = list; + incomplete->xC = 0; + } + + if (list->id >= 0) { + sprintf(buf, "(0,%d)=", list->id); + AppendGListName(&stab_string, buf); + } else { + list->id = StabAppendNextTypeDefinition(); + } + + sprintf(buf, "s%d", type->size); + AppendGListName(&stab_string, buf); + + for (member = TYPE_STRUCT(type)->members; member; member = member->next) { + AppendGListName(&stab_string, member->name->name); + AppendGListName(&stab_string, ":"); + type = member->type; + + if (IS_TYPE_BITFIELD(type)) { + StabAppendType(TYPE_BITFIELD(type)->bitfieldtype); + sprintf(buf, + ",%d,%d;", + TYPE_BITFIELD(type)->unkA + member->offset * 8, + TYPE_BITFIELD(type)->unkB); + AppendGListName(&stab_string, buf); + } else { + StabAppendType(type); + sprintf(buf, + ",%d,%d;", + member->offset * 8, + member->type->size * 8); + AppendGListName(&stab_string, buf); + } + } + + AppendGListName(&stab_string, ";"); +} + +static void nested_local_struct(Type *type) { + StabType *list; + StructMember *member; + + for (list = structlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return; + } + + list = galloc(sizeof(StabType)); + list->next = structlist; + structlist = list; + list->type = type; + list->id = ++nexttypeid; + + for (member = TYPE_STRUCT(type)->members; member; member = member->next) { + if (IS_TYPE_BITFIELD(member->type)) + StabNestedType(TYPE_BITFIELD(member->type)->bitfieldtype); + else + StabNestedType(member->type); + } + + stab_string.size = 0; + StabAppendName(&stab_string, NULL, TYPE_STRUCT(type)->name); + AppendGListName(&stab_string, ":T"); + local_struct_add(list); + + output_stab_string(Output_LSYM_Stab, 0, 0); +} + +static int local_struct(Type *type) { + StabType *list; + + for (list = structlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return list->id; + } + + list = galloc(sizeof(StabType)); + list->next = structlist; + structlist = list; + list->type = type; + local_struct_add(list); + + return list->id; +} + +static void local_class_add(StabClass *list) { + Type *type; + IncompleteList *incomplete; + int baseCount; + ClassList *base; + ObjMemberVar *ivar; + Type *ivarType; + char buf[80]; + + type = list->type; + if (type->size == 0) { + incomplete = galloc(sizeof(IncompleteList)); + incomplete->next = incomplete_list; + incomplete_list = incomplete; + incomplete->type = type; + incomplete->listnode = (StabType *) list; + incomplete->xC = 0; + } + + if (list->id >= 0) { + sprintf(buf, "(0,%d)=", list->id); + AppendGListName(&stab_string, buf); + } else { + list->id = StabAppendNextTypeDefinition(); + } + + list->id2 = list->id; + + if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) { + AppendGListName(&stab_string, "*"); + StabAppendNextTypeDefinition(); + } + + sprintf(buf, "s%d", type->size); + AppendGListName(&stab_string, buf); + + if (!TYPE_CLASS(type)->sominfo) { + baseCount = 0; + base = TYPE_CLASS(type)->bases; + while (base) { + base = base->next; + baseCount++; + } + + if (baseCount > 0) { + sprintf(buf, "!%d,", baseCount); + AppendGListName(&stab_string, buf); + + for (base = TYPE_CLASS(type)->bases; base; base = base->next) { + int virtualChar; + char accessChar; + virtualChar = base->is_virtual ? '1' : '0'; + switch (base->access) { + case ACCESSPUBLIC: + accessChar = '2'; + break; + case ACCESSPRIVATE: + accessChar = '0'; + break; + case ACCESSPROTECTED: + accessChar = '1'; + break; + default: + accessChar = '0'; + break; + } + + sprintf(buf, "%c%c%d,", (char) virtualChar, accessChar, base->is_virtual ? 0 : (base->offset * 8)); + AppendGListName(&stab_string, buf); + StabAppendType(TYPE(base->base)); + AppendGListName(&stab_string, ";"); + } + + for (base = TYPE_CLASS(type)->bases; base; base = base->next) { + if (base->is_virtual) { + AppendGListName(&stab_string, "$vb"); + StabAppendType(TYPE(base->base)); + AppendGListName(&stab_string, ":"); + StabAppendType(CDecl_NewPointerType(TYPE(base->base))); + sprintf(buf, ",%d;", base->offset * 8); + AppendGListName(&stab_string, buf); + } + } + } + } + + for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { + StabAppendName(&stab_string, NULL, ivar->name); + AppendGListName(&stab_string, ":"); + + ivarType = ivar->type; + if (IS_TYPE_BITFIELD(ivarType)) { + StabAppendType(TYPE_BITFIELD(ivarType)->bitfieldtype); + sprintf(buf, ",%d,%d;", + TYPE_BITFIELD(ivarType)->unkA + ivar->offset * 8, + TYPE_BITFIELD(ivarType)->unkB); + AppendGListName(&stab_string, buf); + } else { + StabAppendType(ivarType); + sprintf(buf, ",%d,%d;", + ivar->offset * 8, + ivar->type->size * 8); + AppendGListName(&stab_string, buf); + } + } + + AppendGListName(&stab_string, ";"); +} + +static void nested_local_class(Type *type) { + StabClass *clslist; + ClassList *base; + ObjMemberVar *ivar; + + if (TYPE_CLASS(type)->sominfo) + return; + + for (clslist = classlist; clslist; clslist = clslist->next) { + if (stabtypeequal(type, clslist->type)) + return; + } + + clslist = galloc(sizeof(StabClass)); + clslist->next = classlist; + classlist = clslist; + clslist->id = ++nexttypeid; + clslist->type = type; + + if (!TYPE_CLASS(type)->sominfo) { + for (base = TYPE_CLASS(type)->bases; base; base = base->next) { + if (base->base->classname) { + if (base->is_virtual) + StabNestedType(CDecl_NewPointerType(TYPE(base->base))); + else + StabNestedType(TYPE(base->base)); + } + } + } + + for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { + if (IS_TYPE_BITFIELD(ivar->type)) + StabNestedType(TYPE_BITFIELD(ivar->type)->bitfieldtype); + else + StabNestedType(ivar->type); + } + + stab_string.size = 0; + StabAppendName(&stab_string, TYPE_CLASS(type)->nspace->parent, TYPE_CLASS(type)->classname); + AppendGListName(&stab_string, ":Tt"); + + local_class_add(clslist); + output_stab_string(Output_LSYM_Stab, 0, 0); +} + +static int local_class(Type *type) { + StabClass *list; + + if (TYPE_CLASS(type)->sominfo) + return 31; + + for (list = classlist; list; list = list->next) { + if (stabtypeequal(type, list->type)) + return list->id; + } + + list = galloc(sizeof(StabClass)); + list->next = classlist; + classlist = list; + list->type = type; + local_class_add(list); + return list->id; +} + +static void StabNestedType(Type *type) { + switch (type->type) { + case TYPEVOID: + break; + case TYPEINT: + break; + case TYPEFLOAT: + break; + case TYPEENUM: + nested_local_enum(type); + break; + case TYPESTRUCT: + nested_local_struct(type); + break; + case TYPECLASS: + nested_local_class(type); + break; + case TYPEFUNC: + break; + case TYPEBITFIELD: + break; + case TYPEMEMBERPOINTER: + break; + case TYPEPOINTER: + if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type))) { + if (!IS_TYPE_FUNC(TPTR_TARGET(TPTR_TARGET(type)))) + nested_local_pointer(type); + } else if ( + !IS_TYPE_INT(TPTR_TARGET(type)) || + (TYPE_INTEGRAL(TPTR_TARGET(type))->integral != IT_CHAR && + TYPE_INTEGRAL(TPTR_TARGET(type))->integral != IT_UCHAR)) + nested_local_pointer(type); + break; + case TYPEARRAY: + nested_local_array(type); + break; + default: + CError_FATAL(921); + } +} + +static int StabTypeID(Type *type) { + int id; + + switch (type->type) { + case TYPEVOID: + id = StabType_Void; + break; + case TYPEINT: + case TYPEFLOAT: + id = StabBasicType(TYPE_INTEGRAL(type)->integral); + break; + case TYPEENUM: + id = local_enum(type); + break; + case TYPESTRUCT: + if (IS_TYPESTRUCT_VECTOR(type)) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_4: return StabType_VectorUChar; + case STRUCT_TYPE_5: return StabType_VectorSChar; + case STRUCT_TYPE_6: return StabType_VectorBChar; + case STRUCT_TYPE_7: return StabType_VectorUShort; + case STRUCT_TYPE_8: return StabType_VectorSShort; + case STRUCT_TYPE_9: return StabType_VectorBShort; + case STRUCT_TYPE_A: return StabType_VectorUInt; + case STRUCT_TYPE_B: return StabType_VectorSInt; + case STRUCT_TYPE_C: return StabType_VectorBInt; + case STRUCT_TYPE_D: return StabType_VectorFloat; + case STRUCT_TYPE_E: return StabType_VectorPixel; + } + } else { + id = local_struct(type); + } + break; + case TYPECLASS: + id = local_class(type); + break; + case TYPEFUNC: + id = StabType_Func; + break; + case TYPEBITFIELD: + id = StabType_Void; + break; + case TYPEPOINTER: + if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type))) { + if (IS_TYPE_FUNC(TPTR_TARGET(TPTR_TARGET(type)))) + id = StabType_FuncPtr; + else + id = local_pointer(type); + break; + } + if (IS_TYPE_INT(TPTR_TARGET(type))) { + if (TYPE_INTEGRAL(TPTR_TARGET(type))->integral == IT_CHAR) { + id = copts.unsignedchars ? StabType_UCharPtr : StabType_CharPtr; + break; + } + if (TYPE_INTEGRAL(TPTR_TARGET(type))->integral == IT_UCHAR) { + id = StabType_UCharPtr; + break; + } + } + id = local_pointer(type); + break; + case TYPEARRAY: + id = local_array(type); + break; + case TYPEMEMBERPOINTER: + id = StabType_Void; + break; + default: + CError_FATAL(1041); + id = StabType_Void; + } + + return id; +} + +static void output_stab_string(SInt32 (*func)(char *, SInt16, UInt32), SInt16 desc, UInt32 value) { + int len; + char *src; + char *end; + char *dst; + char *boundarySrc; + char *boundaryDst; + char *possibleBoundarySrc; + char *possibleBoundaryDst; + char buffer[1024]; + + if (stab_string.size > 0) { + LockGList(&stab_string); + + src = *stab_string.data; + end = *stab_string.data + stab_string.size; + dst = buffer; + len = 0; + + boundarySrc = NULL; + boundaryDst = NULL; + possibleBoundarySrc = NULL; + possibleBoundaryDst = NULL; + + while (src < end) { + if (*src == ':') { + boundarySrc = possibleBoundarySrc; + boundaryDst = possibleBoundaryDst; + } + + if (*src == '(') { + *(dst++) = *(src++); + len++; + while (isdigit(*src)) { + *(dst++) = *(src++); + len++; + } + + if (*src == ',') { + *(dst++) = *(src++); + len++; + while (isdigit(*src)) { + *(dst++) = *(src++); + len++; + } + + if (*src == ',') { + *(dst++) = *(src++); + len++; + } + } + } + + if (*src == ',' || *src == ';') { + possibleBoundarySrc = src; + possibleBoundaryDst = dst; + } + + *(dst++) = *(src++); + len++; + + if ((end - src) <= 10 || len <= 40 || !boundarySrc) { + if ((unsigned int) len <= 1021) + continue; + } + + if (boundarySrc) { + src = boundarySrc + 1; + dst = boundaryDst + 1; + } + + dst[0] = '\\'; + dst[1] = 0; + func(buffer, desc, value); + + dst = buffer; + boundarySrc = NULL; + boundaryDst = NULL; + possibleBoundarySrc = NULL; + possibleBoundaryDst = NULL; + len = 0; + } + + if (len) { + *dst = 0; + func(buffer, desc, value); + } + + UnlockGList(&stab_string); + } +} + +static void output_default_types(void) { + Output_LSYM_Stab("int:t(0,1)=r(0,1);0020000000000;0017777777777;", 0, 0); + + if (copts.unsignedchars) + Output_LSYM_Stab("char:t(0,2)=r(0,2);0;255;", 0, 0); + else + Output_LSYM_Stab("char:t(0,2)=r(0,2);-128;127;", 0, 0); + + Output_LSYM_Stab("long int:t(0,3)=r(0,1);0020000000000;0017777777777;", 0, 0); + Output_LSYM_Stab("unsigned int:t(0,4)=r(0,1);0000000000000;0037777777777;", 0, 0); + Output_LSYM_Stab("long unsigned int:t(0,5)=r(0,1);0000000000000;0037777777777;", 0, 0); + Output_LSYM_Stab("long long int:t(0,6)=r(0,1);01000000000000000000000;0777777777777777777777;", 0, 0); + Output_LSYM_Stab("long long unsigned int:t(0,7)=r(0,1);0000000000000;01777777777777777777777;", 0, 0); + Output_LSYM_Stab("short int:t(0,8)=r(0,8);-32768;32767;", 0, 0); + Output_LSYM_Stab("short unsigned int:t(0,9)=r(0,9);0;65535;", 0, 0); + Output_LSYM_Stab("signed char:t(0,10)=r(0,10);-128;127;", 0, 0); + Output_LSYM_Stab("unsigned char:t(0,11)=r(0,11);0;255;", 0, 0); + Output_LSYM_Stab("float:t(0,12)=r(0,1);4;0;", 0, 0); + Output_LSYM_Stab("double:t(0,13)=r(0,1);8;0;", 0, 0); + Output_LSYM_Stab("long double:t(0,14)=r(0,1);8;0;", 0, 0); + Output_LSYM_Stab("complex int:t(0,15)=s8real:(0,1),0,32;imag:(0,1),32,32;;", 0, 0); + Output_LSYM_Stab("complex float:t(0,16)=r(0,16);4;0;", 0, 0); + Output_LSYM_Stab("complex double:t(0,17)=r(0,17);8;0;", 0, 0); + Output_LSYM_Stab("complex long double:t(0,18)=r(0,18);8;0;", 0, 0); + Output_LSYM_Stab("__vector unsigned char:t(0,19)=ar(0,1);0;15;(0,11)", 0, 0); + Output_LSYM_Stab("__vector signed char:t(0,20)=ar(0,1);0;15;(0,10)", 0, 0); + Output_LSYM_Stab("__vector bool char:t(0,21)=ar(0,1);0;15;(0,11)", 0, 0); + Output_LSYM_Stab("__vector unsigned short:t(0,22)=ar(0,1);0;7;(0,9)", 0, 0); + Output_LSYM_Stab("__vector signed short:t(0,23)=ar(0,1);0;7;(0,8)", 0, 0); + Output_LSYM_Stab("__vector bool short:t(0,24)=ar(0,1);0;7;(0,9)", 0, 0); + Output_LSYM_Stab("__vector unsigned int:t(0,25)=ar(0,1);0;3;(0,5)", 0, 0); + Output_LSYM_Stab("__vector signed int:t(0,26)=ar(0,1);0;3;(0,3)", 0, 0); + Output_LSYM_Stab("__vector bool int:t(0,27)=ar(0,1);0;3;(0,5)", 0, 0); + Output_LSYM_Stab("__vector float:t(0,28)=ar(0,1);0;3;(0,12)", 0, 0); + Output_LSYM_Stab("__vector pixel:t(0,29)=ar(0,1);0;7;(0,9)", 0, 0); + + if (copts.booltruefalse) { + Output_LSYM_Stab("bool:t(0,30)=r(0,30);0;1;", 0, 0); + Output_LSYM_Stab("true:c=b1;", 0, 0); + Output_LSYM_Stab("false:c=b0;", 0, 0); + } else { + Output_LSYM_Stab(":t(0,30)=r(0,30);0;1;", 0, 0); + } + + Output_LSYM_Stab("void:t(0,31)=(0,31);", 0, 0); + + if (copts.wchar_type) + Output_LSYM_Stab("wchar_t:t(0,32)=r(0,1);0020000000000;0017777777777;", 0, 0); + else + Output_LSYM_Stab("__wchar_t:t(0,32)=r(0,1);0020000000000;0017777777777;", 0, 0); + + if (copts.cplusplus) + Output_LSYM_Stab("__vtbl_ptr_type:t(0,33)=*(0,34)=f(0,1)", 0, 0); + + Output_LSYM_Stab("__charptr__:t(0,34)=*(0,10);", 0, 0); + Output_LSYM_Stab("__ucharptr__:t(0,35)=*(0,11);", 0, 0); + Output_LSYM_Stab("__funcptr__:t(0,37)=*(0,36)=f(0,31);", 0, 0); + Output_LSYM_Stab("__cstring__:t(0,38)=*(0,10);", 0, 0); + Output_LSYM_Stab("__pstring__:t(0,39)=*(0,11);", 0, 0); + + nexttypeid = StabType_PString; + type_done = 1; +} + +int GenStab_Type(char *name, Type *type) { + int id; + + if (!type_done) + output_default_types(); + + StabNestedType(type); + stab_string.size = 0; + + if (name && strlen(name)) { + AppendGListName(&stab_string, name); + AppendGListName(&stab_string, ":t"); + } + + id = StabTypeID(type); + output_stab_string(Output_LSYM_Stab, 0, 0); + return id; +} + +static void StabAppendType(Type *type) { + SInt32 size; + int id; + char buf[20]; + + size = stab_string.size; + id = StabTypeID(type); + if (size == stab_string.size) { + sprintf(buf, "(0,%d)", id); + AppendGListName(&stab_string, buf); + } +} + +void GenStab_Function(Object *func, UInt32 offset) { + HashNameNode *name; + + if (!type_done) + output_default_types(); + + StabNestedType(TYPE_FUNC(func->type)->functype); + + stab_string.size = 0; + name = CMangler_GetLinkName(func); + AppendGListName(&stab_string, (name->name[0] == '_') ? &name->name[1] : name->name); + + if (CParser_HasInternalLinkage(func)) + AppendGListName(&stab_string, ":f"); + else + AppendGListName(&stab_string, ":F"); + + StabAppendType(TYPE_FUNC(func->type)->functype); + + output_stab_string(Output_FUN_Stab, functionbodyoffset, offset); + + current_offset = offset; + current_line = -1; +} + +void GenStab_FunctionEnd(Object *func, SInt32 relocID, UInt32 offset) { + stab_string.size = 0; + Output_FUN_Stab("", current_line, relocID + offset); +} + +void GenStab_Line(UInt32 line, UInt32 offset) { + SymbolData sym; + if (offset != current_offset && line != current_line) { + sym.u.name = NULL; + sym.type = N_SLINE; + sym.section = NULL; + sym.desc = line; + sym.value = offset; + ObjGen_OutputStab(&sym, -1); + current_offset = offset; + current_line = line; + } +} + +static SInt32 Output_RSYM_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_RSYM; + sym.section = NULL; + sym.desc = desc; + sym.value = value; + return ObjGen_OutputStab(&sym, -1); +} + +static SInt32 Output_PSYM_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_PSYM; + sym.section = NULL; + sym.desc = desc; + sym.value = value; + return ObjGen_OutputStab(&sym, -1); +} + +static SInt32 Output_FUN_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_FUN; + sym.section = NULL; + sym.desc = desc; + sym.value = value; + return ObjGen_OutputStab(&sym, -1); +} + +static SInt32 Output_GSYM_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_GSYM; + sym.section = NULL; + sym.desc = 0; + sym.value = 0; + return ObjGen_OutputStab(&sym, -1); +} + +static SInt32 Output_STSYM_Stab(char *str, SInt16 desc, UInt32 value) { + SymbolData sym; + sym.u.name = str; + sym.type = N_STSYM; + sym.section = NULL; + sym.desc = desc; + sym.value = value; + return ObjGen_OutputStab(&sym, -1); +} + +static const int reg_offset[] = { + -200, + 68, + 76, + 32, + 0 +}; + +void GenStab_Parameter(Object *object) { + VarInfo *vi; + + if (!type_done) + output_default_types(); + + StabNestedType(object->type); + + stab_string.size = 0; + vi = Registers_GetVarInfo(object); + AppendGListName(&stab_string, object->name->name); + + if (vi->flags & VarInfoFlag2) { + AppendGListName(&stab_string, ":P"); + StabAppendType(object->type); + output_stab_string(Output_RSYM_Stab, 0, vi->reg + reg_offset[vi->rclass]); + } else { + AppendGListName(&stab_string, ":p"); + StabAppendType(object->type); + output_stab_string(Output_PSYM_Stab, 0, local_offset_32(object)); + } +} + +void GenStab_Var(Object *object) { + VarInfo *vi; + + if (!type_done) + output_default_types(); + + StabNestedType(object->type); + + stab_string.size = 0; + vi = Registers_GetVarInfo(object); + AppendGListName(&stab_string, object->name->name); + + vi = Registers_GetVarInfo(object); + if (object->datatype == DLOCAL) { + if (vi->flags & VarInfoFlag2) { + AppendGListName(&stab_string, ":r"); + StabAppendType(object->type); + output_stab_string(Output_RSYM_Stab, 0, vi->reg + reg_offset[vi->rclass]); + } else { + AppendGListName(&stab_string, ":"); + StabAppendType(object->type); + output_stab_string(Output_LSYM_Stab, 0, local_offset_32(object)); + } + } else if (CParser_HasInternalLinkage(object) || (object->qual & (Q_20000 | Q_OVERLOAD))) { + AppendGListName(&stab_string, ":S"); + StabAppendType(object->type); + output_stab_string(Output_STSYM_Stab, 0, CMangler_GetLinkName(object)->id); + } else { + AppendGListName(&stab_string, ":G"); + StabAppendType(object->type); + output_stab_string(Output_GSYM_Stab, 0, 0); + } +} + +static HashedPath *Stabs_LookupPath(char *str) { + char *buf; + HashedPath *hp; + HashedPath **ptr; + + for (hp = hashedpaths[CHash(str) & 31]; hp; hp = hp->next) { + if (!strcmp(hp->str, str)) + return hp; + } + + ptr = hashedpaths + (CHash(str) & 31); + hp = galloc(sizeof(HashedPath)); + + buf = galloc(strlen(str) + 1); + strcpy(buf, str); + hp->str = buf; + + hp->id = -1; + hp->next = *ptr; + *ptr = hp; + + return hp; +} + +void GenStab_IncludeFile(char *path) { + HashedPath *hp; + SymbolData sym; + + hp = Stabs_LookupPath(path); + sym.u.name = hp->str; + sym.type = N_SOL; + sym.section = NULL; + sym.desc = 0; + sym.value = 0; + hp->id = ObjGen_OutputStab(&sym, hp->id); +} + +void GenStab_SourceFile(char *path) { + HashedPath *hp; + SymbolData sym; + + hp = Stabs_LookupPath(path); + sym.u.name = hp->str; + sym.type = N_SO; + sym.section = NULL; + sym.desc = 0; + sym.value = 0; + hp->id = ObjGen_OutputStab(&sym, hp->id); +} + +void GenStab_Setup(void) { + SInt32 i; + + for (i = 0; i < 32; i++) + hashedpaths[i] = NULL; + + type_done = 0; + first_file = 0; + nexttypeid = 0; + pointerlist = NULL; + structlist = NULL; + arraylist = NULL; + enumlist = NULL; + classlist = NULL; + incomplete_list = NULL; + current_offset = 0; + current_line = -1; + func_nl.data = NULL; + stab_string.data = NULL; + if (InitGList(&stab_string, 256)) + CError_NoMem(); +} diff --git a/compiler_and_linker/unsorted/GlobalOptimizer.c b/compiler_and_linker/unsorted/GlobalOptimizer.c index e69de29..f600322 100644 --- a/compiler_and_linker/unsorted/GlobalOptimizer.c +++ b/compiler_and_linker/unsorted/GlobalOptimizer.c @@ -0,0 +1,224 @@ +#include "compiler/GlobalOptimizer.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/AddPropagation.h" +#include "compiler/CodeGen.h" +#include "compiler/CodeMotion.h" +#include "compiler/ConstantPropagation.h" +#include "compiler/CopyPropagation.h" +#include "compiler/LoadDeletion.h" +#include "compiler/LoopDetection.h" +#include "compiler/LoopOptimization.h" +#include "compiler/PCodeListing.h" +#include "compiler/Peephole.h" +#include "compiler/StrengthReduction.h" +#include "compiler/ValueNumbering.h" +#include "compiler/VectorArraysToRegs.h" + +static void optimizelevel2(Object *func) { + removecommonsubexpressions(func, 1); + if (removedcommonsubexpressions && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CSE"); + + propagatecopyinstructions(func, 1); + propagateaddinstructions(func); +} + +static void optimizelevel3(Object *func) { + if (copts.peephole) { + if (copts.schedule_mode == 0 && copts.optimizationlevel > 1) + peepholemergeblocks(func, 0); + + peepholeoptimizeforward(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD"); + } + + removecommonsubexpressions(func, 0); + if (removedcommonsubexpressions && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING"); + + propagatecopyinstructions(func, 0); + propagatedcopies = 0; + propagateaddinstructions(func); + + findloopsinflowgraph(); + if (loopsinflowgraph) { + computeusedefchains(1); + analyzeloopsinflowgraph(); + moveloopinvariantcode(); + if (movedloopinvariantcode && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CODE MOTION"); + + computeusedefchains(0); + analyzeForCountableLoops(loopsinflowgraph); + strengthreduceloops(); + if (strengthreducedloops) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER STRENGTH REDUCTION"); + propagatecopyinstructions(func, 1); + } + + optimizeloops(); + if (optimizedloops) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER LOOP TRANSFORMATIONS"); + propagatecopyinstructions(func, 1); + propagateaddinstructions(func); + } + } + + if (!propagatedcopies) { + propagatecopyinstructions(func, 1); + if (propagatedcopies && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER COPY PROPAGATION"); + } + + propagateconstants(); + if (propagatedconstants) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CONSTANT PROPAGATION"); + + deletedeadloads(func); + propagateaddinstructions(func); + } + + if (copts.peephole) { + if (copts.schedule_mode == 0 && copts.optimizationlevel > 1) + peepholemergeblocks(func, 0); + + peepholeoptimizeforward(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD 2"); + } + + removecommonsubexpressions(func, 1); + if (removedcommonsubexpressions) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING 2"); + propagatecopyinstructions(func, 1); + } +} + +static void optimizelevel4(Object *func) { + if (copts.peephole) { + if (copts.schedule_mode == 0 && copts.optimizationlevel > 1) + peepholemergeblocks(func, 0); + + peepholeoptimizeforward(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD"); + } + + removecommonsubexpressions(func, 0); + if (removedcommonsubexpressions && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING"); + + propagatecopyinstructions(func, 0); + propagatedcopies = 0; + propagateaddinstructions(func); + + findloopsinflowgraph(); + if (loopsinflowgraph) { + computeusedefchains(1); + analyzeloopsinflowgraph(); + moveloopinvariantcode(); + if (movedloopinvariantcode && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CODE MOTION"); + + computeusedefchains(0); + analyzeForCountableLoops(loopsinflowgraph); + strengthreduceloops(); + if (strengthreducedloops) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER STRENGTH REDUCTION"); + propagatecopyinstructions(func, 1); + propagatedcopies = 0; + } + + optimizeloops(); + if (optimizedloops) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER LOOP TRANSFORMATIONS"); + propagatecopyinstructions(func, 1); + propagateaddinstructions(func); + } + } + + if (!propagatedcopies) + propagatecopyinstructions(func, 1); + + propagateconstants(); + if (propagatedconstants) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CONSTANT PROPAGATION"); + + deletedeadloads(func); + if (propagatedconstants) + propagatecopyinstructions(func, 1); + propagateaddinstructions(func); + + if (optimizedloop_full_unroll) { + changearraytoregisters(); + if (optimizedloop_trans_regs && copts.debuglisting) { + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER ARRAY => REGISTER TRANSFORM"); + propagateconstants(); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CONSTANT PROPAGATION 2"); + if (propagatedconstants) + propagatecopyinstructions(func, 1); + } + } + } + + if (copts.peephole) { + if (copts.schedule_mode == 0 && copts.optimizationlevel > 1) + peepholemergeblocks(func, 0); + + peepholeoptimizeforward(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD 2"); + } + + removecommonsubexpressions(func, 1); + if (removedcommonsubexpressions) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING 2"); + propagatecopyinstructions(func, 1); + } + + if (has_altivec_arrays && vectorarraystoregs()) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VECTOR ARRAY CONVERSION"); + propagatecopyinstructions(func, 0); + propagatecopyinstructions(func, 1); + } + + findloopsinflowgraph(); + if (loopsinflowgraph) { + computeusedefchains(1); + analyzeloopsinflowgraph(); + moveloopinvariantcode(); + if (movedloopinvariantcode && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER CODE MOTION 2"); + + removecommonsubexpressions(func, 1); + if (removedcommonsubexpressions) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING 3"); + propagatecopyinstructions(func, 1); + } + } +} + +void globallyoptimizepcode(Object *func) { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "BEFORE GLOBAL OPTIMIZATION"); + + if (copts.optimizationlevel == 2 || (has_catch_blocks && copts.optimizationlevel > 2)) + optimizelevel2(func); + else if (copts.optimizationlevel == 3) + optimizelevel3(func); + else if (copts.optimizationlevel == 4) + optimizelevel4(func); +} diff --git a/compiler_and_linker/unsorted/IROUseDef.c b/compiler_and_linker/unsorted/IROUseDef.c index 943e557..19d39ff 100644 --- a/compiler_and_linker/unsorted/IROUseDef.c +++ b/compiler_and_linker/unsorted/IROUseDef.c @@ -230,8 +230,7 @@ CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) { CInt64_SetLong(&result, -1); break; default: -#line 445 - CError_FATAL(); + CError_FATAL(445); } if (IS_TYPE_POINTER_ONLY(linear->rtype)) { @@ -257,12 +256,10 @@ CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) { result = CInt64_Neg(result); break; default: -#line 491 - CError_FATAL(); + CError_FATAL(491); } } else { -#line 496 - CError_FATAL(); + CError_FATAL(496); } return result; @@ -810,11 +807,9 @@ static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) { for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { obj = nd->u.node->data.objref; -#line 1422 - CError_ASSERT(obj != NULL); + CError_ASSERT(1422, obj != NULL); var = IRO_FindVar(obj, 1, 1); -#line 1424 - CError_ASSERT(var != NULL); + CError_ASSERT(1424, var != NULL); for (def = var->defs; def; def = def->varnext) { if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { @@ -883,8 +878,7 @@ static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { foundObjRef = 1; obj = nd->u.node->data.objref; -#line 1522 - CError_ASSERT(obj != NULL); + CError_ASSERT(1522, obj != NULL); depsList = NULL; PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); @@ -922,8 +916,7 @@ static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b for (olist = depsList; olist; olist = olist->next) { var = IRO_FindVar(olist->object, 1, 1); -#line 1573 - CError_ASSERT(var != NULL); + CError_ASSERT(1573, var != NULL); for (def = var->defs; def; def = def->varnext) { if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { @@ -1286,19 +1279,15 @@ static IROLinear *GetAssigned(IROLinear *nd) { if (!nd) return NULL; - if (nd->type == IROLinearOp2Arg) { + if (nd->type == IROLinearOp2Arg) nd = nd->u.diadic.left; - } else if (nd->type == IROLinearOp1Arg) { + else if (nd->type == IROLinearOp1Arg) nd = nd->u.monadic; - } else { -#line 2338 - CError_FATAL(); - } + else + CError_FATAL(2338); - if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) { -#line 2351 - CError_FATAL(); - } + if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) + CError_FATAL(2351); nd = nd->u.monadic; @@ -1341,24 +1330,19 @@ static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) { assigned->type != IROLinearOperand || assigned->u.node->type != EOBJREF || assigned->u.node->data.objref != from - ) { -#line 2459 - CError_FATAL(); - } + ) + CError_FATAL(2459); assigned->u.node->data.objref = to; } static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) { -#line 2482 - CError_ASSERT(nd->type == IROLinearOperand && nd->u.node->type == EOBJREF); + CError_ASSERT(2482, nd->type == IROLinearOperand && nd->u.node->type == EOBJREF); - if (nd->u.node->data.objref == from) { + if (nd->u.node->data.objref == from) nd->u.node->data.objref = to; - } else if (nd->u.node->data.objref != to) { -#line 2494 - CError_FATAL(); - } + else if (nd->u.node->data.objref != to) + CError_FATAL(2494); } static void SplitOffRange(VarRecord *var) { diff --git a/compiler_and_linker/unsorted/InlineAsm.c b/compiler_and_linker/unsorted/InlineAsm.c index ae73d91..628c678 100644 --- a/compiler_and_linker/unsorted/InlineAsm.c +++ b/compiler_and_linker/unsorted/InlineAsm.c @@ -120,8 +120,7 @@ Boolean InlineAsm_LookupSymbolOrTag(HashNameNode *name, IALookupResult *result, case OT_MEMBERVAR: return 0; default: -#line 245 - CError_FATAL(); + CError_FATAL(245); } } } diff --git a/compiler_and_linker/unsorted/InlineAsmPPC.c b/compiler_and_linker/unsorted/InlineAsmPPC.c index e6e857b..19c8fdc 100644 --- a/compiler_and_linker/unsorted/InlineAsmPPC.c +++ b/compiler_and_linker/unsorted/InlineAsmPPC.c @@ -29,7 +29,7 @@ extern int countexceptionactionregisters(ExceptionAction *); extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *); char asm_alloc_flags[10]; -unsigned char sm_section; +Section sm_section; UInt32 cpu; SInt32 fralloc_parameter_area_size; Boolean user_responsible_for_frame; @@ -1018,8 +1018,7 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { op = ia->args; for (format = mnemonic->format; *format; format++) { -#line 1664 - CError_ASSERT(ia->argcount < argcount); + CError_ASSERT(1664, ia->argcount < argcount); if (*format == ',') { eatcommatoken(); @@ -1114,12 +1113,10 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { code = *format; value = 16; if (code == 'a') { - if (isdigit(format[1])) { + if (isdigit(format[1])) code = *(++format); - } else { -#line 1804 - CError_FATAL(); - } + else + CError_FATAL(1804); } if (isdigit(format[1])) { @@ -1147,10 +1144,8 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { if (negate) op->u.imm.value = -op->u.imm.value; - if (pcode_check_imm_bits(op->u.imm.value, value, code)) { -#line 1838 - CError_FATAL(); - } + if (pcode_check_imm_bits(op->u.imm.value, value, code)) + CError_FATAL(1838); break; } @@ -1253,8 +1248,7 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { case 'd': { short effect2; -#line 1971 - CError_ASSERT(format[1] == '('); + CError_ASSERT(1971, format[1] == '('); format++; effect2 = EffectRead; if (format[1] == '=') { @@ -1265,10 +1259,8 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { format++; } -#line 1983 - CError_ASSERT(format[1] == 'b'); -#line 1985 - CError_ASSERT(format[2] == ')'); + CError_ASSERT(1983, format[1] == 'b'); + CError_ASSERT(1985, format[2] == ')'); format += 2; switch (ia->opcode) { @@ -1385,8 +1377,7 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { break; default: -#line 2266 - CError_FATAL(); + CError_FATAL(2266); } while (format[1] && strchr("/<>|*", format[1])) { @@ -1410,30 +1401,25 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { case '<': case '>': case '|': - if (op->type == IAOpnd_Imm) { + if (op->type == IAOpnd_Imm) value = op->u.imm.value; - } else if (op->type == IAOpnd_Reg) { + else if (op->type == IAOpnd_Reg) value = op->u.reg.num; - } else { -#line 2312 - CError_FATAL(); - } + else + CError_FATAL(2312); if (format[1] == 'p') { format++; - if (op[-1].type == IAOpnd_Imm) { + if (op[-1].type == IAOpnd_Imm) value2 = op[-1].u.imm.value; - } else if (op[-1].type == IAOpnd_Reg) { + else if (op[-1].type == IAOpnd_Reg) value2 = op[-1].u.reg.num; - } else { -#line 2322 - CError_FATAL(); - } + else + CError_FATAL(2322); } else if (isdigit(format[1])) { format += pcode_const_from_format(format + 1, &value2); } else { -#line 2327 - CError_FATAL(); + CError_FATAL(2327); } switch (code) { @@ -1450,18 +1436,15 @@ static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { value = value * value2; break; default: -#line 2348 - CError_FATAL(); + CError_FATAL(2348); } - if (op->type == IAOpnd_Imm) { + if (op->type == IAOpnd_Imm) op->u.imm.value = value; - } else if (op->type == IAOpnd_Reg) { + else if (op->type == IAOpnd_Reg) op->u.reg.num = value; - } else { -#line 2355 - CError_FATAL(); - } + else + CError_FATAL(2355); break; } } @@ -1562,8 +1545,7 @@ void InlineAsm_InitializePPC(void) { case CPU_PPC7400: case CPU_PPC7450: cpu = CPUMask_74xx; break; case CPU_Generic: cpu = CPUMask_Generic; break; default: -#line 2613 - CError_FATAL(); + CError_FATAL(2613); } if (copts.altivec_model) @@ -1785,7 +1767,7 @@ void InlineAsm_ProcessDirective(SInt32 directive) { tk = lex(); if (tk == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "PR")) - sm_section = 1; + sm_section = SECT_TEXT; else CError_Error(CErrorStr144); } else { @@ -1946,8 +1928,7 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 extra_args -= (ia->argcount - argcount); argcount = ia->argcount; } else { -#line 3317 - CError_FATAL(); + CError_FATAL(3317); } } @@ -2030,10 +2011,8 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 dest->arg = src->u.reg.rclass; dest->data.reg.reg = r20; dest->data.reg.effect = src->u.reg.effect; - if (pc->op == PC_RLWIMI && (dest->data.reg.effect & EffectWrite) && dest->arg == RegClass_GPR && !(dest->data.reg.effect & EffectRead)) { -#line 3442 - CError_FATAL(); - } + if (pc->op == PC_RLWIMI && (dest->data.reg.effect & EffectWrite) && dest->arg == RegClass_GPR && !(dest->data.reg.effect & EffectRead)) + CError_FATAL(3442); if (dest->arg == RegClass_SPR) { int i; @@ -2059,8 +2038,7 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 if (src->u.reg.object) { if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag4) { int reg, regHi; -#line 3474 - CError_ASSERT(dest->arg == RegClass_GPR); + CError_ASSERT(3474, dest->arg == RegClass_GPR); regHi = OBJECT_REG_HI(src->u.reg.object); reg = OBJECT_REG(src->u.reg.object); @@ -2113,8 +2091,7 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 break; default: -#line 3528 - CError_FATAL(); + CError_FATAL(3528); } } @@ -2224,8 +2201,7 @@ void InlineAsm_TranslateIRtoPCode(Statement *stmt) { dest = pc->args[0].data.label.label; break; default: -#line 3715 - CError_FATAL(); + CError_FATAL(3715); } if (dest) { @@ -2379,8 +2355,7 @@ static SInt32 InlineAsm_OpcodeSize(InlineAsm *ia) { case PC_STVXL: return 16; default: -#line 3924 - CError_FATAL(); + CError_FATAL(3924); } } else { if (opcodeinfo[ia->opcode].flags & fPCodeFlag80000000) @@ -2397,14 +2372,12 @@ static SInt32 InlineAsm_OpcodeSize(InlineAsm *ia) { case PC_TLBLI: return 4; default: -#line 3941 - CError_FATAL(); + CError_FATAL(3941); } } } -#line 3944 - CError_FATAL(); + CError_FATAL(3944); return 0; } @@ -2474,8 +2447,7 @@ void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { effects->operands[effects->numoperands].size = op->u.reg.object->type->size; effects->numoperands++; } else { -#line 4051 - CError_FATAL(); + CError_FATAL(4051); } } } @@ -2510,14 +2482,11 @@ void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { effects->x3 = 1; break; default: -#line 4087 - CError_FATAL(); + CError_FATAL(4087); } -#line 4090 - CError_ASSERT(effects->numoperands <= 16); -#line 4093 - CError_ASSERT(effects->numlabels <= 16); + CError_ASSERT(4090, effects->numoperands <= 16); + CError_ASSERT(4093, effects->numlabels <= 16); } for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { @@ -2538,8 +2507,7 @@ void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { effects->operands[effects->numoperands].size = op->u.reg.object->type->size; effects->numoperands++; } else { -#line 4132 - CError_FATAL(); + CError_FATAL(4132); } } } @@ -2558,8 +2526,7 @@ void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { break; } -#line 4151 - CError_ASSERT(effects->numoperands <= 16); + CError_ASSERT(4151, effects->numoperands <= 16); } if ((info->flags & (fPCodeFlag1 | fPCodeFlag8)) && (SInt32)effects->numlabels == 0) diff --git a/compiler_and_linker/unsorted/InterferenceGraph.c b/compiler_and_linker/unsorted/InterferenceGraph.c index 424c675..f714b13 100644 --- a/compiler_and_linker/unsorted/InterferenceGraph.c +++ b/compiler_and_linker/unsorted/InterferenceGraph.c @@ -122,14 +122,12 @@ static void buildinterferencematrix(void) { if (coloring_class == RegClass_GPR && (instr->flags & fPCodeFlag8)) { i = branch_count_volatiles(); op = instr->args; -#line 219 - CError_ASSERT(instr->argCount != 0); + CError_ASSERT(219, instr->argCount != 0); while (op->kind != PCOp_REGISTER && !(op->data.reg.effect & EffectWrite)) { i++; op++; -#line 226 - CError_ASSERT(i <= instr->argCount); + CError_ASSERT(226, i <= instr->argCount); } op = instr->args + i; @@ -172,15 +170,13 @@ static void coalescenodes(void) { for (instr = block->firstPCode; instr; instr = instr->nextPCode) { if ((instr->flags & fPCodeFlag10) && !(instr->flags & fSideEffects)) { if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) { -#line 309 - CError_FATAL(); + CError_FATAL(309); continue; } if (instr->argCount > 2) { if (instr->argCount != 3 || instr->args[2].kind != PCOp_PLACEHOLDEROPERAND) { -#line 316 - CError_FATAL(); + CError_FATAL(316); continue; } } diff --git a/compiler_and_linker/unsorted/Intrinsics.c b/compiler_and_linker/unsorted/Intrinsics.c index e69de29..7384b5d 100644 --- a/compiler_and_linker/unsorted/Intrinsics.c +++ b/compiler_and_linker/unsorted/Intrinsics.c @@ -0,0 +1,4894 @@ +#include "compiler/Intrinsics.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/FunctionCalls.h" +#include "compiler/InstrSelection.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/StructMoves.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +Object *__memcpy_object; +static Object *intrinsics[311]; +int VectorConditions; // unused? +static Object *cur_intrinsic_object; + +static TypePointer stvectorunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedchar), 0}; +static TypePointer stvectorsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedchar), 0}; +static TypePointer stvectorboolchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolchar), 0}; +static TypePointer stvectorunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedshort), 0}; +static TypePointer stvectorsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedshort), 0}; +static TypePointer stvectorboolshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolshort), 0}; +static TypePointer stvectorunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedlong), 0}; +static TypePointer stvectorsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedlong), 0}; +static TypePointer stvectorboollong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboollong), 0}; +static TypePointer stvectorfloat_ptr = {TYPEPOINTER, 4, TYPE(&stvectorfloat), 0}; +static TypePointer stvectorpixel_ptr = {TYPEPOINTER, 4, TYPE(&stvectorpixel), 0}; +static TypePointer stunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedchar), 0}; +static TypePointer stsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stsignedchar), 0}; +static TypePointer stunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedshort), 0}; +static TypePointer stsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stsignedshort), 0}; +static TypePointer stunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedlong), 0}; +static TypePointer stsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stsignedlong), 0}; +static TypePointer stunsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedint), 0}; +static TypePointer stsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stsignedint), 0}; +static TypePointer stfloat_ptr = {TYPEPOINTER, 4, TYPE(&stfloat), 0}; + +// Verify1VectorArg2Ops +typedef struct TypeTable22 { + Type *rtype; + Type *arg1; + int opcode1; + int opcode2; +} TypeTable22; + +// VerifyNoVectorArgs +typedef struct TypeTable11 { + Type *rtype; + int opcode; +} TypeTable11; + +// Verify1VectorArg +typedef struct TypeTable21 { + Type *rtype; + Type *arg1; + int opcode; +} TypeTable21; + +// Verify2VectorArgs +typedef struct TypeTable31 { + Type *rtype; + Type *arg1; + Type *arg2; + int opcode; +} TypeTable31; + +// Verify3VectorArgs +typedef struct TypeTable41 { + Type *rtype; + Type *arg1; + Type *arg2; + Type *arg3; + int opcode; +} TypeTable41; + +static TypeTable31 vector_add_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_addc_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDCUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_adds_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_and_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAND, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VAND, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VAND, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VAND, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VAND, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_andc_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VANDC, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VANDC, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VANDC, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VANDC, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_avg_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_ceil_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_cmpb_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpeq_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpge_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpgt_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_ctf_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, + TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cts_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTSXS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_ctu_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTUXS, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_dss_type_table[] = { + TYPE(&stvoid), TYPE(&stsignedint), PC_DSS, PC_B, + NULL, NULL, 0 +}; +static TypeTable11 vector_dssall_type_table[] = { + TYPE(&stvoid), PC_DSSALL, + NULL, 0 +}; +static TypeTable41 vector_datastream_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboolchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboolshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorpixel_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboollong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_expte_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VEXPTEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_floor_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIM, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_load_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVX, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVX, + TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVX, + TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVX, + TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVX, + TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_loade_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_loadl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVXL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVXL, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVXL, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVXL, + TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVXL, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVXL, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVXL, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVXL, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVXL, + TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVXL, + TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVXL, + TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVXL, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVXL, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVXL, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_loge_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VLOGEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_lvsl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSL, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvsr_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSR, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_madd_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMADDFP, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_madds_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHADDSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_max_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mergeh_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mergel_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, + NULL, NULL, NULL, 0 +}; +static TypeTable11 vector_mfvscr_type_table[] = { + TYPE(&stvectorunsignedshort), PC_MFVSCR, + NULL, 0 +}; +static TypeTable31 vector_min_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_mladd_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_mradds_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHRADDSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_msum_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_msums_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_mtvscr_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboolchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboolshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorpixel), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedlong), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboollong), PC_MTVSCR, + NULL, NULL, 0 +}; +static TypeTable31 vector_mule_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mulo_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_nmsub_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNMSUBFP, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_nor_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VNOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VNOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VNOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VNOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VNOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VNOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VNOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VNOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VNOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_or_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_pack_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, + TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packpx_type_table[] = { + TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKPX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packsu_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_perm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VPERM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_re_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VREFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_rl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_round_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIN, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_rsqrte_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRSQRTEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable41 vector_sel_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VSEL, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_sld_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSLDOI, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sll_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSL, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_slo_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSLO, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_splat_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s8_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s16_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s32_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u8_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u16_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u32_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_sr_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sra_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_srl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sro_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSRO, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_st_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_ste_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stl_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_subc_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBCUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_subs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sum4s_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sum2s_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUM2SWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sums_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUMSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_trunc_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIZ, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2sh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2sl_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2uh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2ul_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_unpackh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, + NULL, NULL, 0 +}; +static TypeTable21 vector_unpackl_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, + NULL, NULL, 0 +}; +static TypeTable31 vector_xor_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VXOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VXOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VXOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VXOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VXOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_eq_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_ge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_gt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_in_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_le_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_lt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP +}; +static TypeTable22 vector_all_nan_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_all_ne_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_ngt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nle_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nlt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_all_numeric_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_eq_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_ge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_gt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_le_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_lt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_any_nan_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_ne_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_ngt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nle_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nlt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_any_numeric_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_out_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddubm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduhm_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduwm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddubs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddsbs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduhs_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddshs_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduws_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddsws_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavguh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavguw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequb_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpeqfp_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtub_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsb_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtuh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtuw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtfp_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcfux_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcfsx_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvebx_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvehx_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvewx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxuh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxuw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminuh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminuw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumubm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumuhm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsummbm_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumshm_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumuhs_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumshs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuleub_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulesb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuleuh_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulesh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuloub_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulosb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulouh_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulosh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuhum_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuwum_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, + TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuhus_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkshss_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuwus_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkswss_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkshus_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkswus_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vspltb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsplth_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vspltw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_vspltisb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vspltish_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vspltisw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_vsrb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrab_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrah_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsraw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvebx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvehx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvewx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsububm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuhm_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuwm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsububs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubsbs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuhs_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubshs_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuws_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubsws_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4ubs_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4sbs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4shs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, + NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_vupkhsb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupklsb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, + NULL, NULL, 0 +}; +static TypeTable22 vector_vupkhpx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vupklpx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, PC_B, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupkhsh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupklsh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, + NULL, NULL, 0 +}; +static TypeTable22 vector_abs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, PC_VMAXSB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, PC_VMAXSH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, PC_VMAXSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_abss_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, PC_VMAXSB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, PC_VMAXSH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, PC_VMAXSW, + NULL, NULL, 0 +}; +static void *typeTable[] = { + vector_add_type_table, + vector_addc_type_table, + vector_adds_type_table, + vector_and_type_table, + vector_andc_type_table, + vector_avg_type_table, + vector_ceil_type_table, + vector_cmpb_type_table, + vector_cmpeq_type_table, + vector_cmpge_type_table, + vector_cmpge_type_table, + vector_cmpgt_type_table, + vector_cmpgt_type_table, + vector_ctf_type_table, + vector_cts_type_table, + vector_ctu_type_table, + vector_dss_type_table, + vector_dssall_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_expte_type_table, + vector_floor_type_table, + vector_load_type_table, + vector_loade_type_table, + vector_loadl_type_table, + vector_loge_type_table, + vector_lvsl_type_table, + vector_lvsr_type_table, + vector_madd_type_table, + vector_madds_type_table, + vector_max_type_table, + vector_mergeh_type_table, + vector_mergel_type_table, + vector_mfvscr_type_table, + vector_min_type_table, + vector_mladd_type_table, + vector_mradds_type_table, + vector_msum_type_table, + vector_msums_type_table, + vector_mtvscr_type_table, + vector_mule_type_table, + vector_mulo_type_table, + vector_nmsub_type_table, + vector_nor_type_table, + vector_or_type_table, + vector_pack_type_table, + vector_packpx_type_table, + vector_packs_type_table, + vector_packsu_type_table, + vector_perm_type_table, + vector_re_type_table, + vector_rl_type_table, + vector_round_type_table, + vector_rsqrte_type_table, + vector_sel_type_table, + vector_sl_type_table, + vector_sld_type_table, + vector_sll_type_table, + vector_slo_type_table, + vector_splat_type_table, + vector_splat_s8_type_table, + vector_splat_s16_type_table, + vector_splat_s32_type_table, + vector_splat_u8_type_table, + vector_splat_u16_type_table, + vector_splat_u32_type_table, + vector_sr_type_table, + vector_sra_type_table, + vector_srl_type_table, + vector_sro_type_table, + vector_st_type_table, + vector_ste_type_table, + vector_stl_type_table, + vector_sub_type_table, + vector_subc_type_table, + vector_subs_type_table, + vector_sum4s_type_table, + vector_sum2s_type_table, + vector_sums_type_table, + vector_trunc_type_table, + vector_unpack2sh_type_table, + vector_unpack2sl_type_table, + vector_unpack2uh_type_table, + vector_unpack2ul_type_table, + vector_unpackh_type_table, + vector_unpackl_type_table, + vector_xor_type_table, + vector_all_eq_type_table, + vector_all_ge_type_table, + vector_all_gt_type_table, + vector_all_in_type_table, + vector_all_le_type_table, + vector_all_lt_type_table, + vector_all_nan_type_table, + vector_all_ne_type_table, + vector_all_nge_type_table, + vector_all_ngt_type_table, + vector_all_nle_type_table, + vector_all_nlt_type_table, + vector_all_numeric_type_table, + vector_any_eq_type_table, + vector_any_ge_type_table, + vector_any_gt_type_table, + vector_any_le_type_table, + vector_any_lt_type_table, + vector_any_nan_type_table, + vector_any_ne_type_table, + vector_any_nge_type_table, + vector_any_ngt_type_table, + vector_any_nle_type_table, + vector_any_nlt_type_table, + vector_any_numeric_type_table, + vector_any_out_type_table, + vector_vaddubm_type_table, + vector_vadduhm_type_table, + vector_vadduwm_type_table, + vector_vaddfp_type_table, + vector_addc_type_table, + vector_vaddubs_type_table, + vector_vaddsbs_type_table, + vector_vadduhs_type_table, + vector_vaddshs_type_table, + vector_vadduws_type_table, + vector_vaddsws_type_table, + vector_and_type_table, + vector_andc_type_table, + vector_vavgub_type_table, + vector_vavgsb_type_table, + vector_vavguh_type_table, + vector_vavgsh_type_table, + vector_vavguw_type_table, + vector_vavgsw_type_table, + vector_ceil_type_table, + vector_cmpb_type_table, + vector_vcmpequb_type_table, + vector_vcmpequh_type_table, + vector_vcmpequw_type_table, + vector_vcmpeqfp_type_table, + vector_cmpge_type_table, + vector_vcmpgtub_type_table, + vector_vcmpgtsb_type_table, + vector_vcmpgtuh_type_table, + vector_vcmpgtsh_type_table, + vector_vcmpgtuw_type_table, + vector_vcmpgtsw_type_table, + vector_vcmpgtfp_type_table, + vector_vcfux_type_table, + vector_vcfsx_type_table, + vector_cts_type_table, + vector_ctu_type_table, + vector_expte_type_table, + vector_floor_type_table, + vector_load_type_table, + vector_lvebx_type_table, + vector_lvehx_type_table, + vector_lvewx_type_table, + vector_loadl_type_table, + vector_loge_type_table, + vector_madd_type_table, + vector_madds_type_table, + vector_vmaxub_type_table, + vector_vmaxsb_type_table, + vector_vmaxuh_type_table, + vector_vmaxsh_type_table, + vector_vmaxuw_type_table, + vector_vmaxsw_type_table, + vector_vmaxfp_type_table, + vector_vmrghb_type_table, + vector_vmrghh_type_table, + vector_vmrghw_type_table, + vector_vmrglb_type_table, + vector_vmrglh_type_table, + vector_vmrglw_type_table, + vector_vminub_type_table, + vector_vminsb_type_table, + vector_vminuh_type_table, + vector_vminsh_type_table, + vector_vminuw_type_table, + vector_vminsw_type_table, + vector_vminfp_type_table, + vector_mladd_type_table, + vector_mradds_type_table, + vector_vmsumubm_type_table, + vector_vmsumuhm_type_table, + vector_vmsummbm_type_table, + vector_vmsumshm_type_table, + vector_vmsumuhs_type_table, + vector_vmsumshs_type_table, + vector_vmuleub_type_table, + vector_vmulesb_type_table, + vector_vmuleuh_type_table, + vector_vmulesh_type_table, + vector_vmuloub_type_table, + vector_vmulosb_type_table, + vector_vmulouh_type_table, + vector_vmulosh_type_table, + vector_nmsub_type_table, + vector_nor_type_table, + vector_or_type_table, + vector_vpkuhum_type_table, + vector_vpkuwum_type_table, + vector_packpx_type_table, + vector_vpkuhus_type_table, + vector_vpkshss_type_table, + vector_vpkuwus_type_table, + vector_vpkswss_type_table, + vector_vpkshus_type_table, + vector_vpkswus_type_table, + vector_perm_type_table, + vector_re_type_table, + vector_vrlb_type_table, + vector_vrlh_type_table, + vector_vrlw_type_table, + vector_round_type_table, + vector_rsqrte_type_table, + vector_sel_type_table, + vector_vslb_type_table, + vector_vslh_type_table, + vector_vslw_type_table, + vector_sld_type_table, + vector_sll_type_table, + vector_slo_type_table, + vector_vspltb_type_table, + vector_vsplth_type_table, + vector_vspltw_type_table, + vector_vspltisb_type_table, + vector_vspltish_type_table, + vector_vspltisw_type_table, + vector_vsrb_type_table, + vector_vsrh_type_table, + vector_vsrw_type_table, + vector_vsrab_type_table, + vector_vsrah_type_table, + vector_vsraw_type_table, + vector_srl_type_table, + vector_sro_type_table, + vector_st_type_table, + vector_stvebx_type_table, + vector_stvehx_type_table, + vector_stvewx_type_table, + vector_stl_type_table, + vector_vsububm_type_table, + vector_vsubuhm_type_table, + vector_vsubuwm_type_table, + vector_vsubfp_type_table, + vector_subc_type_table, + vector_vsububs_type_table, + vector_vsubsbs_type_table, + vector_vsubuhs_type_table, + vector_vsubshs_type_table, + vector_vsubuws_type_table, + vector_vsubsws_type_table, + vector_vsum4ubs_type_table, + vector_vsum4sbs_type_table, + vector_vsum4shs_type_table, + vector_sum2s_type_table, + vector_sums_type_table, + vector_trunc_type_table, + vector_vupkhsb_type_table, + vector_vupklsb_type_table, + vector_vupkhpx_type_table, + vector_vupklpx_type_table, + vector_vupkhsh_type_table, + vector_vupklsh_type_table, + vector_xor_type_table, + vector_abs_type_table, + vector_abss_type_table, + NULL +}; + +int is_intrinsic_function_call(ENode *funccall) { + ENode *funcref = funccall->data.funccall.funcref; + return + ENODE_IS(funcref, EOBJREF) && + funcref->data.objref->datatype == DFUNC && + (TYPE_FUNC(funcref->data.objref->type)->flags & FUNC_FLAGS_200); +} + +static void abs_intrinsic(ENode *expr, short outputReg, Operand *output) { + int reg1; + int reg2; + Operand op; + + memclrw(&op, sizeof(op)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg1 = ALLOC_GPR(); + emitpcode(PC_SRAWI, reg1, op.reg, 31); + + reg2 = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_XOR, reg2, reg1, op.reg); + emitpcode(PC_SUBF, reg2, reg1, reg2); + + output->optype = OpndType_GPR; + output->reg = reg2; +} + +static void setflm_intrinsic(ENode *expr, short outputReg, Operand *output, int flag) { + int reg; + Operand op; + + memclrw(&op, sizeof(op)); + GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0); + + if (!flag) { + output->optype = OpndType_FPR; + reg = (outputReg && outputReg != op.reg) ? outputReg : ALLOC_FPR(); + emitpcode(PC_MFFS, output->reg = reg); + } + + emitpcode(PC_MTFSF, 255, op.reg); +} + +static void alloca_intrinsic(ENode *expr, short outputReg, Operand *output) { + int reg; + Operand op; + + memclrw(&op, sizeof(op)); + + if (ENODE_IS(expr, EINTCONST)) { + reg = outputReg ? outputReg : ALLOC_GPR(); + allocate_dynamic_stack_space( + 1, reg, ALLOC_GPR(), CInt64_GetULong(&expr->data.intval)); + } else { + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + reg = outputReg ? outputReg : ALLOC_GPR(); + + emitpcode(PC_NEG, reg, op.reg); + emitpcode(PC_RLWINM, reg, reg, 0, 0, get_alloca_alignment()); + allocate_dynamic_stack_space(0, reg, ALLOC_GPR(), 0); + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void load_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, short outputReg, Operand *output) { + int reg; + Operand op1; + Operand op2; + + reg = outputReg ? outputReg : ALLOC_GPR(); + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { + GEN_NODE(expr1, &op1); + if (op1.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, reg, op1.reg, op1.regOffset); + } else { + ENSURE_GPR(&op1, expr1->rtype, 0); + emitpcode(opcode, reg, 0, op1.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + emitpcode(opcode, reg, op1.reg, op2.reg); + } + + setpcodeflags(fSideEffects | ((expr1->flags | expr2->flags | output->flags) & (fIsConst | fIsVolatile))); + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void store_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, ENode *expr3) { + Operand op1; + Operand op2; + Operand op3; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + + if (ENODE_IS(expr3, EINTCONST) && expr3->data.intval.lo == 0) { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE(expr2, &op2); + if (op2.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, op1.reg, op2.reg, op2.regOffset); + } else { + ENSURE_GPR(&op2, expr2->rtype, 0); + emitpcode(opcode, op1.reg, 0, op2.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + GEN_NODE_TO_GPR(expr3, &op3, expr3->rtype, 0); + emitpcode(opcode, op1.reg, op2.reg, op3.reg); + } + + setpcodeflags(fSideEffects | ((op1.flags | op2.flags | op3.flags) & (fIsConst | fIsVolatile))); +} + +static void data_cache_block_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2) { + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { + GEN_NODE(expr1, &op1); + if (op1.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, op1.reg, op1.regOffset); + } else { + ENSURE_GPR(&op1, expr1->rtype, 0); + emitpcode(opcode, 0, op1.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + emitpcode(opcode, op1.reg, op2.reg); + } +} + +static void memcpy_intrinsic(ENode *destexpr, ENode *srcexpr, SInt32 size, Boolean ignored, Operand *output) { + UInt32 qual; + Operand destOp; + Operand srcOp; + + qual = 0; + + memclrw(&destOp, sizeof(destOp)); + memclrw(&srcOp, sizeof(srcOp)); + + GEN_NODE(srcexpr, &srcOp); + indirect(&srcOp, srcexpr); + + GEN_NODE(destexpr, output); + destOp = *output; + indirect(&destOp, destexpr); + + if (destOp.object) + qual = destOp.object->qual; + + move_block(&destOp, &srcOp, size, destexpr->rtype ? CMach_AllocationAlignment(destexpr->rtype, qual) : 1); +} + +static SInt32 checkconstintarg(ENode *expr, char *name, SInt32 min, SInt32 max, int argnum) { + SInt32 value; + + if (!ENODE_IS(expr, EINTCONST)) + PPCError_ErrorTerm(210, name, 3, max, argnum); + + value = CInt64_GetULong(&expr->data.intval); + + if (value < min) { + PPCError_Warning(211, name, argnum, value, min, max, min); + return min; + } + + if (value > max) { + PPCError_Warning(211, name, argnum, value, min, max, value & max); + value = value & max; + } + + return value; +} + +static void rlwimi_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode *expr5, short outputReg, Operand *output) { + SInt32 arg3; + SInt32 arg4; + SInt32 arg5; + Operand op1; + Operand op2; + int reg; + char *name = "__rlwimi"; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + arg5 = checkconstintarg(expr5, name, 0, 31, 5); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + + GEN_NODE(expr2, &op2); + if (copts.optimizationlevel > 1) { + reg = ALLOC_GPR(); + emitpcode(PC_MR, reg, op1.reg); + op1.reg = reg; + } + ENSURE_GPR(&op2, expr2->rtype, 0); + + emitpcode(PC_RLWIMI, op1.reg, op2.reg, arg3, arg4, arg5); + + output->optype = OpndType_GPR; + output->reg = op1.reg; +} + +static void rlwinm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { + char *name = "__rlwinm"; + short reg; + short arg2; + short arg3; + short arg4; + Operand op1; + + memclrw(&op1, sizeof(op1)); + arg2 = checkconstintarg(expr2, name, 0, 31, 2); + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, reg, op1.reg, arg2, arg3, arg4); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void rlwnm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { + short reg; + short arg3; + short arg4; + char *name = "__rlwnm"; + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWNM, reg, op1.reg, op2.reg, arg3, arg4); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static Boolean promotable_types_are_equal(Type *a, Type *b) { + if (a == b) + return 1; + + if (a == TYPE(&stsignedint)) { + if ( + b == TYPE(&stunsignedint) || + b == TYPE(&stsignedchar) || + b == TYPE(&stunsignedchar) || + b == TYPE(&stsignedshort) || + b == TYPE(&stunsignedshort) || + b == TYPE(&stsignedlong) || + b == TYPE(&stunsignedlong) || + b == TYPE(&stbool) + ) + return 1; + } + + return 0; +} + +static int Intrinsics_VerifyParameterCount(int wantedCount, ENodeList *args, HashNameNode *name) { + ENodeList *scan; + int count; + + for (scan = args, count = 0; scan; scan = scan->next) + count++; + + if (count != wantedCount) { + PPCError_Error(103, name->name, count, wantedCount); + return 0; + } + + return 1; +} + +static ENode *Intrinsics_CreateIntrinsicFunc(Object *func, ENodeList *args, Type *rtype) { + TypeFunc *tfunc; + ENodeList *scan; + ENode *expr; + + tfunc = TYPE_FUNC(func->type); + CError_ASSERT(3741, IS_TYPE_FUNC(tfunc)); + + for (scan = args; scan; scan = scan->next) { + if (IS_TYPE_ARRAY(scan->node->rtype)) + scan->node = CExpr_PointerGeneration(scan->node); + } + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = rtype; + expr->ignored = 0; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.args = args; + expr->data.funccall.functype = tfunc; + return CExpr_AdjustFunctionCall(expr); +} + +static Type *Intrinsics_Verify1VectorArg2Ops(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + TypeTable22 *table; + Type *typeA; + Type *typeB; + Type *rtype; + + arg1 = args->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + rtype = table->rtype; + if (!rtype) { + PPCError_Error(104, name->name, name->name, arg1->rtype, 0); + rtype = NULL; + } + return rtype; +} + +static Type *Intrinsics_VerifyNoVectorArgs(Intrinsics id, HashNameNode *name) { + TypeTable11 *table = typeTable[id - Intrinsic_042]; + return table->rtype; +} + +static Type *Intrinsics_Verify1VectorArg(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + TypeTable21 *table; + Type *typeA; + Type *typeB; + Type *rtype; + + arg1 = args->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + switch (id) { + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_107: + case Intrinsic_108: + case Intrinsic_109: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + if (ENODE_IS(arg1, EINTCONST)) { + SInt32 val = arg1->data.intval.lo; + if (val > 15 || val < -16) { + PPCError_Error(108, name->name, name->name, 5); + return NULL; + } + } else { + PPCError_Error(108, name->name, name->name, 5); + return NULL; + } + break; + case Intrinsic_058: + if (ENODE_IS(arg1, EINTCONST)) { + SInt32 val = arg1->data.intval.lo; + if (val > 3 || val < 0) { + PPCError_Error(108, name->name, name->name, 2); + return NULL; + } + } else { + PPCError_Error(108, name->name, name->name, 2); + return NULL; + } + break; + } + + rtype = table->rtype; + if (!rtype) { + PPCError_Error(104, name->name, name->name, arg1->rtype, 0); + rtype = NULL; + } + return rtype; +} + +static Type *Intrinsics_Verify2VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + ENode *arg2; + TypeTable31 *table; + Type *typeB1; + Type *typeB2; + Type *typeA1; + Type *typeA2; + + arg1 = args->node; + arg2 = args->next->node; + table = typeTable[id - Intrinsic_042]; + + switch (id) { + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_103: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + if (ENODE_IS(arg2, EINTCONST)) { + if (arg2->data.intval.lo > 31 || arg2->data.intval.hi < 0) { + PPCError_Error(108, name->name, name->name, 5); + return NULL; + } + } else { + PPCError_Error(108, name->name, name->name, 5); + return NULL; + } + break; + } + + for (; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2)) + break; + } + + if (!table->rtype) { + PPCError_Error(105, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0); + return NULL; + } + + switch (id) { + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + if (arg2->flags & ENODE_FLAG_VOLATILE) + PPCError_Warning(178, name->name); + } + + return table->rtype; +} + +static Type *Intrinsics_Verify3VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + ENode *arg2; + ENode *arg3; + TypeTable41 *table; + Type *typeB1; + Type *typeB2; + Type *typeB3; + Type *typeA1; + Type *typeA2; + Type *typeA3; + + arg1 = args->node; + arg2 = args->next->node; + arg3 = args->next->next->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeB3 = arg3->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + typeA3 = table->arg3; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { + typeA3 = TPTR_TARGET(typeA3); + typeB3 = TPTR_TARGET(typeB3); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2) && + promotable_types_are_equal(typeA3, typeB3)) + break; + } + + switch (id) { + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + if (ENODE_IS(arg3, EINTCONST)) { + SInt32 val = arg3->data.intval.lo; + if (val > 3 || val < 0) { + PPCError_Error(108, name->name, name->name, 2); + return NULL; + } + } else { + PPCError_Error(108, name->name, name->name, 2); + return NULL; + } + break; + case Intrinsic_100: + case Intrinsic_263: + if (ENODE_IS(arg3, EINTCONST)) { + if (arg3->data.intval.lo > 15 || arg3->data.intval.hi < 0) { + PPCError_Error(108, name->name, name->name, 4); + return NULL; + } + } else { + PPCError_Error(108, name->name, name->name, 4); + return NULL; + } + break; + } + + if (!table->rtype) { + PPCError_Error(106, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0, arg3->rtype, 0); + return NULL; + } + + switch (id) { + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + if (arg3->flags & ENODE_FLAG_VOLATILE) + PPCError_Warning(178, name->name); + } + + return table->rtype; +} + +static Opcode Intrinsics_FindOpcodeNoArgs(Intrinsics id, ENode *funccall) { + TypeTable11 *table = typeTable[id - Intrinsic_042]; + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode1Arg(Intrinsics id, ENode *funccall, ENode *arg1) { + TypeTable21 *table; + Type *typeA; + Type *typeB; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4105, table->rtype); + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode2Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2) { + TypeTable31 *table; + Type *typeB1; + Type *typeB2; + Type *typeA1; + Type *typeA2; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2)) + break; + } + + CError_ASSERT(4144, table->rtype); + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode3Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2, ENode *arg3) { + TypeTable41 *table; + Type *typeB1; + Type *typeB2; + Type *typeB3; + Type *typeA1; + Type *typeA2; + Type *typeA3; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeB3 = arg3->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + typeA3 = table->arg3; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { + typeA3 = TPTR_TARGET(typeA3); + typeB3 = TPTR_TARGET(typeB3); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2) && + promotable_types_are_equal(typeA3, typeB3)) + break; + } + + CError_ASSERT(4191, table->rtype); + return table->opcode; +} + +static void vector_intrinsic_no_args(Opcode opcode) { + emitpcode(opcode); +} + +static void vector_intrinsic_mfvscr(short outputReg, Opcode opcode, Operand *output) { + short reg; + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splats(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4253, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu8(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4277, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu16(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4301, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu32(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4325, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_dss(ENode *arg1) { + Operand op1; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4348, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + emitpcode(PC_DSS, op1.immediate, 0); +} + +static void vector_intrinsic_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_2args1const(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4393, ENODE_IS(arg2, EINTCONST)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE(arg2, &op2); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_3args(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + Operand op3; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + GEN_NODE_TO_VR(arg3, &op3, arg3->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg, op3.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_datastream(ENode *arg1, ENode *arg2, ENode *arg3, Opcode opcode) { + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4445, ENODE_IS(arg3, EINTCONST)); + GEN_NODE_TO_GPR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_GPR(arg2, &op2, arg2->rtype, 0); + + switch (opcode) { + case PC_DST: + case PC_DSTST: + emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo, 0); + break; + case PC_DSTT: + case PC_DSTSTT: + emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo); + break; + default: + CError_FATAL(4463); + } +} + +static void vector_intrinsic_sld(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4479, ENODE_IS(arg3, EINTCONST)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg, arg3->data.intval.lo); + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_load(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + GEN_NODE(arg1, &op1); + if (op1.optype == OpndType_Absolute && op1.immediate == 0) { + op1.optype = OpndType_GPR; + op1.reg = 0; + } else { + ENSURE_GPR(&op1, arg1->rtype, 0); + } + + GEN_NODE(arg2, &op2); + if (op2.optype == OpndType_Absolute && op2.immediate == 0 && op1.reg != 0) { + op2 = op1; + op1.optype = OpndType_GPR; + op1.reg = 0; + } else { + ENSURE_GPR(&op2, arg2->rtype, 0); + } + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg); + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_store(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + Operand op3; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + GEN_NODE(arg2, &op2); + if (op2.optype == OpndType_Absolute && op2.immediate == 0) { + op2.optype = OpndType_GPR; + op2.reg = 0; + } else { + ENSURE_GPR(&op2, arg2->rtype, 0); + } + + GEN_NODE(arg3, &op3); + if (op3.optype == OpndType_Absolute && op3.immediate == 0 && op2.reg != 0) { + op3 = op2; + op2.optype = OpndType_GPR; + op2.reg = 0; + } else { + ENSURE_GPR(&op3, arg3->rtype, 0); + } + + emitpcode(opcode, op1.reg, op2.reg, op3.reg); + output->optype = OpndType_VR; + output->reg = op1.reg; +} + +static void vector_intrinsic_abs(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { + TypeTable22 *table; + Type *typeA; + Type *typeB; + short reg1; + short reg2; + short reg3; + Operand op1; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4617, table->rtype); + + reg1 = ALLOC_VR(); + reg2 = ALLOC_VR(); + reg3 = outputReg ? outputReg : ALLOC_VR(); + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + if (arg1->rtype == TYPE(&stvectorfloat)) { + emitpcode(PC_VSPLTISW, reg1, -1); + emitpcode(PC_VSLW, reg2, reg1, reg1); + emitpcode(table->opcode1, reg3, op1.reg, reg2); + } else { + emitpcode(PC_VSPLTISB, reg1, 0); + emitpcode(table->opcode1, reg2, reg1, op1.reg); + emitpcode(table->opcode2, reg3, op1.reg, reg2); + } + + output->optype = OpndType_VR; + output->reg = reg3; +} + +static void vector_intrinsic_abss(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { + TypeTable22 *table; + Type *typeA; + Type *typeB; + short reg1; + short reg2; + short reg3; + Operand op1; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4683, table->rtype); + + reg1 = ALLOC_VR(); + reg2 = ALLOC_VR(); + reg3 = outputReg ? outputReg : ALLOC_VR(); + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + emitpcode(PC_VSPLTISB, reg1, 0); + emitpcode(table->opcode1, reg2, reg1, op1.reg); + emitpcode(table->opcode2, reg3, op1.reg, reg2); + + output->optype = OpndType_VR; + output->reg = reg3; +} + +static void vector_intrinsic_mtvscr(ENode *arg1, Operand *output, Opcode opcode) { + Operand op1; + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + emitpcode(opcode, op1.reg); +} + +static void vector_predicate_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { + Operand op1; + Operand op2; + short reg1; + short reg2; + short reg3; + Opcode cond; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + + reg1 = ALLOC_VR(); + reg2 = op1.reg; + reg3 = op2.reg; + if ( + ((id == Intrinsic_132 || id == Intrinsic_145) && arg1->rtype != TYPE(&stvectorfloat)) || + ((id == Intrinsic_135 || id == Intrinsic_147) && arg1->rtype == TYPE(&stvectorfloat)) || + id == Intrinsic_136 || + id == Intrinsic_148 || + id == Intrinsic_153 || + id == Intrinsic_141 || + id == Intrinsic_142 || + id == Intrinsic_154 + ) + { + reg3 = op1.reg; + reg2 = op2.reg; + } + emitpcode(opcode, reg1, reg2, reg3); + pcsetrecordbit(pclastblock->lastPCode); + + if (arg1->rtype == TYPE(&stvectorfloat)) { + switch (id) { + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_135: + case Intrinsic_136: + cond = ELESS; + break; + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + cond = EGREATEREQU; + break; + case Intrinsic_134: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + cond = EEQU; + break; + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_156: + cond = ENOTEQU; + break; + default: + CError_FATAL(4805); + } + } else { + switch (id) { + case Intrinsic_131: + case Intrinsic_133: + case Intrinsic_136: + cond = ELESS; + break; + case Intrinsic_144: + case Intrinsic_146: + case Intrinsic_148: + cond = ENOTEQU; + break; + case Intrinsic_132: + case Intrinsic_135: + case Intrinsic_138: + cond = EEQU; + break; + case Intrinsic_145: + case Intrinsic_147: + case Intrinsic_150: + cond = EGREATEREQU; + break; + default: + CError_FATAL(4834); + } + } + + output->optype = OpndType_CRField; + output->reg = 6; + output->regOffset = cond; +} + +static void vector_predicate_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { + Operand op1; + short reg; + Opcode cond; + + memclrw(&op1, sizeof(op1)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + reg = ALLOC_VR(); + emitpcode(opcode, reg, op1.reg, op1.reg); + pcsetrecordbit(pclastblock->lastPCode); + + switch (id) { + case Intrinsic_143: + cond = ELESS; + break; + case Intrinsic_149: + cond = EGREATEREQU; + break; + case Intrinsic_137: + cond = EEQU; + break; + case Intrinsic_155: + cond = ENOTEQU; + break; + default: + CError_FATAL(4878); + } + + output->optype = OpndType_CRField; + output->reg = 6; + output->regOffset = cond; +} + +ENode *Intrinsics_HandleIntrinsicCall(Object *func, ENodeList *args) { + ENode *callexpr; + Type *rtype; + Intrinsics id; + + callexpr = NULL; + + if (copts.altivec_model) { + id = func->u.func.u.intrinsicid; + switch (id) { + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + case Intrinsic_072: + case Intrinsic_073: + case Intrinsic_079: + case Intrinsic_080: + case Intrinsic_081: + case Intrinsic_082: + case Intrinsic_086: + case Intrinsic_093: + case Intrinsic_098: + case Intrinsic_100: + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + case Intrinsic_202: + case Intrinsic_203: + case Intrinsic_224: + case Intrinsic_225: + case Intrinsic_226: + case Intrinsic_227: + case Intrinsic_228: + case Intrinsic_229: + case Intrinsic_230: + case Intrinsic_231: + case Intrinsic_240: + case Intrinsic_252: + case Intrinsic_259: + case Intrinsic_263: + case Intrinsic_280: + case Intrinsic_281: + case Intrinsic_282: + case Intrinsic_283: + case Intrinsic_284: + if (Intrinsics_VerifyParameterCount(3, args, func->name)) { + if ((rtype = Intrinsics_Verify3VectorArgs(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_042: + case Intrinsic_043: + case Intrinsic_044: + case Intrinsic_045: + case Intrinsic_046: + case Intrinsic_047: + case Intrinsic_049: + case Intrinsic_050: + case Intrinsic_051: + case Intrinsic_052: + case Intrinsic_053: + case Intrinsic_054: + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + case Intrinsic_070: + case Intrinsic_071: + case Intrinsic_074: + case Intrinsic_075: + case Intrinsic_076: + case Intrinsic_078: + case Intrinsic_084: + case Intrinsic_085: + case Intrinsic_087: + case Intrinsic_088: + case Intrinsic_089: + case Intrinsic_090: + case Intrinsic_091: + case Intrinsic_092: + case Intrinsic_095: + case Intrinsic_099: + case Intrinsic_101: + case Intrinsic_102: + case Intrinsic_103: + case Intrinsic_110: + case Intrinsic_111: + case Intrinsic_112: + case Intrinsic_113: + case Intrinsic_117: + case Intrinsic_118: + case Intrinsic_119: + case Intrinsic_120: + case Intrinsic_121: + case Intrinsic_122: + case Intrinsic_124: + case Intrinsic_125: + case Intrinsic_126: + case Intrinsic_127: + case Intrinsic_130: + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_134: + case Intrinsic_135: + case Intrinsic_136: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + case Intrinsic_156: + case Intrinsic_157: + case Intrinsic_158: + case Intrinsic_159: + case Intrinsic_160: + case Intrinsic_161: + case Intrinsic_162: + case Intrinsic_163: + case Intrinsic_164: + case Intrinsic_165: + case Intrinsic_166: + case Intrinsic_167: + case Intrinsic_168: + case Intrinsic_169: + case Intrinsic_170: + case Intrinsic_171: + case Intrinsic_172: + case Intrinsic_173: + case Intrinsic_174: + case Intrinsic_175: + case Intrinsic_177: + case Intrinsic_178: + case Intrinsic_179: + case Intrinsic_180: + case Intrinsic_181: + case Intrinsic_182: + case Intrinsic_183: + case Intrinsic_184: + case Intrinsic_185: + case Intrinsic_186: + case Intrinsic_187: + case Intrinsic_188: + case Intrinsic_189: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_196: + case Intrinsic_197: + case Intrinsic_198: + case Intrinsic_199: + case Intrinsic_200: + case Intrinsic_204: + case Intrinsic_205: + case Intrinsic_206: + case Intrinsic_207: + case Intrinsic_208: + case Intrinsic_209: + case Intrinsic_210: + case Intrinsic_211: + case Intrinsic_212: + case Intrinsic_213: + case Intrinsic_214: + case Intrinsic_215: + case Intrinsic_216: + case Intrinsic_217: + case Intrinsic_218: + case Intrinsic_219: + case Intrinsic_220: + case Intrinsic_221: + case Intrinsic_222: + case Intrinsic_223: + case Intrinsic_232: + case Intrinsic_233: + case Intrinsic_234: + case Intrinsic_235: + case Intrinsic_236: + case Intrinsic_237: + case Intrinsic_238: + case Intrinsic_239: + case Intrinsic_241: + case Intrinsic_242: + case Intrinsic_243: + case Intrinsic_244: + case Intrinsic_245: + case Intrinsic_246: + case Intrinsic_247: + case Intrinsic_248: + case Intrinsic_249: + case Intrinsic_250: + case Intrinsic_251: + case Intrinsic_254: + case Intrinsic_255: + case Intrinsic_256: + case Intrinsic_260: + case Intrinsic_261: + case Intrinsic_262: + case Intrinsic_264: + case Intrinsic_265: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + case Intrinsic_272: + case Intrinsic_273: + case Intrinsic_274: + case Intrinsic_275: + case Intrinsic_276: + case Intrinsic_277: + case Intrinsic_278: + case Intrinsic_279: + case Intrinsic_285: + case Intrinsic_286: + case Intrinsic_287: + case Intrinsic_288: + case Intrinsic_289: + case Intrinsic_290: + case Intrinsic_291: + case Intrinsic_292: + case Intrinsic_293: + case Intrinsic_294: + case Intrinsic_295: + case Intrinsic_296: + case Intrinsic_297: + case Intrinsic_298: + case Intrinsic_299: + case Intrinsic_300: + case Intrinsic_308: + if (Intrinsics_VerifyParameterCount(2, args, func->name)) { + if ((rtype = Intrinsics_Verify2VectorArgs(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_048: + case Intrinsic_058: + case Intrinsic_064: + case Intrinsic_065: + case Intrinsic_069: + case Intrinsic_083: + case Intrinsic_094: + case Intrinsic_096: + case Intrinsic_097: + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_107: + case Intrinsic_108: + case Intrinsic_109: + case Intrinsic_123: + case Intrinsic_128: + case Intrinsic_129: + case Intrinsic_137: + case Intrinsic_143: + case Intrinsic_149: + case Intrinsic_155: + case Intrinsic_176: + case Intrinsic_194: + case Intrinsic_195: + case Intrinsic_201: + case Intrinsic_253: + case Intrinsic_257: + case Intrinsic_258: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + case Intrinsic_301: + case Intrinsic_302: + case Intrinsic_303: + case Intrinsic_304: + case Intrinsic_305: + case Intrinsic_306: + case Intrinsic_307: + if (Intrinsics_VerifyParameterCount(1, args, func->name)) { + if ((rtype = Intrinsics_Verify1VectorArg(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_059: + case Intrinsic_077: + if (Intrinsics_VerifyParameterCount(0, args, func->name)) { + if ((rtype = Intrinsics_VerifyNoVectorArgs(id, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_309: + case Intrinsic_310: + if (Intrinsics_VerifyParameterCount(1, args, func->name)) { + if ((rtype = Intrinsics_Verify1VectorArg2Ops(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + } + } + + return callexpr; +} + +void call_intrinsic_function(ENode *funccall, short outputReg, Operand *output) { + ENodeList *args; + Object *object; + Intrinsics id; + Opcode op; + short reg; + + static Opcode opcode[MaxIntrinsics] = { + /* Intrinsic_000 */ PC_EIEIO, + /* Intrinsic_001 */ PC_SYNC, + /* Intrinsic_002 */ PC_ISYNC, + 0, + 0, + /* Intrinsic_005 */ PC_FABS, + /* Intrinsic_006 */ PC_FNABS, + 0, + 0, + /* Intrinsic_009 */ PC_CNTLZW, + /* Intrinsic_010 */ PC_LHBRX, + /* Intrinsic_011 */ PC_LWBRX, + /* Intrinsic_012 */ PC_STHBRX, + /* Intrinsic_013 */ PC_STWBRX, + /* Intrinsic_014 */ PC_DCBF, + /* Intrinsic_015 */ PC_DCBT, + /* Intrinsic_016 */ PC_DCBST, + /* Intrinsic_017 */ PC_DCBTST, + /* Intrinsic_018 */ PC_DCBZ, + /* Intrinsic_019 */ PC_MULHW, + /* Intrinsic_020 */ PC_MULHWU, + /* Intrinsic_021 */ PC_DIVW, + /* Intrinsic_022 */ PC_DIVWU, + /* Intrinsic_023 */ PC_FMADD, + /* Intrinsic_024 */ PC_FMSUB, + /* Intrinsic_025 */ PC_FNMADD, + /* Intrinsic_026 */ PC_FNMSUB, + /* Intrinsic_027 */ PC_FMADDS, + /* Intrinsic_028 */ PC_FMSUBS, + /* Intrinsic_029 */ PC_FNMADDS, + /* Intrinsic_030 */ PC_FNMSUBS, + /* Intrinsic_031 */ PC_MFFS, + /* Intrinsic_032 */ PC_FRES, + /* Intrinsic_033 */ PC_FRSQRTE, + /* Intrinsic_004 */ PC_FSEL, + 0, + 0, + /* Intrinsic_037 */ PC_RLWIMI, + /* Intrinsic_038 */ PC_RLWINM, + /* Intrinsic_039 */ PC_RLWNM, + /* Intrinsic_040 */ PC_FABS, + /* Intrinsic_041 */ PC_FNABS + }; + + args = funccall->data.funccall.args; + object = funccall->data.funccall.funcref->data.objref; + id = object->u.func.u.intrinsicid; + cur_intrinsic_object = object; + + switch (id) { + case Intrinsic_000: + case Intrinsic_001: + case Intrinsic_002: + appendpcode(pclastblock, makepcode(opcode[id])); + output->optype = OpndType_Absolute; + break; + case Intrinsic_003: + case Intrinsic_004: + abs_intrinsic(args->node, outputReg, output); + break; + case Intrinsic_005: + case Intrinsic_006: + case Intrinsic_032: + case Intrinsic_033: + case Intrinsic_040: + case Intrinsic_041: + fp_unary_operator(opcode[id], args->node, outputReg, output); + break; + case Intrinsic_007: + setflm_intrinsic(args->node, outputReg, output, funccall->ignored); + break; + case Intrinsic_008: + alloca_intrinsic(args->node, outputReg, output); + break; + case Intrinsic_009: + unary_operator(PC_CNTLZW, args->node, outputReg, output); + break; + case Intrinsic_010: + case Intrinsic_011: + load_bytereversed_intrinsic(opcode[id], args->node, args->next->node, outputReg, output); + break; + case Intrinsic_012: + case Intrinsic_013: + store_bytereversed_intrinsic(opcode[id], args->node, args->next->node, args->next->next->node); + output->optype = OpndType_Absolute; + break; + case Intrinsic_014: + case Intrinsic_015: + case Intrinsic_016: + case Intrinsic_017: + case Intrinsic_018: + data_cache_block_intrinsic(opcode[id], args->node, args->next->node); + output->optype = OpndType_Absolute; + break; + case Intrinsic_019: + case Intrinsic_020: + case Intrinsic_021: + case Intrinsic_022: + binary_operator(opcode[id], args->node, args->next->node, outputReg, output); + break; + case Intrinsic_023: + case Intrinsic_024: + case Intrinsic_025: + case Intrinsic_026: + case Intrinsic_027: + case Intrinsic_028: + case Intrinsic_029: + case Intrinsic_030: + case Intrinsic_034: + fp_multiply_add(opcode[id], + args->node, args->next->node, args->next->next->node, + outputReg, output); + break; + case Intrinsic_031: + reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_MFFS, output->reg = reg); + output->optype = OpndType_FPR; + break; + case Intrinsic_035: + call_function(funccall, output); + break; + case Intrinsic_036: + if (ENODE_IS(args->next->next->node, EINTCONST)) + memcpy_intrinsic( + args->node, args->next->node, args->next->next->node->data.intval.lo, + funccall->ignored, output); + else + call_function(funccall, output); + break; + case Intrinsic_037: + rlwimi_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + args->next->next->next->next->node, + outputReg, output); + break; + case Intrinsic_038: + rlwinm_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + outputReg, output); + break; + case Intrinsic_039: + rlwnm_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + outputReg, output); + break; + case Intrinsic_072: + case Intrinsic_073: + case Intrinsic_079: + case Intrinsic_080: + case Intrinsic_081: + case Intrinsic_082: + case Intrinsic_086: + case Intrinsic_093: + case Intrinsic_098: + case Intrinsic_202: + case Intrinsic_203: + case Intrinsic_224: + case Intrinsic_225: + case Intrinsic_226: + case Intrinsic_227: + case Intrinsic_228: + case Intrinsic_229: + case Intrinsic_230: + case Intrinsic_231: + case Intrinsic_240: + case Intrinsic_252: + case Intrinsic_259: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_3args(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_100: + case Intrinsic_263: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_sld(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_042: + case Intrinsic_043: + case Intrinsic_044: + case Intrinsic_045: + case Intrinsic_046: + case Intrinsic_047: + case Intrinsic_049: + case Intrinsic_050: + case Intrinsic_051: + case Intrinsic_053: + case Intrinsic_074: + case Intrinsic_075: + case Intrinsic_076: + case Intrinsic_078: + case Intrinsic_084: + case Intrinsic_085: + case Intrinsic_087: + case Intrinsic_088: + case Intrinsic_089: + case Intrinsic_090: + case Intrinsic_091: + case Intrinsic_092: + case Intrinsic_095: + case Intrinsic_099: + case Intrinsic_101: + case Intrinsic_102: + case Intrinsic_110: + case Intrinsic_111: + case Intrinsic_112: + case Intrinsic_113: + case Intrinsic_117: + case Intrinsic_118: + case Intrinsic_119: + case Intrinsic_120: + case Intrinsic_121: + case Intrinsic_122: + case Intrinsic_124: + case Intrinsic_125: + case Intrinsic_126: + case Intrinsic_127: + case Intrinsic_130: + case Intrinsic_157: + case Intrinsic_158: + case Intrinsic_159: + case Intrinsic_160: + case Intrinsic_161: + case Intrinsic_162: + case Intrinsic_163: + case Intrinsic_164: + case Intrinsic_165: + case Intrinsic_166: + case Intrinsic_167: + case Intrinsic_168: + case Intrinsic_169: + case Intrinsic_170: + case Intrinsic_171: + case Intrinsic_172: + case Intrinsic_173: + case Intrinsic_174: + case Intrinsic_175: + case Intrinsic_177: + case Intrinsic_178: + case Intrinsic_179: + case Intrinsic_180: + case Intrinsic_181: + case Intrinsic_182: + case Intrinsic_183: + case Intrinsic_184: + case Intrinsic_185: + case Intrinsic_186: + case Intrinsic_187: + case Intrinsic_188: + case Intrinsic_189: + case Intrinsic_204: + case Intrinsic_205: + case Intrinsic_206: + case Intrinsic_207: + case Intrinsic_208: + case Intrinsic_209: + case Intrinsic_210: + case Intrinsic_211: + case Intrinsic_212: + case Intrinsic_213: + case Intrinsic_214: + case Intrinsic_215: + case Intrinsic_216: + case Intrinsic_217: + case Intrinsic_218: + case Intrinsic_219: + case Intrinsic_220: + case Intrinsic_221: + case Intrinsic_222: + case Intrinsic_223: + case Intrinsic_232: + case Intrinsic_233: + case Intrinsic_234: + case Intrinsic_235: + case Intrinsic_236: + case Intrinsic_237: + case Intrinsic_238: + case Intrinsic_239: + case Intrinsic_241: + case Intrinsic_242: + case Intrinsic_243: + case Intrinsic_244: + case Intrinsic_245: + case Intrinsic_246: + case Intrinsic_247: + case Intrinsic_248: + case Intrinsic_249: + case Intrinsic_250: + case Intrinsic_251: + case Intrinsic_254: + case Intrinsic_255: + case Intrinsic_256: + case Intrinsic_260: + case Intrinsic_261: + case Intrinsic_262: + case Intrinsic_264: + case Intrinsic_265: + case Intrinsic_272: + case Intrinsic_273: + case Intrinsic_274: + case Intrinsic_275: + case Intrinsic_276: + case Intrinsic_277: + case Intrinsic_278: + case Intrinsic_279: + case Intrinsic_285: + case Intrinsic_286: + case Intrinsic_287: + case Intrinsic_288: + case Intrinsic_289: + case Intrinsic_290: + case Intrinsic_291: + case Intrinsic_292: + case Intrinsic_293: + case Intrinsic_294: + case Intrinsic_295: + case Intrinsic_296: + case Intrinsic_297: + case Intrinsic_298: + case Intrinsic_299: + case Intrinsic_300: + case Intrinsic_308: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_048: + case Intrinsic_064: + case Intrinsic_065: + case Intrinsic_069: + case Intrinsic_094: + case Intrinsic_096: + case Intrinsic_097: + case Intrinsic_123: + case Intrinsic_128: + case Intrinsic_129: + case Intrinsic_176: + case Intrinsic_194: + case Intrinsic_195: + case Intrinsic_201: + case Intrinsic_253: + case Intrinsic_257: + case Intrinsic_258: + case Intrinsic_301: + case Intrinsic_302: + case Intrinsic_303: + case Intrinsic_304: + case Intrinsic_305: + case Intrinsic_306: + case Intrinsic_307: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_1arg(args->node, outputReg, output, op); + break; + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_103: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args1const(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splats(args->node, outputReg, output, op); + break; + case Intrinsic_107: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu8(args->node, outputReg, output, op); + break; + case Intrinsic_108: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu16(args->node, outputReg, output, op); + break; + case Intrinsic_109: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu32(args->node, outputReg, output, op); + break; + case Intrinsic_083: + vector_intrinsic_mtvscr(args->node, output, PC_MTVSCR); + break; + case Intrinsic_077: + op = Intrinsics_FindOpcodeNoArgs(id, funccall); + vector_intrinsic_mfvscr(outputReg, op, output); + break; + case Intrinsic_058: + vector_intrinsic_dss(args->node); + break; + case Intrinsic_059: + op = Intrinsics_FindOpcodeNoArgs(id, funccall); + vector_intrinsic_no_args(op); + break; + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + switch (id) { + case Intrinsic_060: + op = PC_DST; + break; + case Intrinsic_061: + op = PC_DSTST; + break; + case Intrinsic_062: + op = PC_DSTSTT; + break; + case Intrinsic_063: + op = PC_DSTT; + break; + } + vector_intrinsic_datastream(args->node, args->next->node, args->next->next->node, op); + break; + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + case Intrinsic_070: + case Intrinsic_071: + case Intrinsic_196: + case Intrinsic_197: + case Intrinsic_198: + case Intrinsic_199: + case Intrinsic_200: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_load(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + case Intrinsic_280: + case Intrinsic_281: + case Intrinsic_282: + case Intrinsic_283: + case Intrinsic_284: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_store(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_134: + case Intrinsic_135: + case Intrinsic_136: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + case Intrinsic_156: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_predicate_2args(args->node, args->next->node, outputReg, output, op, id); + break; + case Intrinsic_137: + case Intrinsic_143: + case Intrinsic_149: + case Intrinsic_155: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_predicate_1arg(args->node, outputReg, output, op, id); + break; + case Intrinsic_309: + vector_intrinsic_abs(id, funccall, args->node, outputReg, output); + break; + case Intrinsic_310: + vector_intrinsic_abss(id, funccall, args->node, outputReg, output); + break; + case Intrinsic_052: + case Intrinsic_054: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); + break; + default: + CError_FATAL(6152); + } +} + +void Intrinsics_SetupRuntimeObjects(void) { + static TypePointer char_ptr = {TYPEPOINTER, 4, TYPE(&stchar), 0}; + Boolean savecpp; + int i; + + savecpp = copts.cplusplus; + copts.cplusplus = 0; + + for (i = 0; i < MaxIntrinsics; i++) + intrinsics[i] = NULL; + + intrinsics[Intrinsic_000] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__eieio"), 0, 0); + intrinsics[Intrinsic_001] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sync"), 0, 0); + intrinsics[Intrinsic_002] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__isync"), 0, 0); + intrinsics[Intrinsic_003] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__abs"), 0, 1, &stsignedint); + intrinsics[Intrinsic_004] = CParser_NewRTFunc(TYPE(&stsignedlong), GetHashNameNodeExport("__labs"), 0, 1, &stsignedlong); + intrinsics[Intrinsic_005] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fabs"), 0, 1, &stdouble); + intrinsics[Intrinsic_006] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnabs"), 0, 1, &stdouble); + intrinsics[Intrinsic_007] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__setflm"), 0, 1, &stdouble); + intrinsics[Intrinsic_033] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__frsqrte"), 0, 1, &stdouble); + intrinsics[Intrinsic_008] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__alloca"), 0, 1, &stunsignedint); + intrinsics[Intrinsic_009] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__cntlzw"), 0, 1, &stunsignedint); + intrinsics[Intrinsic_010] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lhbrx"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_011] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lwbrx"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_012] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sthbrx"), 0, 3, &stunsignedshort, &void_ptr, &stsignedint); + intrinsics[Intrinsic_013] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__stwbrx"), 0, 3, &stunsignedint, &void_ptr, &stsignedint); + intrinsics[Intrinsic_014] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbf"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_015] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbt"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_016] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbst"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_017] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbtst"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_018] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbz"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_019] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__mulhw"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_020] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__mulhwu"), 0, 2, &stunsignedint, &stunsignedint); + intrinsics[Intrinsic_021] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divw"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_022] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divwu"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_023] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmadd"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_024] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmsub"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_025] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmadd"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_026] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmsub"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_034] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fsel"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_027] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmadds"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_028] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_029] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmadds"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_030] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_031] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__mffs"), 0, 0); + intrinsics[Intrinsic_032] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fres"), 0, 1, &stfloat); + intrinsics[Intrinsic_040] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fabsf"), 0, 1, &stfloat); + intrinsics[Intrinsic_041] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnabsf"), 0, 1, &stfloat); + intrinsics[Intrinsic_035] = CParser_NewRTFunc(TYPE(&char_ptr), GetHashNameNodeExport("__strcpy"), 0, 2, &char_ptr, &char_ptr); + TYPE_FUNC(intrinsics[Intrinsic_035]->type)->args->next->qual |= Q_CONST; + intrinsics[Intrinsic_036] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__memcpy"), 0, 3, &void_ptr, &void_ptr, &stunsignedlong); + __memcpy_object = intrinsics[Intrinsic_036]; + TYPE_FUNC(intrinsics[Intrinsic_036]->type)->args->next->qual |= Q_CONST; + intrinsics[Intrinsic_037] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwimi"), 0, 5, &stsignedint, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_038] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwinm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_039] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwnm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_042] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_add"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_043] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_addc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_044] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_adds"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_045] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_and"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_046] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_andc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_047] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_avg"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_048] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ceil"), 0, 1, &stvector); + intrinsics[Intrinsic_049] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_050] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpeq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_051] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_052] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmple"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_053] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpgt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_054] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmplt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_055] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctf"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_056] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cts"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_057] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctu"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_058] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dss"), 0, 1, &stsignedint); + intrinsics[Intrinsic_059] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dssall"), 0, 0); + intrinsics[Intrinsic_060] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dst"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_061] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstst"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_062] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dststt"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_063] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstt"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_064] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_expte"), 0, 1, &stvector); + intrinsics[Intrinsic_065] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_floor"), 0, 1, &stvector); + intrinsics[Intrinsic_066] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ld"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_067] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lde"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_068] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ldl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_069] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_loge"), 0, 1, &stvector); + intrinsics[Intrinsic_070] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_071] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_072] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madd"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_073] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madds"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_074] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_max"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_075] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergeh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_076] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergel"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_077] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mfvscr"), 0, 0); + intrinsics[Intrinsic_078] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_min"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_079] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mladd"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_080] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mradds"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_081] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msum"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_082] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msums"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_083] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mtvscr"), 0, 1, &stvector); + intrinsics[Intrinsic_084] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mule"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_085] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mulo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_086] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nmsub"), 0, 2, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_087] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_088] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_or"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_089] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_pack"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_090] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packpx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_091] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_092] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packsu"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_093] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_perm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_094] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_re"), 0, 1, &stvector); + intrinsics[Intrinsic_095] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_096] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_round"), 0, 1, &stvector); + intrinsics[Intrinsic_097] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rsqrte"), 0, 1, &stvector); + intrinsics[Intrinsic_098] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sel"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_099] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_100] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sld"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_101] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sll"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_102] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_slo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_103] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_104] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s8"), 0, 1, &stvector); + intrinsics[Intrinsic_105] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s16"), 0, 1, &stvector); + intrinsics[Intrinsic_106] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s32"), 0, 1, &stvector); + intrinsics[Intrinsic_107] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u8"), 0, 1, &stvector); + intrinsics[Intrinsic_108] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u16"), 0, 1, &stvector); + intrinsics[Intrinsic_109] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u32"), 0, 1, &stvector); + intrinsics[Intrinsic_110] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_111] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sra"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_112] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_srl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_113] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sro"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_114] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_st"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_115] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ste"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_116] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stl"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_117] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_118] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_119] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_120] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum4s"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_121] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum2s"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_122] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sums"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_123] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_trunc"), 0, 1, &stvector); + intrinsics[Intrinsic_124] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_125] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_126] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2uh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_127] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2ul"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_128] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackh"), 0, 1, &stvector); + intrinsics[Intrinsic_129] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackl"), 0, 1, &stvector); + intrinsics[Intrinsic_130] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_xor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_131] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_eq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_132] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_133] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_gt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_134] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_in"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_135] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_le"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_136] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_lt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_137] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nan"), 0, 1, &stvector); + intrinsics[Intrinsic_138] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ne"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_139] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_140] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ngt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_141] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nle"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_142] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nlt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_143] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_numeric"), 0, 1, &stvector); + intrinsics[Intrinsic_144] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_eq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_145] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_146] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_gt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_147] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_le"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_148] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_lt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_149] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nan"), 0, 1, &stvector); + intrinsics[Intrinsic_150] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ne"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_151] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_152] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ngt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_153] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nle"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_154] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nlt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_155] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_numeric"), 0, 1, &stvector); + intrinsics[Intrinsic_156] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_out"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_157] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_158] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_159] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduwm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_160] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_161] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddcuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_162] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_163] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_164] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_165] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddshs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_166] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_167] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_168] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vand"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_169] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vandc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_170] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_171] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_172] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_173] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_174] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_175] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_176] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfip"), 0, 1, &stvector); + intrinsics[Intrinsic_177] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpbfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_178] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_179] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_180] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_181] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpeqfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_182] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgefp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_183] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_184] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_185] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_186] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_187] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_188] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_189] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_190] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfux"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_191] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfsx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_192] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctsxs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_193] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctuxs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_194] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vexptefp"), 0, 1, &stvector); + intrinsics[Intrinsic_195] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfim"), 0, 1, &stvector); + intrinsics[Intrinsic_196] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_197] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvebx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_198] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvehx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_199] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvewx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_200] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvxl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_201] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vlogefp"), 0, 1, &stvector); + intrinsics[Intrinsic_202] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaddfp"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_203] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhaddshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_204] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_205] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_206] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_207] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_208] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_209] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_210] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_211] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_212] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_213] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_214] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_215] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_216] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_217] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_218] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_219] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_220] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_221] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_222] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_223] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_224] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmladduhm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_225] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhraddshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_226] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumubm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_227] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_228] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsummbm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_229] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_230] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_231] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_232] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_233] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_234] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_235] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_236] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuloub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_237] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_238] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulouh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_239] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_240] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnmsubfp"), 0, 2, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_241] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_242] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_243] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhum"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_244] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwum"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_245] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkpx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_246] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_247] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshss"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_248] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_249] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswss"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_250] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_251] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_252] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vperm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_253] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrefp"), 0, 1, &stvector); + intrinsics[Intrinsic_254] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_255] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_256] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_257] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfin"), 0, 1, &stvector); + intrinsics[Intrinsic_258] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrsqrtefp"), 0, 1, &stvector); + intrinsics[Intrinsic_259] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsel"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_260] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_261] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_262] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_263] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsldoi"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_264] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_265] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_266] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_267] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsplth"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_268] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_269] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisb"), 0, 1, &stvector); + intrinsics[Intrinsic_270] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltish"), 0, 1, &stvector); + intrinsics[Intrinsic_271] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisw"), 0, 1, &stvector); + intrinsics[Intrinsic_272] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_273] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_274] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_275] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrab"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_276] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrah"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_277] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsraw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_278] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_279] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsro"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_280] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_281] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvebx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_282] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvehx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_283] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvewx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_284] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvxl"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_285] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_286] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_287] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuwm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_288] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_289] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubcuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_290] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_291] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_292] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_293] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubshs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_294] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_295] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_296] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4ubs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_297] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4sbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_298] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4shs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_299] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum2sws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_300] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsumsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_301] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfiz"), 0, 1, &stvector); + intrinsics[Intrinsic_302] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsb"), 0, 1, &stvector); + intrinsics[Intrinsic_303] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsb"), 0, 1, &stvector); + intrinsics[Intrinsic_304] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhpx"), 0, 1, &stvector); + intrinsics[Intrinsic_305] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklpx"), 0, 1, &stvector); + intrinsics[Intrinsic_306] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsh"), 0, 1, &stvector); + intrinsics[Intrinsic_307] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsh"), 0, 1, &stvector); + intrinsics[Intrinsic_308] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vxor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_309] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abs"), 0, 1, &stvector); + intrinsics[Intrinsic_310] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abss"), 0, 1, &stvector); + + for (i = 0; i < MaxIntrinsics; i++) { + CError_ASSERT(6600, intrinsics[i]); + intrinsics[i]->u.func.u.intrinsicid = i; + TYPE_FUNC(intrinsics[i]->type)->flags |= FUNC_FLAGS_200; + CScope_AddGlobalObject(intrinsics[i]); + } + + copts.cplusplus = savecpp; +} + +static Object *CheckRuntimeObject(char *name) { + NameSpaceName *nsname = CScope_FindNameSpaceName(cscope_root, GetHashNameNodeExport(name)); + + if (!nsname) + return NULL; + + if (nsname->first.object && nsname->first.next == NULL) + return OBJECT(nsname->first.object); + + return NULL; +} + +Boolean Intrinsics_ReInitRuntimeObjects(Boolean flag) { + if (flag) { + if (!(intrinsics[Intrinsic_000] = CheckRuntimeObject("__eieio"))) return 0; + if (!(intrinsics[Intrinsic_001] = CheckRuntimeObject("__sync"))) return 0; + if (!(intrinsics[Intrinsic_002] = CheckRuntimeObject("__isync"))) return 0; + if (!(intrinsics[Intrinsic_003] = CheckRuntimeObject("__abs"))) return 0; + if (!(intrinsics[Intrinsic_004] = CheckRuntimeObject("__labs"))) return 0; + if (!(intrinsics[Intrinsic_005] = CheckRuntimeObject("__fabs"))) return 0; + if (!(intrinsics[Intrinsic_006] = CheckRuntimeObject("__fnabs"))) return 0; + if (!(intrinsics[Intrinsic_007] = CheckRuntimeObject("__setflm"))) return 0; + if (!(intrinsics[Intrinsic_033] = CheckRuntimeObject("__frsqrte"))) return 0; + if (!(intrinsics[Intrinsic_008] = CheckRuntimeObject("__alloca"))) return 0; + if (!(intrinsics[Intrinsic_009] = CheckRuntimeObject("__cntlzw"))) return 0; + if (!(intrinsics[Intrinsic_010] = CheckRuntimeObject("__lhbrx"))) return 0; + if (!(intrinsics[Intrinsic_011] = CheckRuntimeObject("__lwbrx"))) return 0; + if (!(intrinsics[Intrinsic_012] = CheckRuntimeObject("__sthbrx"))) return 0; + if (!(intrinsics[Intrinsic_013] = CheckRuntimeObject("__stwbrx"))) return 0; + if (!(intrinsics[Intrinsic_014] = CheckRuntimeObject("__dcbf"))) return 0; + if (!(intrinsics[Intrinsic_015] = CheckRuntimeObject("__dcbt"))) return 0; + if (!(intrinsics[Intrinsic_016] = CheckRuntimeObject("__dcbst"))) return 0; + if (!(intrinsics[Intrinsic_017] = CheckRuntimeObject("__dcbtst"))) return 0; + if (!(intrinsics[Intrinsic_018] = CheckRuntimeObject("__dcbz"))) return 0; + if (!(intrinsics[Intrinsic_019] = CheckRuntimeObject("__mulhw"))) return 0; + if (!(intrinsics[Intrinsic_020] = CheckRuntimeObject("__mulhwu"))) return 0; + if (!(intrinsics[Intrinsic_021] = CheckRuntimeObject("__divw"))) return 0; + if (!(intrinsics[Intrinsic_022] = CheckRuntimeObject("__divwu"))) return 0; + if (!(intrinsics[Intrinsic_023] = CheckRuntimeObject("__fmadd"))) return 0; + if (!(intrinsics[Intrinsic_024] = CheckRuntimeObject("__fmsub"))) return 0; + if (!(intrinsics[Intrinsic_025] = CheckRuntimeObject("__fnmadd"))) return 0; + if (!(intrinsics[Intrinsic_026] = CheckRuntimeObject("__fnmsub"))) return 0; + if (!(intrinsics[Intrinsic_034] = CheckRuntimeObject("__fsel"))) return 0; + if (!(intrinsics[Intrinsic_027] = CheckRuntimeObject("__fmadds"))) return 0; + if (!(intrinsics[Intrinsic_028] = CheckRuntimeObject("__fmsubs"))) return 0; + if (!(intrinsics[Intrinsic_029] = CheckRuntimeObject("__fnmadds"))) return 0; + if (!(intrinsics[Intrinsic_030] = CheckRuntimeObject("__fnmsubs"))) return 0; + if (!(intrinsics[Intrinsic_031] = CheckRuntimeObject("__mffs"))) return 0; + if (!(intrinsics[Intrinsic_032] = CheckRuntimeObject("__fres"))) return 0; + if (!(intrinsics[Intrinsic_040] = CheckRuntimeObject("__fabsf"))) return 0; + if (!(intrinsics[Intrinsic_041] = CheckRuntimeObject("__fnabsf"))) return 0; + if (!(intrinsics[Intrinsic_035] = CheckRuntimeObject("__strcpy"))) return 0; + if (!(intrinsics[Intrinsic_037] = CheckRuntimeObject("__rlwimi"))) return 0; + if (!(intrinsics[Intrinsic_038] = CheckRuntimeObject("__rlwinm"))) return 0; + if (!(intrinsics[Intrinsic_039] = CheckRuntimeObject("__rlwnm"))) return 0; + if (!(intrinsics[Intrinsic_042] = CheckRuntimeObject("vec_add"))) return 0; + if (!(intrinsics[Intrinsic_043] = CheckRuntimeObject("vec_addc"))) return 0; + if (!(intrinsics[Intrinsic_044] = CheckRuntimeObject("vec_adds"))) return 0; + if (!(intrinsics[Intrinsic_045] = CheckRuntimeObject("vec_and"))) return 0; + if (!(intrinsics[Intrinsic_046] = CheckRuntimeObject("vec_andc"))) return 0; + if (!(intrinsics[Intrinsic_047] = CheckRuntimeObject("vec_avg"))) return 0; + if (!(intrinsics[Intrinsic_048] = CheckRuntimeObject("vec_ceil"))) return 0; + if (!(intrinsics[Intrinsic_049] = CheckRuntimeObject("vec_cmpb"))) return 0; + if (!(intrinsics[Intrinsic_050] = CheckRuntimeObject("vec_cmpeq"))) return 0; + if (!(intrinsics[Intrinsic_051] = CheckRuntimeObject("vec_cmpge"))) return 0; + if (!(intrinsics[Intrinsic_052] = CheckRuntimeObject("vec_cmple"))) return 0; + if (!(intrinsics[Intrinsic_053] = CheckRuntimeObject("vec_cmpgt"))) return 0; + if (!(intrinsics[Intrinsic_054] = CheckRuntimeObject("vec_cmplt"))) return 0; + if (!(intrinsics[Intrinsic_055] = CheckRuntimeObject("vec_ctf"))) return 0; + if (!(intrinsics[Intrinsic_056] = CheckRuntimeObject("vec_cts"))) return 0; + if (!(intrinsics[Intrinsic_057] = CheckRuntimeObject("vec_ctu"))) return 0; + if (!(intrinsics[Intrinsic_064] = CheckRuntimeObject("vec_expte"))) return 0; + if (!(intrinsics[Intrinsic_065] = CheckRuntimeObject("vec_floor"))) return 0; + if (!(intrinsics[Intrinsic_066] = CheckRuntimeObject("vec_ld"))) return 0; + if (!(intrinsics[Intrinsic_067] = CheckRuntimeObject("vec_lde"))) return 0; + if (!(intrinsics[Intrinsic_068] = CheckRuntimeObject("vec_ldl"))) return 0; + if (!(intrinsics[Intrinsic_069] = CheckRuntimeObject("vec_loge"))) return 0; + if (!(intrinsics[Intrinsic_070] = CheckRuntimeObject("vec_lvsl"))) return 0; + if (!(intrinsics[Intrinsic_071] = CheckRuntimeObject("vec_lvsr"))) return 0; + if (!(intrinsics[Intrinsic_072] = CheckRuntimeObject("vec_madd"))) return 0; + if (!(intrinsics[Intrinsic_073] = CheckRuntimeObject("vec_madds"))) return 0; + if (!(intrinsics[Intrinsic_074] = CheckRuntimeObject("vec_max"))) return 0; + if (!(intrinsics[Intrinsic_075] = CheckRuntimeObject("vec_mergeh"))) return 0; + if (!(intrinsics[Intrinsic_076] = CheckRuntimeObject("vec_mergel"))) return 0; + if (!(intrinsics[Intrinsic_077] = CheckRuntimeObject("vec_mfvscr"))) return 0; + if (!(intrinsics[Intrinsic_078] = CheckRuntimeObject("vec_min"))) return 0; + if (!(intrinsics[Intrinsic_079] = CheckRuntimeObject("vec_mladd"))) return 0; + if (!(intrinsics[Intrinsic_080] = CheckRuntimeObject("vec_mradds"))) return 0; + if (!(intrinsics[Intrinsic_081] = CheckRuntimeObject("vec_msum"))) return 0; + if (!(intrinsics[Intrinsic_082] = CheckRuntimeObject("vec_msums"))) return 0; + if (!(intrinsics[Intrinsic_083] = CheckRuntimeObject("vec_mtvscr"))) return 0; + if (!(intrinsics[Intrinsic_084] = CheckRuntimeObject("vec_mule"))) return 0; + if (!(intrinsics[Intrinsic_085] = CheckRuntimeObject("vec_mulo"))) return 0; + if (!(intrinsics[Intrinsic_086] = CheckRuntimeObject("vec_nmsub"))) return 0; + if (!(intrinsics[Intrinsic_087] = CheckRuntimeObject("vec_nor"))) return 0; + if (!(intrinsics[Intrinsic_088] = CheckRuntimeObject("vec_or"))) return 0; + if (!(intrinsics[Intrinsic_089] = CheckRuntimeObject("vec_pack"))) return 0; + if (!(intrinsics[Intrinsic_090] = CheckRuntimeObject("vec_packpx"))) return 0; + if (!(intrinsics[Intrinsic_091] = CheckRuntimeObject("vec_packs"))) return 0; + if (!(intrinsics[Intrinsic_092] = CheckRuntimeObject("vec_packsu"))) return 0; + if (!(intrinsics[Intrinsic_093] = CheckRuntimeObject("vec_perm"))) return 0; + if (!(intrinsics[Intrinsic_094] = CheckRuntimeObject("vec_re"))) return 0; + if (!(intrinsics[Intrinsic_095] = CheckRuntimeObject("vec_rl"))) return 0; + if (!(intrinsics[Intrinsic_096] = CheckRuntimeObject("vec_round"))) return 0; + if (!(intrinsics[Intrinsic_097] = CheckRuntimeObject("vec_rsqrte"))) return 0; + if (!(intrinsics[Intrinsic_098] = CheckRuntimeObject("vec_sel"))) return 0; + if (!(intrinsics[Intrinsic_099] = CheckRuntimeObject("vec_sl"))) return 0; + if (!(intrinsics[Intrinsic_100] = CheckRuntimeObject("vec_sld"))) return 0; + if (!(intrinsics[Intrinsic_101] = CheckRuntimeObject("vec_sll"))) return 0; + if (!(intrinsics[Intrinsic_102] = CheckRuntimeObject("vec_slo"))) return 0; + if (!(intrinsics[Intrinsic_103] = CheckRuntimeObject("vec_splat"))) return 0; + if (!(intrinsics[Intrinsic_104] = CheckRuntimeObject("vec_splat_s8"))) return 0; + if (!(intrinsics[Intrinsic_105] = CheckRuntimeObject("vec_splat_s16"))) return 0; + if (!(intrinsics[Intrinsic_106] = CheckRuntimeObject("vec_splat_s32"))) return 0; + if (!(intrinsics[Intrinsic_107] = CheckRuntimeObject("vec_splat_u8"))) return 0; + if (!(intrinsics[Intrinsic_108] = CheckRuntimeObject("vec_splat_u16"))) return 0; + if (!(intrinsics[Intrinsic_109] = CheckRuntimeObject("vec_splat_u32"))) return 0; + if (!(intrinsics[Intrinsic_110] = CheckRuntimeObject("vec_sr"))) return 0; + if (!(intrinsics[Intrinsic_111] = CheckRuntimeObject("vec_sra"))) return 0; + if (!(intrinsics[Intrinsic_112] = CheckRuntimeObject("vec_srl"))) return 0; + if (!(intrinsics[Intrinsic_113] = CheckRuntimeObject("vec_sro"))) return 0; + if (!(intrinsics[Intrinsic_114] = CheckRuntimeObject("vec_st"))) return 0; + if (!(intrinsics[Intrinsic_115] = CheckRuntimeObject("vec_ste"))) return 0; + if (!(intrinsics[Intrinsic_116] = CheckRuntimeObject("vec_stl"))) return 0; + if (!(intrinsics[Intrinsic_117] = CheckRuntimeObject("vec_sub"))) return 0; + if (!(intrinsics[Intrinsic_118] = CheckRuntimeObject("vec_subc"))) return 0; + if (!(intrinsics[Intrinsic_119] = CheckRuntimeObject("vec_subs"))) return 0; + if (!(intrinsics[Intrinsic_120] = CheckRuntimeObject("vec_sum4s"))) return 0; + if (!(intrinsics[Intrinsic_121] = CheckRuntimeObject("vec_sum2s"))) return 0; + if (!(intrinsics[Intrinsic_122] = CheckRuntimeObject("vec_sums"))) return 0; + if (!(intrinsics[Intrinsic_123] = CheckRuntimeObject("vec_trunc"))) return 0; + if (!(intrinsics[Intrinsic_124] = CheckRuntimeObject("vec_unpack2sh"))) return 0; + if (!(intrinsics[Intrinsic_125] = CheckRuntimeObject("vec_unpack2sl"))) return 0; + if (!(intrinsics[Intrinsic_126] = CheckRuntimeObject("vec_unpack2uh"))) return 0; + if (!(intrinsics[Intrinsic_127] = CheckRuntimeObject("vec_unpack2ul"))) return 0; + if (!(intrinsics[Intrinsic_128] = CheckRuntimeObject("vec_unpackh"))) return 0; + if (!(intrinsics[Intrinsic_129] = CheckRuntimeObject("vec_unpackl"))) return 0; + if (!(intrinsics[Intrinsic_130] = CheckRuntimeObject("vec_xor"))) return 0; + if (!(intrinsics[Intrinsic_131] = CheckRuntimeObject("vec_all_eq"))) return 0; + if (!(intrinsics[Intrinsic_132] = CheckRuntimeObject("vec_all_ge"))) return 0; + if (!(intrinsics[Intrinsic_133] = CheckRuntimeObject("vec_all_gt"))) return 0; + if (!(intrinsics[Intrinsic_134] = CheckRuntimeObject("vec_all_in"))) return 0; + if (!(intrinsics[Intrinsic_135] = CheckRuntimeObject("vec_all_le"))) return 0; + if (!(intrinsics[Intrinsic_136] = CheckRuntimeObject("vec_all_lt"))) return 0; + if (!(intrinsics[Intrinsic_137] = CheckRuntimeObject("vec_all_nan"))) return 0; + if (!(intrinsics[Intrinsic_138] = CheckRuntimeObject("vec_all_ne"))) return 0; + if (!(intrinsics[Intrinsic_139] = CheckRuntimeObject("vec_all_nge"))) return 0; + if (!(intrinsics[Intrinsic_140] = CheckRuntimeObject("vec_all_ngt"))) return 0; + if (!(intrinsics[Intrinsic_141] = CheckRuntimeObject("vec_all_nle"))) return 0; + if (!(intrinsics[Intrinsic_142] = CheckRuntimeObject("vec_all_nlt"))) return 0; + if (!(intrinsics[Intrinsic_143] = CheckRuntimeObject("vec_all_numeric"))) return 0; + if (!(intrinsics[Intrinsic_144] = CheckRuntimeObject("vec_any_eq"))) return 0; + if (!(intrinsics[Intrinsic_145] = CheckRuntimeObject("vec_any_ge"))) return 0; + if (!(intrinsics[Intrinsic_146] = CheckRuntimeObject("vec_any_gt"))) return 0; + if (!(intrinsics[Intrinsic_147] = CheckRuntimeObject("vec_any_le"))) return 0; + if (!(intrinsics[Intrinsic_148] = CheckRuntimeObject("vec_any_lt"))) return 0; + if (!(intrinsics[Intrinsic_149] = CheckRuntimeObject("vec_any_nan"))) return 0; + if (!(intrinsics[Intrinsic_150] = CheckRuntimeObject("vec_any_ne"))) return 0; + if (!(intrinsics[Intrinsic_151] = CheckRuntimeObject("vec_any_nge"))) return 0; + if (!(intrinsics[Intrinsic_152] = CheckRuntimeObject("vec_any_ngt"))) return 0; + if (!(intrinsics[Intrinsic_153] = CheckRuntimeObject("vec_any_nle"))) return 0; + if (!(intrinsics[Intrinsic_154] = CheckRuntimeObject("vec_any_nlt"))) return 0; + if (!(intrinsics[Intrinsic_155] = CheckRuntimeObject("vec_any_numeric"))) return 0; + if (!(intrinsics[Intrinsic_156] = CheckRuntimeObject("vec_any_out"))) return 0; + if (!(intrinsics[Intrinsic_157] = CheckRuntimeObject("vec_vaddubm"))) return 0; + if (!(intrinsics[Intrinsic_158] = CheckRuntimeObject("vec_vadduhm"))) return 0; + if (!(intrinsics[Intrinsic_159] = CheckRuntimeObject("vec_vadduwm"))) return 0; + if (!(intrinsics[Intrinsic_160] = CheckRuntimeObject("vec_vaddfp"))) return 0; + if (!(intrinsics[Intrinsic_161] = CheckRuntimeObject("vec_vaddcuw"))) return 0; + if (!(intrinsics[Intrinsic_162] = CheckRuntimeObject("vec_vaddubs"))) return 0; + if (!(intrinsics[Intrinsic_163] = CheckRuntimeObject("vec_vaddubs"))) return 0; + if (!(intrinsics[Intrinsic_164] = CheckRuntimeObject("vec_vadduhs"))) return 0; + if (!(intrinsics[Intrinsic_165] = CheckRuntimeObject("vec_vadduhs"))) return 0; + if (!(intrinsics[Intrinsic_166] = CheckRuntimeObject("vec_vadduws"))) return 0; + if (!(intrinsics[Intrinsic_167] = CheckRuntimeObject("vec_vadduws"))) return 0; + if (!(intrinsics[Intrinsic_168] = CheckRuntimeObject("vec_vand"))) return 0; + if (!(intrinsics[Intrinsic_169] = CheckRuntimeObject("vec_vandc"))) return 0; + if (!(intrinsics[Intrinsic_170] = CheckRuntimeObject("vec_vavgub"))) return 0; + if (!(intrinsics[Intrinsic_171] = CheckRuntimeObject("vec_vavgsb"))) return 0; + if (!(intrinsics[Intrinsic_172] = CheckRuntimeObject("vec_vavguh"))) return 0; + if (!(intrinsics[Intrinsic_173] = CheckRuntimeObject("vec_vavgsh"))) return 0; + if (!(intrinsics[Intrinsic_174] = CheckRuntimeObject("vec_vavguw"))) return 0; + if (!(intrinsics[Intrinsic_175] = CheckRuntimeObject("vec_vavgsw"))) return 0; + if (!(intrinsics[Intrinsic_176] = CheckRuntimeObject("vec_vrfip"))) return 0; + if (!(intrinsics[Intrinsic_177] = CheckRuntimeObject("vec_vcmpbfp"))) return 0; + if (!(intrinsics[Intrinsic_178] = CheckRuntimeObject("vec_vcmpequb"))) return 0; + if (!(intrinsics[Intrinsic_179] = CheckRuntimeObject("vec_vcmpequh"))) return 0; + if (!(intrinsics[Intrinsic_180] = CheckRuntimeObject("vec_vcmpequw"))) return 0; + if (!(intrinsics[Intrinsic_181] = CheckRuntimeObject("vec_vcmpeqfp"))) return 0; + if (!(intrinsics[Intrinsic_182] = CheckRuntimeObject("vec_vcmpgefp"))) return 0; + if (!(intrinsics[Intrinsic_183] = CheckRuntimeObject("vec_vcmpgtub"))) return 0; + if (!(intrinsics[Intrinsic_184] = CheckRuntimeObject("vec_vcmpgtsb"))) return 0; + if (!(intrinsics[Intrinsic_185] = CheckRuntimeObject("vec_vcmpgtuh"))) return 0; + if (!(intrinsics[Intrinsic_186] = CheckRuntimeObject("vec_vcmpgtsh"))) return 0; + if (!(intrinsics[Intrinsic_187] = CheckRuntimeObject("vec_vcmpgtuw"))) return 0; + if (!(intrinsics[Intrinsic_188] = CheckRuntimeObject("vec_vcmpgtsw"))) return 0; + if (!(intrinsics[Intrinsic_189] = CheckRuntimeObject("vec_vcmpgtfp"))) return 0; + if (!(intrinsics[Intrinsic_190] = CheckRuntimeObject("vec_vcfux"))) return 0; + if (!(intrinsics[Intrinsic_191] = CheckRuntimeObject("vec_vcfsx"))) return 0; + if (!(intrinsics[Intrinsic_192] = CheckRuntimeObject("vec_vctsxs"))) return 0; + if (!(intrinsics[Intrinsic_193] = CheckRuntimeObject("vec_vctuxs"))) return 0; + if (!(intrinsics[Intrinsic_194] = CheckRuntimeObject("vec_vexptefp"))) return 0; + if (!(intrinsics[Intrinsic_195] = CheckRuntimeObject("vec_vrfim"))) return 0; + if (!(intrinsics[Intrinsic_196] = CheckRuntimeObject("vec_lvx"))) return 0; + if (!(intrinsics[Intrinsic_197] = CheckRuntimeObject("vec_lvebx"))) return 0; + if (!(intrinsics[Intrinsic_198] = CheckRuntimeObject("vec_lvehx"))) return 0; + if (!(intrinsics[Intrinsic_199] = CheckRuntimeObject("vec_lvewx"))) return 0; + if (!(intrinsics[Intrinsic_200] = CheckRuntimeObject("vec_lvxl"))) return 0; + if (!(intrinsics[Intrinsic_201] = CheckRuntimeObject("vec_vlogefp"))) return 0; + if (!(intrinsics[Intrinsic_202] = CheckRuntimeObject("vec_vmaddfp"))) return 0; + if (!(intrinsics[Intrinsic_203] = CheckRuntimeObject("vec_vmhaddshs"))) return 0; + if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vmaxub"))) return 0; + if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vmaxsb"))) return 0; + if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vmaxuh"))) return 0; + if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vmaxsh"))) return 0; + if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vmaxuw"))) return 0; + if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vmaxsw"))) return 0; + if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vmaxfp"))) return 0; + if (!(intrinsics[Intrinsic_211] = CheckRuntimeObject("vec_vmrghb"))) return 0; + if (!(intrinsics[Intrinsic_212] = CheckRuntimeObject("vec_vmrghh"))) return 0; + if (!(intrinsics[Intrinsic_213] = CheckRuntimeObject("vec_vmrghw"))) return 0; + if (!(intrinsics[Intrinsic_214] = CheckRuntimeObject("vec_vmrglb"))) return 0; + if (!(intrinsics[Intrinsic_215] = CheckRuntimeObject("vec_vmrglh"))) return 0; + if (!(intrinsics[Intrinsic_216] = CheckRuntimeObject("vec_vmrglw"))) return 0; + if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vminub"))) return 0; + if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vminsb"))) return 0; + if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vminuh"))) return 0; + if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vminsh"))) return 0; + if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vminuw"))) return 0; + if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vminsw"))) return 0; + if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vminfp"))) return 0; + if (!(intrinsics[Intrinsic_224] = CheckRuntimeObject("vec_vmladduhm"))) return 0; + if (!(intrinsics[Intrinsic_225] = CheckRuntimeObject("vec_vmhraddshs"))) return 0; + if (!(intrinsics[Intrinsic_226] = CheckRuntimeObject("vec_vmsumubm"))) return 0; + if (!(intrinsics[Intrinsic_227] = CheckRuntimeObject("vec_vmsumuhm"))) return 0; + if (!(intrinsics[Intrinsic_228] = CheckRuntimeObject("vec_vmsummbm"))) return 0; + if (!(intrinsics[Intrinsic_229] = CheckRuntimeObject("vec_vmsumshm"))) return 0; + if (!(intrinsics[Intrinsic_230] = CheckRuntimeObject("vec_vmsumuhs"))) return 0; + if (!(intrinsics[Intrinsic_231] = CheckRuntimeObject("vec_vmsumshs"))) return 0; + if (!(intrinsics[Intrinsic_232] = CheckRuntimeObject("vec_vmuleub"))) return 0; + if (!(intrinsics[Intrinsic_233] = CheckRuntimeObject("vec_vmulesb"))) return 0; + if (!(intrinsics[Intrinsic_234] = CheckRuntimeObject("vec_vmuleuh"))) return 0; + if (!(intrinsics[Intrinsic_235] = CheckRuntimeObject("vec_vmulesh"))) return 0; + if (!(intrinsics[Intrinsic_236] = CheckRuntimeObject("vec_vmuloub"))) return 0; + if (!(intrinsics[Intrinsic_237] = CheckRuntimeObject("vec_vmulosb"))) return 0; + if (!(intrinsics[Intrinsic_238] = CheckRuntimeObject("vec_vmulouh"))) return 0; + if (!(intrinsics[Intrinsic_239] = CheckRuntimeObject("vec_vmulosh"))) return 0; + if (!(intrinsics[Intrinsic_240] = CheckRuntimeObject("vec_vnmsubfp"))) return 0; + if (!(intrinsics[Intrinsic_241] = CheckRuntimeObject("vec_vnor"))) return 0; + if (!(intrinsics[Intrinsic_242] = CheckRuntimeObject("vec_vor"))) return 0; + if (!(intrinsics[Intrinsic_243] = CheckRuntimeObject("vec_vpkuhum"))) return 0; + if (!(intrinsics[Intrinsic_244] = CheckRuntimeObject("vec_vpkuwum"))) return 0; + if (!(intrinsics[Intrinsic_245] = CheckRuntimeObject("vec_vpkpx"))) return 0; + if (!(intrinsics[Intrinsic_246] = CheckRuntimeObject("vec_vpkuhus"))) return 0; + if (!(intrinsics[Intrinsic_247] = CheckRuntimeObject("vec_vpkshss"))) return 0; + if (!(intrinsics[Intrinsic_248] = CheckRuntimeObject("vec_vpkuwus"))) return 0; + if (!(intrinsics[Intrinsic_249] = CheckRuntimeObject("vec_vpkswss"))) return 0; + if (!(intrinsics[Intrinsic_250] = CheckRuntimeObject("vec_vpkshus"))) return 0; + if (!(intrinsics[Intrinsic_251] = CheckRuntimeObject("vec_vpkswus"))) return 0; + if (!(intrinsics[Intrinsic_252] = CheckRuntimeObject("vec_vperm"))) return 0; + if (!(intrinsics[Intrinsic_253] = CheckRuntimeObject("vec_vrefp"))) return 0; + if (!(intrinsics[Intrinsic_254] = CheckRuntimeObject("vec_vrlb"))) return 0; + if (!(intrinsics[Intrinsic_255] = CheckRuntimeObject("vec_vrlh"))) return 0; + if (!(intrinsics[Intrinsic_256] = CheckRuntimeObject("vec_vrlw"))) return 0; + if (!(intrinsics[Intrinsic_257] = CheckRuntimeObject("vec_vrfin"))) return 0; + if (!(intrinsics[Intrinsic_258] = CheckRuntimeObject("vec_vrsqrtefp"))) return 0; + if (!(intrinsics[Intrinsic_259] = CheckRuntimeObject("vec_vsel"))) return 0; + if (!(intrinsics[Intrinsic_260] = CheckRuntimeObject("vec_vslb"))) return 0; + if (!(intrinsics[Intrinsic_261] = CheckRuntimeObject("vec_vslh"))) return 0; + if (!(intrinsics[Intrinsic_262] = CheckRuntimeObject("vec_vslw"))) return 0; + if (!(intrinsics[Intrinsic_263] = CheckRuntimeObject("vec_vsldoi"))) return 0; + if (!(intrinsics[Intrinsic_264] = CheckRuntimeObject("vec_vsl"))) return 0; + if (!(intrinsics[Intrinsic_265] = CheckRuntimeObject("vec_vslo"))) return 0; + if (!(intrinsics[Intrinsic_266] = CheckRuntimeObject("vec_vspltb"))) return 0; + if (!(intrinsics[Intrinsic_267] = CheckRuntimeObject("vec_vsplth"))) return 0; + if (!(intrinsics[Intrinsic_268] = CheckRuntimeObject("vec_vspltw"))) return 0; + if (!(intrinsics[Intrinsic_269] = CheckRuntimeObject("vec_vspltisb"))) return 0; + if (!(intrinsics[Intrinsic_270] = CheckRuntimeObject("vec_vspltish"))) return 0; + if (!(intrinsics[Intrinsic_271] = CheckRuntimeObject("vec_vspltisw"))) return 0; + if (!(intrinsics[Intrinsic_272] = CheckRuntimeObject("vec_vsrb"))) return 0; + if (!(intrinsics[Intrinsic_273] = CheckRuntimeObject("vec_vsrh"))) return 0; + if (!(intrinsics[Intrinsic_274] = CheckRuntimeObject("vec_vsrw"))) return 0; + if (!(intrinsics[Intrinsic_275] = CheckRuntimeObject("vec_vsrab"))) return 0; + if (!(intrinsics[Intrinsic_276] = CheckRuntimeObject("vec_vsrah"))) return 0; + if (!(intrinsics[Intrinsic_277] = CheckRuntimeObject("vec_vsraw"))) return 0; + if (!(intrinsics[Intrinsic_278] = CheckRuntimeObject("vec_vsr"))) return 0; + if (!(intrinsics[Intrinsic_279] = CheckRuntimeObject("vec_vsro"))) return 0; + if (!(intrinsics[Intrinsic_280] = CheckRuntimeObject("vec_stvx"))) return 0; + if (!(intrinsics[Intrinsic_281] = CheckRuntimeObject("vec_stvebx"))) return 0; + if (!(intrinsics[Intrinsic_282] = CheckRuntimeObject("vec_stvehx"))) return 0; + if (!(intrinsics[Intrinsic_283] = CheckRuntimeObject("vec_stvewx"))) return 0; + if (!(intrinsics[Intrinsic_284] = CheckRuntimeObject("vec_stvxl"))) return 0; + if (!(intrinsics[Intrinsic_285] = CheckRuntimeObject("vec_vsububm"))) return 0; + if (!(intrinsics[Intrinsic_286] = CheckRuntimeObject("vec_vsubuhm"))) return 0; + if (!(intrinsics[Intrinsic_287] = CheckRuntimeObject("vec_vsubuwm"))) return 0; + if (!(intrinsics[Intrinsic_288] = CheckRuntimeObject("vec_vsubfp"))) return 0; + if (!(intrinsics[Intrinsic_289] = CheckRuntimeObject("vec_vsubcuw"))) return 0; + if (!(intrinsics[Intrinsic_290] = CheckRuntimeObject("vec_vsububs"))) return 0; + if (!(intrinsics[Intrinsic_291] = CheckRuntimeObject("vec_vsubsbs"))) return 0; + if (!(intrinsics[Intrinsic_292] = CheckRuntimeObject("vec_vsubuhs"))) return 0; + if (!(intrinsics[Intrinsic_293] = CheckRuntimeObject("vec_vsubshs"))) return 0; + if (!(intrinsics[Intrinsic_294] = CheckRuntimeObject("vec_vsubuws"))) return 0; + if (!(intrinsics[Intrinsic_295] = CheckRuntimeObject("vec_vsubsws"))) return 0; + if (!(intrinsics[Intrinsic_296] = CheckRuntimeObject("vec_vsum4ubs"))) return 0; + if (!(intrinsics[Intrinsic_297] = CheckRuntimeObject("vec_vsum4sbs"))) return 0; + if (!(intrinsics[Intrinsic_298] = CheckRuntimeObject("vec_vsum4shs"))) return 0; + if (!(intrinsics[Intrinsic_299] = CheckRuntimeObject("vec_vsum2sws"))) return 0; + if (!(intrinsics[Intrinsic_300] = CheckRuntimeObject("vec_vsumsws"))) return 0; + if (!(intrinsics[Intrinsic_301] = CheckRuntimeObject("vec_vrfiz"))) return 0; + if (!(intrinsics[Intrinsic_302] = CheckRuntimeObject("vec_vupkhsb"))) return 0; + if (!(intrinsics[Intrinsic_303] = CheckRuntimeObject("vec_vupklsb"))) return 0; + if (!(intrinsics[Intrinsic_304] = CheckRuntimeObject("vec_vupkhpx"))) return 0; + if (!(intrinsics[Intrinsic_305] = CheckRuntimeObject("vec_vupklpx"))) return 0; + if (!(intrinsics[Intrinsic_306] = CheckRuntimeObject("vec_vupkhsh"))) return 0; + if (!(intrinsics[Intrinsic_307] = CheckRuntimeObject("vec_vupklsh"))) return 0; + if (!(intrinsics[Intrinsic_308] = CheckRuntimeObject("vec_vxor"))) return 0; + if (!(intrinsics[Intrinsic_309] = CheckRuntimeObject("vec_abs"))) return 0; + if (!(intrinsics[Intrinsic_310] = CheckRuntimeObject("vec_abss"))) return 0; + } + + return 1; +} + +Boolean Intrinsics_IsPublicRuntimeObject(Object *object) { + int i; + + for (i = 0; i < MaxIntrinsics; i++) { + if (object == intrinsics[i]) + return 1; + } + + return 0; +} diff --git a/compiler_and_linker/unsorted/IroBitVect.c b/compiler_and_linker/unsorted/IroBitVect.c index f243238..29bc28a 100644 --- a/compiler_and_linker/unsorted/IroBitVect.c +++ b/compiler_and_linker/unsorted/IroBitVect.c @@ -16,12 +16,10 @@ void Bv_AllocVectorLocal(BitVector **bv, UInt32 size) { } void Bv_ClearBit(UInt32 bit, BitVector *bv) { - if ((bit / 32) < bv->size) { + if ((bit / 32) < bv->size) bv->data[bit / 32] &= ~(1 << (bit & 31)); - } else { -#line 73 - CError_FATAL(); - } + else + CError_FATAL(73); } void Bv_And(const BitVector *a, BitVector *b) { diff --git a/compiler_and_linker/unsorted/IroCSE.c b/compiler_and_linker/unsorted/IroCSE.c index e7ad16f..dd82716 100644 --- a/compiler_and_linker/unsorted/IroCSE.c +++ b/compiler_and_linker/unsorted/IroCSE.c @@ -69,14 +69,11 @@ static void GetDependsOfIndirect(IROLinear *nd) { for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { obj = scannd->u.node->data.objref; -#line 119 - CError_ASSERT(obj != NULL); + CError_ASSERT(119, obj != NULL); var = IRO_FindVar(obj, 1, 1); -#line 121 - CError_ASSERT(var != NULL); + CError_ASSERT(121, var != NULL); index = var->index; -#line 123 - CError_ASSERT(index != 0); + CError_ASSERT(123, index != 0); if (is_volatile_object(obj)) { IRO_IsVolatile = 1; @@ -158,8 +155,7 @@ static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { foundObjRef = 1; obj = scannd->u.node->data.objref; -#line 234 - CError_ASSERT(obj != NULL); + CError_ASSERT(234, obj != NULL); depsList = NULL; PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); @@ -199,11 +195,9 @@ static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) { for (olist = depsList; olist; olist = olist->next) { var = IRO_FindVar(olist->object, 1, 1); -#line 285 - CError_ASSERT(var != NULL); + CError_ASSERT(285, var != NULL); index = var->index; -#line 287 - CError_ASSERT(index != 0); + CError_ASSERT(287, index != 0); if (is_volatile_object(olist->object)) { IRO_IsVolatile = 1; @@ -312,8 +306,7 @@ static void IRO_DependsOn(IROLinear *linear, Boolean flag) { IRO_NotSubable = 1; break; default: -#line 479 - CError_FATAL(); + CError_FATAL(479); } } } @@ -384,8 +377,7 @@ static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag) { GetDependsOfFunctionCallForDataFlow(linear); break; default: -#line 650 - CError_FATAL(); + CError_FATAL(650); } } @@ -476,8 +468,7 @@ void IRO_RemoveExpr(IROExpr *expr) { while (scan != expr) { prev = scan; scan = scan->next; -#line 809 - CError_ASSERT(scan); + CError_ASSERT(809, scan); } expr->linear->expr = NULL; @@ -544,11 +535,9 @@ static void GetExprKillsByIndirectAssignment(IROLinear *linear) { for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { obj = scannd->u.node->data.objref; -#line 893 - CError_ASSERT(obj != NULL); + CError_ASSERT(893, obj != NULL); var = IRO_FindVar(obj, 1, 1); -#line 895 - CError_ASSERT(var != NULL); + CError_ASSERT(895, var != NULL); index = var->index; for (expr = IRO_FirstExpr; expr; expr = expr->next) { @@ -615,8 +604,7 @@ static void GetExprKillsByFunctionCall(IROLinear *funccall) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { foundObjRef = 1; obj = scannd->u.node->data.objref; -#line 991 - CError_ASSERT(obj != NULL); + CError_ASSERT(991, obj != NULL); depsList = NULL; PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); @@ -656,11 +644,9 @@ static void GetExprKillsByFunctionCall(IROLinear *funccall) { for (olist = depsList; olist; olist = olist->next) { var = IRO_FindVar(olist->object, 1, 1); -#line 1042 - CError_ASSERT(var != NULL); + CError_ASSERT(1042, var != NULL); index = var->index; -#line 1044 - CError_ASSERT(index != 0); + CError_ASSERT(1044, index != 0); for (expr = IRO_FirstExpr; expr; expr = expr->next) { if (Bv_IsBitSet(index, expr->depends)) diff --git a/compiler_and_linker/unsorted/IroEmptyLoop.c b/compiler_and_linker/unsorted/IroEmptyLoop.c index 1a63f84..780fb9b 100644 --- a/compiler_and_linker/unsorted/IroEmptyLoop.c +++ b/compiler_and_linker/unsorted/IroEmptyLoop.c @@ -93,8 +93,7 @@ static Boolean EmptyLoop(IRONode *fnode) { if (!Bv_IsBitSet(pred->index, InLoop)) { flag2 = 1; if (pred->nextnode == fnode) { -#line 173 - CError_ASSERT(!bestpred || pred == bestpred); + CError_ASSERT(173, !bestpred || pred == bestpred); bestpred = pred; } } @@ -441,8 +440,7 @@ static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) *val1 = CInt64_Add(*val1, neg1); -#line 855 - CError_ASSERT(!CInt64_IsZero(&addConst)); + CError_ASSERT(855, !CInt64_IsZero(&addConst)); if (isUnsigned) *val1 = CInt64_DivU(*val1, addConst); @@ -453,15 +451,11 @@ static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val return 1; if (isUnsigned) { - if (CInt64_LessEqualU(*val1, cint64_zero)) { -#line 877 - CError_FATAL(); - } + if (CInt64_LessEqualU(*val1, cint64_zero)) + CError_FATAL(877); } else { - if (CInt64_LessEqual(*val1, cint64_zero)) { -#line 886 - CError_FATAL(); - } + if (CInt64_LessEqual(*val1, cint64_zero)) + CError_FATAL(886); } if (isUnsigned) { @@ -521,8 +515,7 @@ static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val if (IS_LINEAR_DIADIC(loop->nd18, EGREATER)) *val1 = CInt64_Add(*val1, neg1); -#line 995 - CError_ASSERT(!CInt64_IsZero(&addConst)); + CError_ASSERT(995, !CInt64_IsZero(&addConst)); if (isUnsigned) *val1 = CInt64_DivU(*val1, addConst); diff --git a/compiler_and_linker/unsorted/IroFlowgraph.c b/compiler_and_linker/unsorted/IroFlowgraph.c index 7b6aa3a..f9a18fd 100644 --- a/compiler_and_linker/unsorted/IroFlowgraph.c +++ b/compiler_and_linker/unsorted/IroFlowgraph.c @@ -66,8 +66,7 @@ static void AddLabelSucc(IRONode *node, CLabel *label) { AddSucc(node, targetnode); targetnode->x39 = 1; } else { -#line 126 - CError_FATAL(); + CError_FATAL(126); } } diff --git a/compiler_and_linker/unsorted/IroLinearForm.c b/compiler_and_linker/unsorted/IroLinearForm.c index 8b8e305..c44a90c 100644 --- a/compiler_and_linker/unsorted/IroLinearForm.c +++ b/compiler_and_linker/unsorted/IroLinearForm.c @@ -228,8 +228,7 @@ static inline void MarkSubExpr(IROLinear *linear) { linear->u.funccall.args[i]->flags |= IROLF_Reffed; break; default: -#line 368 - CError_FATAL(); + CError_FATAL(368); } } @@ -281,12 +280,10 @@ static void AssignCommaRToTemp(ENode *enode, Boolean flag) { ENode *indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(obj); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 548 - CError_FATAL(); - } + else + CError_FATAL(548); stmt = lalloc(sizeof(Statement)); memset(stmt, 0, sizeof(Statement)); @@ -311,8 +308,7 @@ static void AssignCommaRToTemp(ENode *enode, Boolean flag) { enode->type = EINDIRECT; enode->data.monadic = create_objectrefnode(obj); -#line 580 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(580, !IS_TYPE_VOID(enode->rtype)); } else { stmt = lalloc(sizeof(Statement)); memset(stmt, 0, sizeof(Statement)); @@ -347,12 +343,10 @@ static void AssignDangerousArgumentToTemp(ENode *enode) { indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(obj); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 627 - CError_FATAL(); - } + else + CError_FATAL(627); rightnode = IRO_NewENode(enode->type); memcpy(rightnode, enode, sizeof(ENode)); @@ -390,12 +384,10 @@ static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) { *objptr = create_temp_object(enode->rtype); indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 678 - CError_FATAL(); - } + else + CError_FATAL(678); rightnode = IRO_NewENode(EINTCONST); rightnode->data.intval = cint64_zero; @@ -431,12 +423,10 @@ static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) { *objptr = create_temp_object(enode->rtype); indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 720 - CError_FATAL(); - } + else + CError_FATAL(720); rightnode = IRO_NewENode(EINTCONST); rightnode->data.intval = cint64_one; @@ -534,8 +524,7 @@ static Object *GetTempFromtheList(ENode *expr) { break; } -#line 839 - CError_ASSERT(n); + CError_ASSERT(839, n); return n->tempobj; } @@ -592,8 +581,7 @@ static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) { indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); indnode->rtype = enode->rtype; -#line 905 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(905, !IS_TYPE_VOID(enode->rtype)); } stmt = lalloc(sizeof(Statement)); @@ -631,8 +619,7 @@ static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) { indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); indnode->rtype = enode->rtype; -#line 953 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(953, !IS_TYPE_VOID(enode->rtype)); } stmt = lalloc(sizeof(Statement)); @@ -671,8 +658,7 @@ static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) { indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); indnode->rtype = enode->rtype; -#line 1003 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(1003, !IS_TYPE_VOID(enode->rtype)); } stmt = lalloc(sizeof(Statement)); @@ -845,12 +831,10 @@ static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **label indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 1225 - CError_FATAL(); - } + else + CError_FATAL(1225); rightnode = IRO_NewENode(EINTCONST); rightnode->data.intval = cint64_one; @@ -898,8 +882,7 @@ static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **label enode->type = EINDIRECT; enode->data.monadic = create_objectrefnode(*objptr); -#line 1276 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(1276, !IS_TYPE_VOID(enode->rtype)); } static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) { @@ -953,12 +936,10 @@ static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelp indnode = IRO_NewENode(EINDIRECT); indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) { + if (!IS_TYPE_VOID(enode->rtype)) indnode->rtype = enode->rtype; - } else { -#line 1354 - CError_FATAL(); - } + else + CError_FATAL(1354); rightnode = IRO_NewENode(EINTCONST); rightnode->data.intval = cint64_zero; @@ -1006,24 +987,22 @@ static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelp enode->type = EINDIRECT; enode->data.monadic = create_objectrefnode(*objptr); -#line 1405 - CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + CError_ASSERT(1405, !IS_TYPE_VOID(enode->rtype)); } static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { switch (a->type) { - ENODE_CASE_MONADIC + ENODE_CASE_MONADIC: LinearizeExpr1(a->data.monadic, a, 0, 0); if (a->type == EFORCELOAD) { Object *obj; GenerateForceLoadTempAssignment(a, &obj); a->type = EINDIRECT; a->data.monadic = create_objectrefnode(obj); -#line 1428 - CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + CError_ASSERT(1428, !IS_TYPE_VOID(a->rtype)); } break; - ENODE_CASE_DIADIC_1 + ENODE_CASE_DIADIC_1: case ECOMMA: case EPMODULO: case EROTL: @@ -1042,7 +1021,7 @@ static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { LinearizeExpr1(a->data.diadic.right, a, 0, 0); } break; - ENODE_CASE_ASSIGN + ENODE_CASE_ASSIGN: LinearizeExpr1(a->data.diadic.right, a, 0, 0); LinearizeExpr1(a->data.diadic.left, a, 0, 0); break; @@ -1081,8 +1060,7 @@ static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { if (!IS_TYPE_VOID(a->rtype)) { a->type = EINDIRECT; a->data.monadic = create_objectrefnode(obj); -#line 1596 - CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + CError_ASSERT(1596, !IS_TYPE_VOID(a->rtype)); } else { a->type = EINTCONST; a->data.intval = cint64_zero; @@ -1093,8 +1071,7 @@ static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { Object *temp = GetTempFromtheList(a); a->type = EINDIRECT; a->data.monadic = create_objectrefnode(temp); -#line 1614 - CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + CError_ASSERT(1614, !IS_TYPE_VOID(a->rtype)); break; } case ENULLCHECK: { @@ -1109,8 +1086,7 @@ static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { if (!IS_TYPE_VOID(a->rtype)) { a->type = EINDIRECT; a->data.monadic = create_objectrefnode(obj); -#line 1639 - CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + CError_ASSERT(1639, !IS_TYPE_VOID(a->rtype)); } else { a->type = EINTCONST; a->data.intval = cint64_zero; @@ -1165,8 +1141,7 @@ static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { break; default: -#line 1723 - CError_FATAL(); + CError_FATAL(1723); } } @@ -1174,7 +1149,7 @@ static IROLinear *LinearizeExpr(ENode *enode) { IROLinear *linear = NULL; switch (enode->type) { - ENODE_CASE_MONADIC + ENODE_CASE_MONADIC: linear = IRO_NewLinear(IROLinearOp1Arg); linear->u.monadic = LinearizeExpr(enode->data.monadic); linear->nodetype = enode->type; @@ -1189,7 +1164,7 @@ static IROLinear *LinearizeExpr(ENode *enode) { MarkSubscript(linear->u.monadic); } break; - ENODE_CASE_DIADIC_1 + ENODE_CASE_DIADIC_1: case ECOMMA: case EPMODULO: case EROTL: @@ -1210,7 +1185,7 @@ static IROLinear *LinearizeExpr(ENode *enode) { if (IRO_IsAssignOp[linear->nodetype]) MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); break; - ENODE_CASE_ASSIGN + ENODE_CASE_ASSIGN: linear = IRO_NewLinear(IROLinearOp2Arg); linear->nodeflags = enode->flags; linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); @@ -1278,8 +1253,7 @@ static IROLinear *LinearizeExpr(ENode *enode) { break; } default: -#line 1943 - CError_FATAL(); + CError_FATAL(1943); } if (linear) @@ -1303,8 +1277,7 @@ void IRO_PreLinearize(Statement *stmt) { case ST_GOTO: break; case ST_OVF: -#line 1989 - CError_FATAL(); + CError_FATAL(1989); case ST_EXPRESSION: LinearizeExpr1(stmt->expr, NULL, 0, 0); break; @@ -1337,8 +1310,7 @@ void IRO_PreLinearize(Statement *stmt) { break; default: -#line 2038 - CError_FATAL(); + CError_FATAL(2038); } PrevStmt = stmt; @@ -1409,8 +1381,7 @@ void IRO_Linearize(Statement *stmt) { linear->u.monadic = NULL; break; case ST_OVF: -#line 2143 - CError_FATAL(); + CError_FATAL(2143); break; case ST_EXIT: linear = IRO_NewLinear(IROLinearExit); @@ -1448,8 +1419,7 @@ void IRO_Linearize(Statement *stmt) { } break; default: -#line 2194 - CError_FATAL(); + CError_FATAL(2194); } if (linear) @@ -1567,8 +1537,7 @@ static ENode *BuildExpr(IROLinear *linear) { default: IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index); -#line 2390 - CError_FATAL(); + CError_FATAL(2390); } enode->pointsTo = linear->pointsToFunction; @@ -1667,8 +1636,7 @@ Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) { stmt = NULL; break; default: -#line 2685 - CError_FATAL(); + CError_FATAL(2685); } if (stmt) { @@ -1742,8 +1710,7 @@ static void TravExprToUpdateFlags(IROLinear *linear) { break; default: IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index); -#line 2853 - CError_FATAL(); + CError_FATAL(2853); } } @@ -1793,8 +1760,7 @@ void IRO_UpdateFlagsOnInts(void) { case IROLinearEnd: break; default: -#line 2931 - CError_FATAL(); + CError_FATAL(2931); } } if (linear == node->last) diff --git a/compiler_and_linker/unsorted/IroLoop.c b/compiler_and_linker/unsorted/IroLoop.c index 7f207e6..01391bd 100644 --- a/compiler_and_linker/unsorted/IroLoop.c +++ b/compiler_and_linker/unsorted/IroLoop.c @@ -402,8 +402,7 @@ static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2 ) return 0; -#line 802 - CError_ASSERT(indirect->u.monadic->u.node != NULL); + CError_ASSERT(802, indirect->u.monadic->u.node != NULL); *resultVar = IRO_FindVar(indirect->u.monadic->u.node->data.objref, 0, 1); if (!*resultVar || (*resultVar)->xA != 2) return 0; @@ -419,8 +418,7 @@ static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2 while (ind && ind->var != *resultVar) ind = ind->next; -#line 845 - CError_ASSERT(ind != NULL); + CError_ASSERT(845, ind != NULL); if (ind->addNode == NULL) { if (ind->addConst < (val = CInt64_GetULong(&val64))) @@ -632,8 +630,7 @@ static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) { fnode2->nextnode = newfnode; newfnode->nextnode = fnode1; } else { -#line 1254 - CError_ASSERT(fnode1->first->type == IROLinearLabel); + CError_ASSERT(1254, fnode1->first->type == IROLinearLabel); labelnode->next = IRO_NewLinear(IROLinearGoto); labelnode->next->u.label.label = fnode1->first->u.label.label; IRO_LastNode->last->next = labelnode; @@ -695,8 +692,7 @@ static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { SwitchCase *swcase; UInt16 i; -#line 1355 - CError_ASSERT(fnode1 != NULL && LoopExitNumber == 1); + CError_ASSERT(1355, fnode1 != NULL && LoopExitNumber == 1); fnode2 = NULL; flag = 0; @@ -704,8 +700,7 @@ static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { for (i = 0; i < fnode1->numpred; i++) { iter = IRO_NodeTable[fnode1->pred[i]]; if (Bv_IsBitSet(iter->index, InLoop_Exits)) { -#line 1366 - CError_ASSERT(fnode2 == NULL); + CError_ASSERT(1366, fnode2 == NULL); fnode2 = iter; if (!flag) { if ( @@ -721,8 +716,7 @@ static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { } } -#line 1382 - CError_ASSERT(fnode2 != NULL); + CError_ASSERT(1382, fnode2 != NULL); newfnode = oalloc(sizeof(IRONode)); memset(newfnode, 0, sizeof(IRONode)); @@ -745,8 +739,7 @@ static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { fnode2->nextnode = newfnode; newfnode->nextnode = fnode1; } else { -#line 1422 - CError_ASSERT(fnode1->first->type == IROLinearLabel); + CError_ASSERT(1422, fnode1->first->type == IROLinearLabel); labelnode->next = IRO_NewLinear(IROLinearGoto); labelnode->next->u.label.label = fnode1->first->u.label.label; IRO_LastNode->last->next = labelnode; @@ -1260,8 +1253,7 @@ static void MyHandleLoop_Vector(IRONode *fnode) { node22 = pred; flag21 = 1; if (pred->nextnode == fnode) { -#line 2880 - CError_ASSERT(v2 == NULL || pred == v2); + CError_ASSERT(2880, v2 == NULL || pred == v2); v2 = pred; } } @@ -1326,8 +1318,7 @@ static void MyHandleLoop_Vector(IRONode *fnode) { induction = FirstInd; while (induction && induction->var != var) induction = induction->next; -#line 3529 - CError_ASSERT(induction != NULL); + CError_ASSERT(3529, induction != NULL); IRO_FindDepends(reduceNd1); if (!Bv_BitsInCommon(IRO_Depends, AllKills)) { @@ -1445,8 +1436,7 @@ static void MyHandleLoop_Motion(IRONode *fnode) { node21 = pred; flag20 = 1; if (pred->nextnode == fnode) { -#line 3880 - CError_ASSERT(v2 == NULL || pred == v2); + CError_ASSERT(3880, v2 == NULL || pred == v2); v2 = pred; } } @@ -1536,8 +1526,7 @@ static void MyHandleLoop_Motion(IRONode *fnode) { IRO_AddToList(ass, &list); IRO_Paste(list.head, list.tail, PredInt); } else { -#line 4123 - CError_FATAL(); + CError_FATAL(4123); } if (LoopExitSuccessor->numpred != 1) diff --git a/compiler_and_linker/unsorted/IroPropagate.c b/compiler_and_linker/unsorted/IroPropagate.c index ebcbb56..fb3a9ad 100644 --- a/compiler_and_linker/unsorted/IroPropagate.c +++ b/compiler_and_linker/unsorted/IroPropagate.c @@ -396,14 +396,12 @@ Boolean IRO_CopyAndConstantPropagation(void) { for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { if (ass2->varIndex == var->index && Bv_IsBitSet(ass2->index, IRO_Avail) && ass2->linear->rtype->size == effects.operands[i].size) { ENode *enode; - if (ass2->varObj) { + if (ass2->varObj) enode = create_objectrefnode(ass2->varObj); - } else if (ass2->linear2->type == IROLinearOperand) { + else if (ass2->linear2->type == IROLinearOperand) enode = ass2->linear2->u.node; - } else { -#line 768 - CError_FATAL(); - } + else + CError_FATAL(768); CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode); break; } diff --git a/compiler_and_linker/unsorted/IroRangePropagation.c b/compiler_and_linker/unsorted/IroRangePropagation.c index c471277..8fbc932 100644 --- a/compiler_and_linker/unsorted/IroRangePropagation.c +++ b/compiler_and_linker/unsorted/IroRangePropagation.c @@ -193,8 +193,7 @@ static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) { for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { obj = scannd->u.node->data.objref; -#line 302 - CError_ASSERT(obj != NULL); + CError_ASSERT(302, obj != NULL); range = nd->x16; if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) @@ -266,8 +265,7 @@ static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) { if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { foundObjRef = 1; obj = scannd->u.node->data.objref; -#line 385 - CError_ASSERT(obj != NULL); + CError_ASSERT(385, obj != NULL); killList = NULL; PointerAnalysis_GetFunctionKills(obj, nd, &killList); diff --git a/compiler_and_linker/unsorted/IroUtil.c b/compiler_and_linker/unsorted/IroUtil.c index 37a6be9..67edd4b 100644 --- a/compiler_and_linker/unsorted/IroUtil.c +++ b/compiler_and_linker/unsorted/IroUtil.c @@ -149,14 +149,12 @@ Type *IRO_UnsignedType(Type *type) { return TYPE(&stunsignedlong); if (type->size == stunsignedlonglong.size) return TYPE(&stunsignedlonglong); -#line 281 - CError_FATAL(); + CError_FATAL(281); return NULL; } if (!IS_TYPE_INT(type)) { -#line 287 - CError_FATAL(); + CError_FATAL(287); return NULL; } @@ -174,8 +172,7 @@ Type *IRO_UnsignedType(Type *type) { if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) return TYPE(&stunsignedlonglong); -#line 319 - CError_FATAL(); + CError_FATAL(319); return NULL; } @@ -191,14 +188,12 @@ Type *IRO_SignedType(Type *type) { return TYPE(&stsignedlong); if (type->size == stsignedlonglong.size) return TYPE(&stsignedlonglong); -#line 357 - CError_FATAL(); + CError_FATAL(357); return NULL; } if (!IS_TYPE_INT(type)) { -#line 363 - CError_FATAL(); + CError_FATAL(363); return NULL; } @@ -219,8 +214,7 @@ Type *IRO_SignedType(Type *type) { if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) return TYPE(&stsignedlonglong); -#line 399 - CError_FATAL(); + CError_FATAL(399); return NULL; } @@ -371,8 +365,7 @@ IROLinear *IRO_FindFirst(IROLinear *linear) { i = linear->u.funccall.argCount - 1; return IRO_FindFirst(linear->u.funccall.args[i]); default: -#line 641 - CError_FATAL(); + CError_FATAL(641); return NULL; } } @@ -562,8 +555,7 @@ void IRO_Cut(IROLinear *a, IROLinear *b) { for (scan = IRO_FirstLinear; scan && scan != a; scan = scan->next) prev = scan; -#line 951 - CError_ASSERT(scan); + CError_ASSERT(951, scan); for (node = IRO_FirstNode; node; node = node->nextnode) { if (node->first == a) { @@ -591,15 +583,13 @@ void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c) { IROLinear *scan; IRONode *node; -#line 1002 - CError_ASSERT(c && c->type != IROLinearLabel); + CError_ASSERT(1002, c && c->type != IROLinearLabel); prev = NULL; for (scan = IRO_FirstLinear; scan && scan != c; scan = scan->next) prev = scan; -#line 1016 - CError_ASSERT(scan); + CError_ASSERT(1016, scan); for (node = IRO_FirstNode; node; node = node->nextnode) { if (node->first == c) { @@ -623,8 +613,7 @@ void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { case IROLinearIf: case IROLinearIfNot: case IROLinearSwitch: -#line 1060 - CError_FATAL(); + CError_FATAL(1060); } for (node = IRO_FirstNode; node; node = node->nextnode) { @@ -719,8 +708,7 @@ IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear) { break; } -#line 1244 - CError_ASSERT(scan); + CError_ASSERT(1244, scan); return scan; } @@ -901,8 +889,7 @@ inline IROLinear *LocateFatherHelper(IROLinear *linear, Boolean a, IROLinear *** case IROLinearEnd: break; default: -#line 1536 - CError_FATAL(); + CError_FATAL(1536); } scan = scan->next; } @@ -923,8 +910,7 @@ IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b) { IROLinear **p; IROLinear *l = LocateFatherHelper(a, 0, &p); if (l) { -#line 1568 - CError_ASSERT(p && *p); + CError_ASSERT(1568, p && *p); IRO_NopOut(a); *p = b; } @@ -935,8 +921,7 @@ IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinea IROLinear **p; IROLinear *l = LocateFatherHelper(a, 0, &p); if (l) { -#line 1585 - CError_ASSERT(p && *p); + CError_ASSERT(1585, p && *p); *p = b; } return l; @@ -947,8 +932,7 @@ void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b) { IROList list; if (LocateFatherHelper(a, 1, &ptr)) { -#line 1605 - CError_ASSERT(ptr && *ptr); + CError_ASSERT(1605, ptr && *ptr); IRO_InitList(&list); *ptr = IRO_TempReference(obj, &list); IRO_PasteAfter(list.head, list.tail, b); @@ -964,8 +948,7 @@ void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b) { IROList list; if (LocateFatherHelper(a, 1, &ptr)) { -#line 1664 - CError_ASSERT(ptr && *ptr); + CError_ASSERT(1664, ptr && *ptr); *ptr = b; b->flags |= IROLF_Reffed; } else { diff --git a/compiler_and_linker/unsorted/IroVars.c b/compiler_and_linker/unsorted/IroVars.c index e306dd0..a40656a 100644 --- a/compiler_and_linker/unsorted/IroVars.c +++ b/compiler_and_linker/unsorted/IroVars.c @@ -467,14 +467,12 @@ VarRecord *IRO_FindAssigned(IROLinear *linear) { VarRecord *rec; IRO_IsBitField = 0; - if (linear->type == IROLinearOp2Arg) { + if (linear->type == IROLinearOp2Arg) linear = linear->u.diadic.left; - } else if (linear->type == IROLinearOp1Arg) { + else if (linear->type == IROLinearOp1Arg) linear = linear->u.monadic; - } else { -#line 818 - CError_FATAL(); - } + else + CError_FATAL(818); if (IS_LINEAR_MONADIC(linear, EINDIRECT)) linear = linear->u.monadic; @@ -561,16 +559,13 @@ static void GetKillsByIndirectAssignment(IROLinear *linear) { int index; obj = nd->u.node->data.objref; -#line 952 - CError_ASSERT(obj != NULL); + CError_ASSERT(952, obj != NULL); var = IRO_FindVar(obj, 1, 1); -#line 954 - CError_ASSERT(var != NULL); + CError_ASSERT(954, var != NULL); index = var->index; -#line 956 - CError_ASSERT(index != 0); + CError_ASSERT(956, index != 0); Bv_SetBit(index, IRO_VarKills); } @@ -631,8 +626,7 @@ static void GetKillsByFunctionCall(IROLinear *linear) { if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { foundLinear = 1; obj = nd->u.node->data.objref; -#line 1028 - CError_ASSERT(obj != NULL); + CError_ASSERT(1028, obj != NULL); killList = NULL; PointerAnalysis_GetFunctionKills(obj, linear, &killList); @@ -674,12 +668,10 @@ static void GetKillsByFunctionCall(IROLinear *linear) { int index; var = IRO_FindVar(olist->object, 1, 1); -#line 1079 - CError_ASSERT(var != NULL); + CError_ASSERT(1079, var != NULL); index = var->index; -#line 1081 - CError_ASSERT(index != 0); + CError_ASSERT(1081, index != 0); Bv_SetBit(index, IRO_VarKills); } @@ -915,12 +907,10 @@ void IRO_RewriteBitFieldTemps(void) { for (nd = IRO_FirstLinear; nd; nd = nd->next) { if ((obj = IRO_IsVariable(nd)) && (nd->flags & IROLF_BitfieldIndirect)) { var = IRO_FindVar(obj, 0, 1); -#line 1526 - CError_ASSERT(var != NULL); + CError_ASSERT(1526, var != NULL); expr2 = var->x1E; -#line 1532 - CError_ASSERT(expr2 != NULL); + CError_ASSERT(1532, expr2 != NULL); IRO_InitList(&list); IRO_DuplicateExpr(expr2, &list); @@ -962,8 +952,7 @@ static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { foundObjRef = 1; obj = nd->u.node->data.objref; -#line 1592 - CError_ASSERT(obj != NULL); + CError_ASSERT(1592, obj != NULL); killList = NULL; PointerAnalysis_GetFunctionKills(obj, funccall, &killList); @@ -972,8 +961,7 @@ static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { result = 1; } else { var = IRO_FindVar(olist->object, 1, 1); -#line 1604 - CError_ASSERT(var != NULL); + CError_ASSERT(1604, var != NULL); if (var->xB) result = 1; } @@ -996,8 +984,7 @@ static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { result = 1; } else { var = IRO_FindVar(olist->object, 1, 1); -#line 1632 - CError_ASSERT(var != NULL); + CError_ASSERT(1632, var != NULL); if (var->xB) result = 1; } @@ -1074,11 +1061,9 @@ static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) { if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { foundObjRef = 1; obj = nd->u.node->data.objref; -#line 1723 - CError_ASSERT(obj != NULL); + CError_ASSERT(1723, obj != NULL); var = IRO_FindVar(obj, 1, 1); -#line 1725 - CError_ASSERT(var != NULL); + CError_ASSERT(1725, var != NULL); if (var->xB) result = 1; @@ -1131,12 +1116,10 @@ void IRO_ScalarizeClassDataMembers(void) { int i; CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); for (i = 0; i < effects.numoperands; i++) { - if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) { + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) CheckAddressConsistency(nd, var, -1, &stvoid); - } else { -#line 1823 - CError_FATAL(); - } + else + CError_FATAL(1823); } } if (nd->type == IROLinearFunccall && !flag) @@ -1254,8 +1237,7 @@ static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) { IS_TYPE_ARRAY(inner->u.node->data.objref->type)) { if (inner->u.node->data.objref->datatype == DLOCAL) { var = IRO_FindVar(inner->u.node->data.objref, 0, 1); -#line 2240 - CError_ASSERT(var != NULL); + CError_ASSERT(2240, var != NULL); CheckAddressConsistency(nd, var, 0, nd->rtype); result = 1; } @@ -1276,8 +1258,7 @@ static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) { ) { if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); -#line 2267 - CError_ASSERT(var != NULL); + CError_ASSERT(2267, var != NULL); CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype); result = 1; } diff --git a/compiler_and_linker/unsorted/LoopDetection.c b/compiler_and_linker/unsorted/LoopDetection.c index 54bc180..5df2524 100644 --- a/compiler_and_linker/unsorted/LoopDetection.c +++ b/compiler_and_linker/unsorted/LoopDetection.c @@ -271,13 +271,11 @@ void insertpreheaderblock(Loop *loop) { if (link->block->pcodeCount) { pcode27 = link->block->lastPCode; if (pcode27->op == PC_B) { -#line 462 - CError_ASSERT(pcode27->args[0].kind == PCOp_LABEL); + CError_ASSERT(462, pcode27->args[0].kind == PCOp_LABEL); if (pcode27->args[0].data.label.label->block == block28) pcode27->args[0].data.label.label = preheader->labels; } else if (pcode27->op == PC_BT || pcode27->op == PC_BF) { -#line 474 - CError_ASSERT(pcode27->args[2].kind == PCOp_LABEL); + CError_ASSERT(474, pcode27->args[2].kind == PCOp_LABEL); if (pcode27->args[2].data.label.label->block == block28) pcode27->args[2].data.label.label = preheader->labels; } else if (pcode27->op == PC_BCTR) { @@ -297,8 +295,7 @@ void insertpreheaderblock(Loop *loop) { } } } else { -#line 505 - CError_ASSERT(link->block->nextBlock == block28); + CError_ASSERT(505, link->block->nextBlock == block28); } } diff --git a/compiler_and_linker/unsorted/LoopOptimization.c b/compiler_and_linker/unsorted/LoopOptimization.c index 327d7e4..1c0b905 100644 --- a/compiler_and_linker/unsorted/LoopOptimization.c +++ b/compiler_and_linker/unsorted/LoopOptimization.c @@ -145,8 +145,7 @@ static void skiplooptest(Loop *loop) { preheader = loop->preheader; lastInstr = loop->body->lastPCode; -#line 340 - CError_ASSERT(lastInstr->args[2].kind == PCOp_LABEL); + CError_ASSERT(340, lastInstr->args[2].kind == PCOp_LABEL); label = lastInstr->args[2].data.label.label; preheader->lastPCode->args[0].data.label.label = label; @@ -166,8 +165,7 @@ static void skiplooptest(Loop *loop) { while (1) { instr = loop->body->firstPCode; -#line 369 - CError_ASSERT(instr); + CError_ASSERT(369, instr); if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) break; @@ -204,12 +202,9 @@ static void unrollloop(Loop *loop) { newBlock->firstPCode = newBlock->lastPCode = NULL; for (i = 0; i < factor - 1; i++) { firstInstr = loop->body->firstPCode; -#line 448 - CError_ASSERT(firstInstr); - if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) { -#line 450 - CError_FATAL(); - } + CError_ASSERT(448, firstInstr); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) + CError_FATAL(450); for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode) appendpcode(newBlock, copypcode(instr)); @@ -236,8 +231,7 @@ void pccomputepredecessors1(PCodeBlock *block) { for (succ = block->successors; succ; succ = succ->nextLink) { if (!succ->block) { -#line 496 - CError_FATAL(); + CError_FATAL(496); } else { for (pred = succ->block->predecessors; pred; pred = pred->nextLink) { if (pred->block == block) @@ -427,12 +421,9 @@ static void unrollloopconditional(Loop *loop) { } firstInstr = loop->body->firstPCode; -#line 762 - CError_ASSERT(firstInstr != NULL); - if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) { -#line 764 - CError_FATAL(); - } + CError_ASSERT(762, firstInstr != NULL); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) + CError_FATAL(764); for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode) appendpcode(blocks2[inputBlockCount - 1], copypcode(instr)); @@ -734,8 +725,7 @@ static void deleteloop(Loop *loop) { while (1) { instr = body->firstPCode; -#line 1294 - CError_ASSERT(instr != NULL); + CError_ASSERT(1294, instr != NULL); if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) break; @@ -978,8 +968,7 @@ static void rewriteunknownloopwithBDNZ(Loop *loop) { while (1) { instr = loop->body->firstPCode; -#line 1857 - CError_ASSERT(instr); + CError_ASSERT(1857, instr); if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) break; @@ -1452,8 +1441,7 @@ void changearraytoregisters(void) { floatCounter -= best->elementCount; } -#line 2394 - CError_ASSERT(intCounter <= 8 && floatCounter <= 8); + CError_ASSERT(2394, intCounter <= 8 && floatCounter <= 8); if (!arrays) return; @@ -1522,8 +1510,7 @@ void changearraytoregisters(void) { newInstr = makepcode(PC_FMR, reg, reg2); break; default: -#line 2494 - CError_FATAL(); + CError_FATAL(2494); break; } diff --git a/compiler_and_linker/unsorted/MachO.c b/compiler_and_linker/unsorted/MachO.c index e69de29..a0e11ae 100644 --- a/compiler_and_linker/unsorted/MachO.c +++ b/compiler_and_linker/unsorted/MachO.c @@ -0,0 +1,878 @@ +#include "compiler/MachO.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "cos.h" + +static MachOSegment *FirstSeg; +static MachOSegment *LastSeg; +static UInt32 SectNum; +static UInt32 SymNum; +static UInt32 NumStabs; +static UInt32 ilocalsym; +static UInt32 nlocalsym; +static UInt32 iextdefsym; +static UInt32 nextdefsym; +static UInt32 iundefsym; +static UInt32 nundefsym; +static MachOSymbol *FirstSym; +static MachOSymbol *LastSym; +static MachOSymbol *FirstStab; +static MachOSymbol *LastStab; +static UInt32 FileOffset; +static UInt32 VmAddr; +static GList ObjFile; +static SInt32 SymPad; +static UInt32 CodeSize; +static UInt32 IdataSize; +static UInt32 UdataSize; +static GList IndirectSymbolTable; +static GList StringTable; +static UInt32 IndirectSymbolTableOffset; + +void MachO_Setup(void) { + FirstSeg = LastSeg = NULL; + FirstSym = LastSym = NULL; + FirstStab = LastStab = NULL; + + SectNum = 0; + SymNum = 0; + NumStabs = 0; + + ilocalsym = -1; + nlocalsym = 0; + + iextdefsym = -1; + nextdefsym = 0; + + iundefsym = -1; + nundefsym = 0; + + InitGList(&IndirectSymbolTable, 256); + InitGList(&StringTable, 4096); + AppendGListByte(&StringTable, 0); +} + +static UInt32 GetSectVMAddr(UInt32 id) { + MachOSegment *segment; + MachOSection *section; + + for (segment = FirstSeg; segment; segment = segment->next) { + for (section = segment->firstSection; section; section = section->next) { + if (section->num == id) + return section->section.addr; + } + } + + return 0; +} + +static UInt32 AllocateForLoadCommands(void) { + UInt32 ncmds = 0; + MachOSegment *segment; + MachOSection *section; + + for (segment = FirstSeg; segment; segment = segment->next) { + FileOffset += sizeof(struct segment_command); + segment->cmd.cmdsize += sizeof(struct segment_command); + ncmds++; + + for (section = segment->firstSection; section; section = section->next) { + segment->cmd.cmdsize += sizeof(struct section); + FileOffset += sizeof(struct section); + } + } + + return ncmds; +} + +static UInt32 AlignModulus[] = { + 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800 +}; + +static void AllocateAddresses(void) { + MachOSegment *segment; + MachOSection *section; + UInt32 pad; + + for (segment = FirstSeg; segment; segment = segment->next) { + segment->cmd.vmaddr = VmAddr; + segment->cmd.fileoff = FileOffset; + + for (section = segment->firstSection; section; section = section->next) { + if (section->glist.size) + section->section.size = section->glist.size; + + pad = AlignModulus[section->section.align] - (VmAddr % AlignModulus[section->section.align]); + pad %= AlignModulus[section->section.align]; + + VmAddr += pad; + section->section.addr = VmAddr; + VmAddr += section->section.size; + + FileOffset += pad; + if (section->glist.size) { + section->section.offset = FileOffset; + FileOffset += section->glist.size; + } else { + section->section.offset = FileOffset; + } + + if (!strncmp(section->section.segname, "__TEXT", 6)) { + CodeSize += section->section.size; + } else { + if (section->glist.size) + IdataSize += section->section.size; + else + UdataSize += section->section.size; + } + } + + segment->cmd.filesize = FileOffset - segment->cmd.fileoff; + segment->cmd.vmsize = VmAddr - segment->cmd.vmaddr; + } +} + +static void ApplyRelocs(void) { + MachOSegment *segment; + MachOSection *section; + MachOReloc *reloc; + enum reloc_type_ppc pairType; + UInt32 pairValue; + UInt32 opMask; + UInt32 argMask; + UInt32 value; + UInt32 *ptr; + + for (segment = FirstSeg; segment; segment = segment->next) { + for (section = segment->firstSection; section; section = section->next) { + for (reloc = section->firstReloc; reloc; reloc = reloc->next) { + if (reloc->is_extern) { + opMask = 0xFFFFFFFF; + argMask = 0; + value = 0; + switch (reloc->reltype) { + case PPC_RELOC_HI16: + case PPC_RELOC_LO16: + case PPC_RELOC_HA16: + pairValue = 0; + pairType = reloc->reltype; + break; + } + } else if (reloc->reltype == PPC_RELOC_PAIR) { + if (reloc->value != 0xFFFFFF) { + value = pairValue - (reloc->value + section->section.addr); + value += reloc->address; + } else { + value = pairValue + reloc->address; + } + switch (pairType) { + case PPC_RELOC_HI16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value >>= 16; + break; + case PPC_RELOC_HA16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + if (value & 0x8000) + value += 0x10000; + value >>= 16; + break; + case PPC_RELOC_LO16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = value & 0xFFFF; + break; + case PPC_RELOC_HI16_SECTDIFF: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value >>= 16; + break; + case PPC_RELOC_HA16_SECTDIFF: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + if (value & 0x8000) + value += 0x10000; + value >>= 16; + break; + case PPC_RELOC_LO16_SECTDIFF: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = value & 0xFFFF; + break; + case PPC_RELOC_SECTDIFF: + opMask = 0; + argMask = 0xFFFFFFFF; + break; + default: + CError_FATAL(388); + } + } else { + value = GetSectVMAddr(reloc->value); + switch (reloc->reltype) { + case PPC_RELOC_VANILLA: + opMask = 0; + argMask = 0xFFFFFFFF; + break; + case PPC_RELOC_BR14: + opMask = 0xFFFF0003; + argMask = 0xFFFC; + break; + case PPC_RELOC_BR24: + opMask = 0xFC000003; + argMask = 0x3FFFFFC; + break; + case PPC_RELOC_LO14: + opMask = 0xFFFF0003; + argMask = 0xFFFC; + break; + case PPC_RELOC_HI16: + case PPC_RELOC_HA16: + case PPC_RELOC_LO16: + case PPC_RELOC_HI16_SECTDIFF: + case PPC_RELOC_HA16_SECTDIFF: + case PPC_RELOC_LO16_SECTDIFF: + case PPC_RELOC_SECTDIFF: + // first half of a pair + opMask = 0xFFFF0000; + argMask = 0xFFFF; + pairValue = value; + pairType = reloc->reltype; + value = 0; + break; + case PPC_RELOC_PB_LA_PTR: + CError_FATAL(428); + break; + default: + CError_FATAL(432); + } + } + + if (reloc->reltype != PPC_RELOC_PAIR) + ptr = (UInt32 *) ((*section->glist.data) + reloc->address); + + if (reloc->is_pcrel) { + if (!reloc->is_extern) + *ptr = (*ptr & opMask) | (argMask & (value - (reloc->address + section->section.addr) + (*ptr & argMask))); + } else { + if (reloc->reltype == PPC_RELOC_PAIR) + *ptr = (*ptr & opMask) | (value & argMask); + else + *ptr = (*ptr & opMask) | (argMask & (value + (*ptr & argMask))); + } + } + } + } +} + +static void AllocForRelocs(void) { + MachOSegment *segment; + MachOSection *section; + + for (segment = FirstSeg; segment; segment = segment->next) { + for (section = segment->firstSection; section; section = section->next) { + if (section->section.nreloc) { + section->section.reloff = FileOffset; + FileOffset += section->section.nreloc * 8; + } + } + } +} + +static void WriteSegLoadCommands(void) { + MachOSegment *segment; + MachOSection *section; + + for (segment = FirstSeg; segment; segment = segment->next) { + AppendGListData(&ObjFile, &segment->cmd, sizeof(segment->cmd)); + for (section = segment->firstSection; section; section = section->next) + AppendGListData(&ObjFile, §ion->section, sizeof(section->section)); + } +} + +static void WriteSymtabLoadCommand(void) { + struct symtab_command cmd; + UInt32 total; + + cmd.cmd = LC_SYMTAB; + cmd.cmdsize = sizeof(cmd); + cmd.symoff = FileOffset; + total = SymNum + NumStabs; + cmd.nsyms = total; + FileOffset += total * sizeof(struct nlist); + cmd.stroff = FileOffset; + cmd.strsize = StringTable.size; + + AppendGListData(&ObjFile, &cmd, sizeof(cmd)); +} + +static void WriteDynamicSymtabLoadCommand(void) { + struct dysymtab_command cmd; + + if (!nlocalsym) + ilocalsym = 0; + if (!nextdefsym) + iextdefsym = ilocalsym + nlocalsym; + if (!nundefsym) + iundefsym = iextdefsym + nextdefsym; + + ilocalsym += NumStabs; + iextdefsym += NumStabs; + iundefsym += NumStabs; + + CError_ASSERT(644, (ilocalsym + nlocalsym) <= (SymNum + NumStabs)); + + CError_ASSERT(648, (iextdefsym + nextdefsym) <= (SymNum + NumStabs)); + + CError_ASSERT(652, (iundefsym + nundefsym) <= (SymNum + NumStabs)); + + cmd.cmd = LC_DYSYMTAB; + cmd.cmdsize = sizeof(cmd); + + cmd.ilocalsym = ilocalsym; + cmd.nlocalsym = nlocalsym; + cmd.iextdefsym = iextdefsym; + cmd.nextdefsym = nextdefsym; + cmd.iundefsym = iundefsym; + cmd.nundefsym = nundefsym; + + cmd.tocoff = 0; + cmd.ntoc = 0; + cmd.modtaboff = 0; + cmd.nmodtab = 0; + cmd.extrefsymoff = 0; + cmd.nextrefsyms = 0; + cmd.indirectsymoff = IndirectSymbolTableOffset; + cmd.nindirectsyms = IndirectSymbolTable.size / 4; + cmd.extreloff = 0; + cmd.nextrel = 0; + cmd.locreloff = 0; + cmd.nlocrel = 0; + + AppendGListData(&ObjFile, &cmd, sizeof(cmd)); +} + +static void WriteSectionData(void) { + MachOSegment *segment; + MachOSection *section; + UInt32 pad; + + VmAddr = 0; + + for (segment = FirstSeg; segment; segment = segment->next) { + for (section = segment->firstSection; section; section = section->next) { + pad = AlignModulus[section->section.align] - (VmAddr % AlignModulus[section->section.align]); + pad %= AlignModulus[section->section.align]; + + while (pad) { + AppendGListByte(&ObjFile, 0); + VmAddr++; + FileOffset++; + pad--; + } + + if (section->glist.size) { + CError_ASSERT(711, ObjFile.size == section->section.offset); + + COS_LockHandle(section->glist.data); + AppendGListData(&ObjFile, *section->glist.data, section->glist.size); + COS_UnlockHandle(section->glist.data); + + VmAddr += section->glist.size; + FreeGList(§ion->glist); + } else { + VmAddr += pad + section->section.size; + } + } + } +} + +static void WriteRelocs(void) { + MachOSegment *segment; + MachOSection *section; + MachOReloc *reloc; + enum reloc_type_ppc pairType; + UInt32 pairValue; + SInt32 scatterFlag; + UInt32 combo; + + static char length_code[] = { + 0, 0, 1, 1, 2 + }; + + pairType = 0; + pairValue = 0; + scatterFlag = 0; + + for (segment = FirstSeg; segment; segment = segment->next) { + for (section = segment->firstSection; section; section = section->next) { + for (reloc = section->firstReloc; reloc; reloc = reloc->next) { + if (reloc->is_extern) + reloc->value += NumStabs; + + switch (reloc->reltype) { + case PPC_RELOC_LO16: + case PPC_RELOC_HA16: + case PPC_RELOC_LO14: + pairType = reloc->reltype; + if (reloc->is_extern) { + pairValue = 0; + } else { + pairValue = reloc->next->address + GetSectVMAddr(reloc->value); + } + case PPC_RELOC_VANILLA: + case PPC_RELOC_BR14: + case PPC_RELOC_BR24: + case PPC_RELOC_HI16: + case PPC_RELOC_PB_LA_PTR: + AppendGListLong(&ObjFile, reloc->address); + AppendGListLong(&ObjFile, + (reloc->value << 8) | + (reloc->is_pcrel << 7) | + (length_code[reloc->length] << 5) | + (reloc->is_extern << 4) | + reloc->reltype + ); + break; + case PPC_RELOC_PAIR: + switch (pairType) { + case PPC_RELOC_HI16: + case PPC_RELOC_HA16: + scatterFlag = 0; + reloc->address = pairValue & 0xFFFF; + break; + case PPC_RELOC_LO16: + scatterFlag = 0; + reloc->address = pairValue >> 16; + break; + case PPC_RELOC_HI16_SECTDIFF: + case PPC_RELOC_HA16_SECTDIFF: + scatterFlag = R_SCATTERED; + reloc->value += section->section.addr; + pairValue -= reloc->value; + reloc->address = pairValue & 0xFFFF; + break; + case PPC_RELOC_LO16_SECTDIFF: + scatterFlag = R_SCATTERED; + reloc->value += section->section.addr; + pairValue -= reloc->value; + reloc->address = pairValue >> 16; + break; + default: + CError_FATAL(891); + reloc->address = 0; + break; + } + + pairValue = 0; + pairType = 0; + if (scatterFlag) { + AppendGListLong(&ObjFile, + scatterFlag | + (reloc->is_pcrel << 30) | + (length_code[reloc->length] << 28) | + (reloc->reltype << 24) | + reloc->address + ); + AppendGListLong(&ObjFile, reloc->value); + } else { + combo = + (reloc->value << 8) | + (reloc->is_pcrel << 7) | + (length_code[reloc->length] << 5) | + reloc->reltype; + AppendGListLong(&ObjFile, reloc->address); + AppendGListLong(&ObjFile, combo); + } + break; + case PPC_RELOC_SECTDIFF: + case PPC_RELOC_HI16_SECTDIFF: + case PPC_RELOC_LO16_SECTDIFF: + case PPC_RELOC_HA16_SECTDIFF: + // build scattered relocation + reloc->value = reloc->next->address + GetSectVMAddr(reloc->value); + pairType = reloc->reltype; + pairValue = reloc->value; + AppendGListLong(&ObjFile, + R_SCATTERED | + (reloc->is_pcrel << 30) | + (length_code[reloc->length] << 28) | + (reloc->reltype << 24) | + reloc->address + ); + AppendGListLong(&ObjFile, reloc->value); + break; + + default: + CError_FATAL(930); + } + } + } + } +} + +static void WriteIndirectSymbolTable(void) { + UInt32 i; + UInt32 *ptr; + + while (SymPad) { + AppendGListByte(&ObjFile, 0); + SymPad--; + } + + COS_LockHandle(IndirectSymbolTable.data); + ptr = (UInt32 *) *IndirectSymbolTable.data; + for (i = 0; i < MachO_NumIndirectSym(); ptr++, i++) + *ptr += NumStabs; + + AppendGListData(&ObjFile, *IndirectSymbolTable.data, IndirectSymbolTable.size); + COS_UnlockHandle(IndirectSymbolTable.data); + FreeGList(&IndirectSymbolTable); +} + +static void WriteSymbolTable(void) { + MachOSymbol *symbol; + struct nlist nlist; + + if (FirstStab) { + LastStab->next = FirstSym; + FirstSym = FirstStab; + } + + for (symbol = FirstSym; symbol; symbol = symbol->next) { + nlist.n_strx = symbol->data.u.strx; + nlist.n_type = symbol->data.type; + if (symbol->data.section) + nlist.n_sect = symbol->data.section->num; + else + nlist.n_sect = 0; + nlist.n_desc = symbol->data.desc; + + if ( + symbol->data.type == N_STSYM || + symbol->data.type == N_FUN || + symbol->data.type == N_LCSYM || + symbol->data.type == N_SLINE || + symbol->data.type == N_SO || + symbol->data.type == N_SOL || + symbol->data.type == N_ENTRY || + symbol->data.type == N_ECOML || + (symbol->data.type & N_TYPE) == N_SECT + ) + { + if (symbol->data.section) + symbol->data.value += symbol->data.section->section.addr; + else + CError_FATAL(1010); + } + + nlist.n_value = symbol->data.value; + AppendGListData(&ObjFile, &nlist, sizeof(nlist)); + } +} + +static void WriteStringTable(void) { + COS_LockHandle(StringTable.data); + AppendGListData(&ObjFile, *StringTable.data, StringTable.size); + COS_UnlockHandle(StringTable.data); +} + +void MachO_Finish(void) { + struct mach_header hdr; + + CodeSize = 0; + IdataSize = UdataSize = 0; + VmAddr = 0; + FileOffset = sizeof(hdr); + + hdr.ncmds = AllocateForLoadCommands(); + + FileOffset += 24; // what am I? + hdr.ncmds++; + + if (copts.codegen_dynamic) { + FileOffset += 80; // what am I? + hdr.ncmds++; + } + + hdr.sizeofcmds = FileOffset - sizeof(hdr); + + AllocateAddresses(); + ApplyRelocs(); + AllocForRelocs(); + + SymPad = (4 - (FileOffset & 3)) & 3; + FileOffset += SymPad; + IndirectSymbolTableOffset = 0; + + if (IndirectSymbolTable.size > 0) { + IndirectSymbolTableOffset = FileOffset; + FileOffset += IndirectSymbolTable.size; + } + + InitGList(&ObjFile, 4096); + + hdr.magic = MH_MAGIC; + hdr.cputype = CPU_TYPE_POWERPC; + hdr.cpusubtype = CPU_SUBTYPE_MC98000_ALL; + hdr.filetype = MH_OBJECT; + hdr.flags = 0; + AppendGListData(&ObjFile, &hdr, sizeof(hdr)); + + WriteSegLoadCommands(); + WriteSymtabLoadCommand(); + if (copts.codegen_dynamic) + WriteDynamicSymtabLoadCommand(); + WriteSectionData(); + WriteRelocs(); + WriteIndirectSymbolTable(); + WriteSymbolTable(); + WriteStringTable(); + + COS_ResizeHandle(ObjFile.data, ObjFile.size); + + cparamblkptr->objectDataHandle = ObjFile.data; + cparamblkptr->objectdata.codesize = CodeSize; + cparamblkptr->objectdata.udatasize = UdataSize; + cparamblkptr->objectdata.idatasize = IdataSize; +} + +void MachO_Cleanup(void) { + if (StringTable.data) + FreeGList(&StringTable); + if (IndirectSymbolTable.data) + FreeGList(&IndirectSymbolTable); +} + +MachOSegment *MachO_CreateSegment(char *segname, int maxprot, int initprot, UInt32 flags) { + MachOSegment *segment = galloc(sizeof(MachOSegment)); + + memset(&segment->cmd, 0, sizeof(segment->cmd)); + segment->cmd.cmd = LC_SEGMENT; + strncpy(segment->cmd.segname, segname, sizeof(segment->cmd.segname)); + segment->cmd.maxprot = maxprot; + segment->cmd.initprot = initprot; + segment->cmd.flags = flags; + + segment->firstSection = segment->lastSection = NULL; + segment->next = NULL; + if (FirstSeg == NULL) + FirstSeg = segment; + else + LastSeg->next = segment; + LastSeg = segment; + + return segment; +} + +MachOSection *MachO_CreateSection(MachOSegment *segment, char *segname, char *sectname, UInt32 align, UInt32 flags, UInt32 sectionID) { + MachOSection *section; + UInt32 alignConv; + + alignConv = 0; + while (!(align & 1)) { + align >>= 1; + alignConv++; + } + + section = galloc(sizeof(MachOSection)); + memset(section, 0, sizeof(MachOSection)); + + strncpy(section->section.segname, segname, sizeof(section->section.segname)); + strncpy(section->section.sectname, sectname, sizeof(section->section.sectname)); + section->section.align = alignConv; + section->section.flags = flags; + + section->num = ++SectNum; + section->id = sectionID; + + section->next = NULL; + if (segment->firstSection == NULL) + segment->firstSection = section; + else + segment->lastSection->next = section; + segment->lastSection = section; + + segment->cmd.nsects++; + + return section; +} + +GList *MachO_GetGList(MachOSection *section) { + if (!section->glist.data) + InitGList(§ion->glist, 256); + return §ion->glist; +} + +void MachO_SetSectionSize(void) { + // empty, unused, unknown args +} + +void MachO_Relocate(MachOSection *section, UInt32 address, UInt32 value, char length, char is_pcrel, Boolean is_extern, int reltype) { + MachOReloc *reloc; + + reloc = galloc(sizeof(MachOReloc)); + reloc->address = address; + reloc->value = value; + reloc->length = length; + reloc->is_pcrel = is_pcrel; + reloc->is_extern = is_extern; + reloc->reltype = reltype; + + reloc->next = NULL; + if (section->firstReloc == NULL) + section->firstReloc = reloc; + else + section->lastReloc->next = reloc; + section->lastReloc = reloc; + + section->section.nreloc++; +} + +static SInt32 DeclareString(char *str) { + SInt32 offset; + + if (str) { + offset = StringTable.size; + AppendGListID(&StringTable, str); + } else { + offset = 0; + } + + return offset; +} + +UInt32 MachO_DeclareSymbol(char *name, MachOSection *section, UInt32 value, Boolean isAbsolute, short type, short desc) { + MachOSymbol *symbol; + + symbol = galloc(sizeof(MachOSymbol)); + memset(symbol, 0, sizeof(MachOSymbol)); + + if (section) { + if (type) { + if (nextdefsym == 0) + iextdefsym = SymNum; + nextdefsym++; + } else { + if (nlocalsym == 0) + ilocalsym = SymNum; + nlocalsym++; + } + symbol->data.type = type | N_SECT; + symbol->data.section = section; + } else if (isAbsolute) { + symbol->data.type = type | N_ABS; + } else { + if (nundefsym == 0) + iundefsym = SymNum; + nundefsym++; + symbol->data.type = type & ~N_PEXT; + } + + symbol->data.value = value; + symbol->data.u.strx = DeclareString(name); + symbol->data.desc = desc; + symbol->index = SymNum++; + + if (FirstSym == NULL) + FirstSym = symbol; + else + LastSym->next = symbol; + LastSym = symbol; + + return symbol->index; +} + +void MachO_ReOrderSections(void) { + MachOSection *section; + MachOSegment *segment; + MachOSection *prev; + MachOSection *firstRemoved; + MachOSection *lastRemoved; + UInt32 counter; + + counter = 0; + for (segment = FirstSeg; segment; segment = segment->next) { + prev = NULL; + section = segment->firstSection; + firstRemoved = lastRemoved = NULL; + while (section) { + if (section->section.size && section->glist.data == NULL && section != segment->firstSection) { + // detach this section + if (prev) + prev->next = section->next; + else + segment->firstSection = section->next; + + if (section == segment->lastSection) + segment->lastSection = prev; + + section->next = NULL; + + // add it to the list to be pushed to the end + if (firstRemoved == NULL) + firstRemoved = section; + else + lastRemoved->next = section; + lastRemoved = section; + + // continue iterating + if (prev) + section = prev->next; + else + section = segment->firstSection; + } else { + prev = section; + section = section->next; + } + } + + // attach the other sections + if (firstRemoved) { + if (segment->firstSection == NULL) + segment->firstSection = firstRemoved; + else + segment->lastSection->next = firstRemoved; + segment->lastSection = lastRemoved; + } + + // renumber them all + for (section = segment->firstSection; section; section = section->next) + section->num = ++counter; + } +} + +void MachO_AddIndirectSymbol(SInt32 symbol) { + CError_ASSERT(1577, symbol >= 0); + + AppendGListLong(&IndirectSymbolTable, symbol); +} + +UInt32 MachO_NumIndirectSym(void) { + return IndirectSymbolTable.size / 4; +} + +SInt32 MachO_OutputStab(SymbolData *data, SInt32 strIndex) { + MachOSymbol *symbol; + + symbol = galloc(sizeof(MachOSymbol)); + memset(symbol, 0, sizeof(MachOSymbol)); + if (strIndex == -1) + data->u.strx = DeclareString(data->u.name); + else + data->u.strx = strIndex; + + memcpy(&symbol->data, data, sizeof(SymbolData)); + + if (FirstStab == NULL) + FirstStab = symbol; + else + LastStab->next = symbol; + LastStab = symbol; + NumStabs++; + + return data->u.strx; +} diff --git a/compiler_and_linker/unsorted/ObjGenMachO.c b/compiler_and_linker/unsorted/ObjGenMachO.c index e69de29..890c06e 100644 --- a/compiler_and_linker/unsorted/ObjGenMachO.c +++ b/compiler_and_linker/unsorted/ObjGenMachO.c @@ -0,0 +1,1810 @@ +#include "compiler/ObjGenMachO.h" +#include "compiler/CError.h" +#include "compiler/CInit.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/uDump.h" +#include "compiler/GenStabs.h" +#include "compiler/IrOptimizer.h" +#include "compiler/MachO.h" +#include "compiler/PCodeListing.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" +#include "cos.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct Reloc { + MachOSection *section; + SInt32 offset; + SInt32 relocID; + SInt32 picOffset; + struct Reloc *next; + RelocType relocType; + MWReloc mwRelType; +} Reloc; + +typedef struct { + Section x0; + Section x1; + char *segname; + char *sectname; + UInt32 align; + UInt32 flags; +} DefSectionInfo; + +static DefSectionInfo def_section_info[] = { + SECT_DEFAULT, SECT_DEFAULT, "", "", 1, S_REGULAR, + SECT_TEXT, SECT_TEXT_COALESCE, "__TEXT", "__text", 4, S_ATTR_SOME_INSTRUCTIONS, + SECT_DATA, SECT_DATA_COALESCE, "__DATA", "__data", 8, S_REGULAR, + SECT_UDATA, SECT_UDATA_COALESCE, "__DATA", "__bss", 8, S_ZEROFILL, + SECT_DATA_FAR, 0, "__DATA", "__fdata", 8, S_REGULAR, + SECT_DATA_NEAR, 0, "__DATA", "__ndata", 8, S_REGULAR, + SECT_INIT, 0, "__INIT", "__init", 4, S_REGULAR, + SECT_OBJC_CAT_CLS_METH, 0, "__OBJC", "__cat_cls_meth", 4, S_REGULAR, + SECT_OBJC_CAT_INST_METH, 0, "__OBJC", "__cat_inst_meth", 4, S_REGULAR, + SECT_OBJC_STRING_OBJECT, 0, "__OBJC", "__string_object", 1, S_REGULAR, + SECT_OBJC_CSTRING_OBJECT, 0, "__OBJC", "__cstring_object", 1, S_REGULAR, + SECT_OBJC_MESSAGE_REFS, 0, "__OBJC", "__message_refs", 4, S_LITERAL_POINTERS, + SECT_OBJC_SEL_FIXUP, 0, "__OBJC", "__sel_fixup", 4, S_REGULAR, + SECT_OBJC_CLS_REFS, 0, "__OBJC", "__cls_refs", 4, S_LITERAL_POINTERS, + SECT_OBJC_CLASS, 0, "__OBJC", "__class", 4, S_REGULAR, + SECT_OBJC_META_CLASS, 0, "__OBJC", "__meta_class", 4, S_REGULAR, + SECT_OBJC_CLS_METH, 0, "__OBJC", "__cls_meth", 4, S_REGULAR, + SECT_OBJC_INST_METH, 0, "__OBJC", "__inst_meth", 4, S_REGULAR, + SECT_OBJC_PROTOCOL, 0, "__OBJC", "__protocol", 4, S_REGULAR, + SECT_OBJC_CLASS_NAMES, 0, "__OBJC", "__class_names", 4, S_CSTRING_LITERALS, + SECT_OBJC_METH_VAR_TYPES, 0, "__OBJC", "__meth_var_types", 4, S_CSTRING_LITERALS, + SECT_OBJC_METH_VAR_NAMES, 0, "__OBJC", "__meth_var_names", 4, S_CSTRING_LITERALS, + SECT_OBJC_CATEGORY, 0, "__OBJC", "__category", 4, S_REGULAR, + SECT_OBJC_CLASS_VARS, 0, "__OBJC", "__class_vars", 4, S_REGULAR, + SECT_OBJC_INSTANCE_VARS, 0, "__OBJC", "__instance_vars", 4, S_REGULAR, + SECT_OBJC_MODULE_INFO, 0, "__OBJC", "__module_info", 4, S_REGULAR, + SECT_OBJC_MSYMBOLS, 0, "__OBJC", "__symbols", 4, S_REGULAR, + SECT_TEXT_CSTRING, SECT_TEXT_CSTRING, "__TEXT", "__cstring", 4, S_CSTRING_LITERALS, + SECT_MW_EX_TABLE, SECT_MW_EX_TABLE, "__DATA", "__coalsc_MXCPTTB", 4, S_COALESCED | S_ATTR_NO_TOC, + SECT_MW_EX_TABLE_INDEX, SECT_MW_EX_TABLE_INDEX, "__DATA", "__mwexceptionidx", 4, S_COALESCED | S_ATTR_NO_TOC, + SECT_MW_SWITCH, SECT_MW_SWITCH, "__DATA", "__mwswitch", 4, S_REGULAR, + SECT_8BYTE_LITERALS, SECT_8BYTE_LITERALS, "__TEXT", "__literal8", 8, S_8BYTE_LITERALS, + SECT_4BYTE_LITERALS, SECT_4BYTE_LITERALS, "__TEXT", "__literal4", 4, S_4BYTE_LITERALS, + SECT_MOD_INIT_FUNC, SECT_MOD_INIT_FUNC, "__DATA", "__mod_init_func", 4, S_MOD_INIT_FUNC_POINTERS, + SECT_CONST, SECT_CONST, "__TEXT", "__const", 4, S_REGULAR, + SECT_CONST_PTR, SECT_CONST_PTR, "__TEXT", "__const", 4, S_REGULAR, + SECT_NONLAZY_PTRS, SECT_NONLAZY_PTRS, "__DATA", "__nl_symbol_ptr", 4, S_NON_LAZY_SYMBOL_POINTERS, + SECT_COMMON_VARS, SECT_COMMON_VARS, NULL, NULL, 0, S_REGULAR, + SECT_16BYTE_LITERALS, SECT_16BYTE_LITERALS, "__DATA", "__literal16", 16, S_REGULAR, + SECT_TEXT_COALESCE, SECT_TEXT_COALESCE, "__TEXT", "__coalesced_text", 4, S_COALESCED | S_ATTR_SOME_INSTRUCTIONS, + SECT_DATA_COALESCE, SECT_DATA_COALESCE, "__DATA", "__coalesced_data", 8, S_COALESCED, + SECT_UDATA_COALESCE, SECT_UDATA_COALESCE, "__DATA", "__coalesced_bss", 8, S_COALESCED, + SECT_CONST_COALESCE, SECT_CONST_COALESCE, "__TEXT", "__coalesce_const", 4, S_COALESCED, + SECT_CONST_PTR_COALESCE, SECT_CONST_PTR_COALESCE, "__DATA", "__coalesce_const", 4, S_COALESCED +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +Boolean declare_readonly; +SInt32 symdeclend; +SInt32 symdecloffset; +SInt32 nexttypeid; +GList symtypemodule; +SInt32 last_base_offset[N_SECTIONS]; +static SInt32 RelocIndex; +static MachOSegment *TheSegment; +MachOSection *Sections[N_SECTIONS]; +static MachOSection *StubSect; +static MachOSection *LazySymbolSect; +static MachOSection *NonLazySymbolSect; +static GList RelocData; +static Reloc *FirstReloc; +static Reloc *LastReloc; +Section last_function_sect_id; +MachOSection *last_function_sect; +SInt32 pic_base_offset; + +#define RELOC_DATA(_id) (((RelocDataT *) (*RelocData.data))[(_id)]) + +static Section SegmentForceCreate = SECT_TEXT; + +// forward decls +static void CreateTheSegment(void); +static void SymContainedVars(void); +static void AppendGListZeros(GList *glist, SInt32 size); + +static Section ObjGen_CheckCoalesceSection(Object *object) { + Section s; + + if ( + !CParser_HasInternalLinkage(object) && + (object->qual & (Q_20000 | Q_OVERLOAD)) && + (s = def_section_info[object->section].x1) != SECT_DEFAULT + ) + return s; + else + return object->section; +} + +static MachOSection *ObjGen_GetSection(Section section) { + CError_ASSERT(360, section != SECT_COMMON_VARS); + + if (!Sections[section]) { + DefSectionInfo *info = def_section_info + section; + Sections[section] = MachO_CreateSection( + TheSegment, + info->segname, + info->sectname, + info->align, + info->flags, + section); + } + + return Sections[section]; +} + +static UInt32 AlignTo_Section(MachOSection *section, UInt32 value) { + UInt32 conv; + UInt32 work; + + if (value < (1 << section->section.align)) + return 1 << section->section.align; + + conv = 0; + work = 1; + while (work < value) { + work = work * 2; + conv++; + } + + section->section.align = conv; + return work; +} + +static void updatesectreloc(RelocDataT *r, MachOSection *section, UInt32 a) { + CError_ASSERT(396, r->x3 == 0); + + r->type = RT_0; + r->section = section; + r->x4 = a; +} + +SInt32 ObjGen_MakeSectReloc(MachOSection *section) { + RelocDataT r = {0}; + r.x18 = -1; + updatesectreloc(&r, section, section->glist.data ? section->glist.size : section->section.size); + AppendGListData(&RelocData, &r, sizeof(r)); + + return RelocIndex++; +} + +static char ObjGen_ComputePrivFlag(UInt8 objectFlags) { + switch (copts.x06) { + case 0: + case 1: + if ( + (objectFlags & OBJECT_FLAGS_UNUSED) && + (objectFlags & OBJECT_FLAGS_2) && + !(objectFlags & OBJECT_FLAGS_4) + ) + return 0; + return 1; + case 3: + case 4: + if ((objectFlags & OBJECT_FLAGS_10) == OBJECT_FLAGS_10) + return 1; + if ((objectFlags & OBJECT_FLAGS_40) == OBJECT_FLAGS_40) + return 0; + if ( + (objectFlags & OBJECT_FLAGS_UNUSED) && + (objectFlags & OBJECT_FLAGS_2) && + !(objectFlags & OBJECT_FLAGS_4) + ) + return 0; + return 1; + case 2: + return 0; + default: + return 1; + } +} + +SInt32 ObjGen_GetHashNodeRelocID(Object *object, MachOSection *section, SInt32 value) { + HashNameNode *name; + HashNameNode *name2; + RelocDataT r; + RelocDataT *other_rd; + ObjectList *list; + SInt32 tmp; + + memclrw(&r, sizeof(r)); + r.x18 = -1; + + if (object->datatype == DNONLAZYPTR) + name = object->name; + else + name = CMangler_GetLinkName(object); + + if (value < 0) + return name->id; + + if (name->id < 0) { + if (section) { + if (Sections[SECT_COMMON_VARS] && section == Sections[SECT_COMMON_VARS]) { + CError_FATAL(489); + } else { + name->id = ObjGen_MakeSectReloc(section); + } + } else if (object->datatype == DNONLAZYPTR) { + CError_ASSERT(497, object->u.var.realObj != NULL); + name->id = RelocIndex; + + r.type = RT_3; + r.privFlag = ObjGen_ComputePrivFlag(object->flags); + r.name = name->name; + + AppendGListData(&RelocData, &r, sizeof(r)); + RelocIndex++; + ObjGen_GetHashNodeRelocID(object->u.var.realObj, NULL, 0); + } else if (value) { + object->section = SECT_COMMON_VARS; + name->id = RelocIndex; + + r.type = RT_4; + r.privFlag = ObjGen_ComputePrivFlag(object->flags); + r.name = name->name; + r.x4 = value; + + AppendGListData(&RelocData, &r, sizeof(r)); + RelocIndex++; + } else { + name->id = RelocIndex; + + r.type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; + r.x2 = 1; + r.privFlag = ObjGen_ComputePrivFlag(object->flags); + if (!CParser_HasInternalLinkage(object)) + r.x3 = (object->qual & (Q_20000 | Q_OVERLOAD)) > 0; + r.name = name->name; + r.x4 = value; + + AppendGListData(&RelocData, &r, sizeof(r)); + RelocIndex++; + } + } else if (section) { + other_rd = &RELOC_DATA(name->id); + other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); + if (!CParser_HasInternalLinkage(object) && (object->qual & (Q_20000 | Q_OVERLOAD))) { + other_rd->x3 = 1; + switch (other_rd->type) { + case RT_0: + CError_FATAL(548); + + other_rd->type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; + other_rd->x2 = 1; + other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); + other_rd->x18 = -1; + other_rd->name = name->name; + break; + case RT_1: + case RT_2: + case RT_5: + tmp = ObjGen_GetSectSize(section); + other_rd = &RELOC_DATA(name->id); + other_rd->section = section; + other_rd->x4 = tmp; + break; + default: + CError_FATAL(571); + break; + } + } else { + switch (other_rd->type) { + case RT_0: + CError_ASSERT(577, other_rd->section == section); + break; + case RT_2: + name2 = CMangler_GetLinkName(object); + for (list = toclist; list; list = list->next) { + if (name2->id == CMangler_GetLinkName(list->object)->id) { + SInt32 id = list->object->name->id; + list->object->section = SECT_CONST_PTR; + list->object->u.var.realObj = object; + other_rd = &RELOC_DATA(id); + if (other_rd->type == RT_3) { + other_rd->type = RT_6; + other_rd->x18 = name2->id; + } else if (other_rd->type != RT_6) { + CError_FATAL(602); + } + } + } + + for (tmp = 0; tmp < RelocIndex; tmp++) { + other_rd = &RELOC_DATA(tmp); + if (other_rd->type == RT_2 && !strcmp(name->name, other_rd->name)) { + name->id = tmp; + break; + } + } + + case RT_1: + case RT_5: + tmp = ObjGen_GetSectSize(section); + other_rd = &RELOC_DATA(name->id); + updatesectreloc(other_rd, section, tmp); + break; + + default: + CError_FATAL(626); + } + } + } else if (value) { + other_rd = &RELOC_DATA(name->id); + other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); + if (other_rd->type == RT_4) { + CError_ASSERT(635, value == other_rd->x4); + } else { + CError_ASSERT(639, other_rd->type == RT_2); + other_rd->type = RT_4; + other_rd->x4 = value; + } + } + + return name->id; +} + +static Boolean ObjGen_DeclareSymbol(Object *object, MachOSection *section, SInt32 value) { + HashNameNode *name; + RelocDataT r; + + if (object->name->name[0] == '@') + return 0; + + if (object->sclass == TK_STATIC) { + if (!strncmp(object->name->name, "L_OBJC_", 7) || !strncmp(object->name->name, "L_NSConst", 9)) + return 0; + } + + name = CMangler_GetLinkName(object); + memclrw(&r, sizeof(r)); + r.x18 = -1; + r.type = RT_7; + + if (!CParser_HasInternalLinkage(object)) { + if (object->datatype == DFUNC || object->datatype == DVFUNC) { + if (ObjGen_ComputePrivFlag(object->flags)) { + r.privFlag = 1; + r.x2 = 1; + } else { + r.privFlag = 0; + r.x2 = 1; + } + } else { + if (object->qual & Q_INLINE) { + r.privFlag = 1; + r.x2 = 1; + } else { + r.privFlag = 0; + r.x2 = 1; + } + } + } + + if (!CParser_HasInternalLinkage(object) && (object->qual & (Q_20000 | Q_OVERLOAD))) + r.x3 = 1; + + r.x4 = value; + r.section = section; + r.name = name->name; + + if (r.x3) { + r.type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; + if (name->id >= 0) { + RELOC_DATA(name->id) = r; + return 1; + } + } + + if (r.type == RT_7) { + AppendGListData(&RelocData, &r, sizeof(r)); + RelocIndex++; + r.type = RT_0; + } + + if (name->id < 0) + name->id = RelocIndex; + + AppendGListData(&RelocData, &r, sizeof(r)); + RelocIndex++; + + return 1; +} + +void ObjGen_Setup(void) { + int i; + + MachO_Setup(); + GenStab_Setup(); + declare_readonly = 0; + symtypemodule.data = NULL; + if (InitGList(&symtypemodule, 5000)) + CError_NoMem(); + + nexttypeid = -1; + pic_base_offset = 0; + last_function_sect = 0; + last_function_sect_id = SECT_DEFAULT; + + setupaddressing(); + + TheSegment = NULL; + + for (i = 0; i < N_SECTIONS; i++) { + Sections[i] = NULL; + last_base_offset[i] = 0; + CError_ASSERT(769, i == def_section_info[i].x0); + } + + RelocIndex = 0; + FirstReloc = NULL; + StubSect = NULL; + LazySymbolSect = NULL; + NonLazySymbolSect = NULL; + LastReloc = NULL; + + InitGList(&RelocData, 2800); + + CreateTheSegment(); + ObjGen_SrcBreakName(NULL, 0, 1); + IRO_Setup(); +} + +static void GenStubs(void) { + SInt32 i; + SInt32 rdCount; + SInt32 offset; + RelocDataT *rd; + + rdCount = RelocData.size / sizeof(RelocDataT); + for (i = 0; i < rdCount; i++) { + if (RELOC_DATA(i).type == RT_1 && RELOC_DATA(i).x3) { + if (StubSect == NULL) { + StubSect = MachO_CreateSection( + TheSegment, + "__TEXT", + copts.codegen_pic ? "__picsymbol_stub" : "__symbol_stub", + 4, + S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS, + -1); + MachO_GetGList(StubSect); + } + + if (LazySymbolSect == NULL) { + LazySymbolSect = MachO_CreateSection( + TheSegment, + "__DATA", + "__la_symbol_ptr", + 4, + S_LAZY_SYMBOL_POINTERS, + -2); + } + + offset = StubSect->glist.size; + rd = &RELOC_DATA(i); + rd->gapC = offset; + rd->sect10 = StubSect; + CodeGen_GenDynLinkStub(StubSect, LazySymbolSect, ObjGen_MakeSectReloc(LazySymbolSect)); + StubSect->section.reserved2 = StubSect->glist.size - offset; + } + } + + for (i = 0; i < rdCount; i++) { + if (RELOC_DATA(i).type == RT_1 && !RELOC_DATA(i).x3) { + if (StubSect == NULL) { + StubSect = MachO_CreateSection( + TheSegment, + "__TEXT", + copts.codegen_pic ? "__picsymbol_stub" : "__symbol_stub", + 4, + S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS, + -1); + MachO_GetGList(StubSect); + } + + if (LazySymbolSect == NULL) { + LazySymbolSect = MachO_CreateSection( + TheSegment, + "__DATA", + "__la_symbol_ptr", + 4, + S_LAZY_SYMBOL_POINTERS, + -2); + } + + offset = StubSect->glist.size; + rd = &RELOC_DATA(i); + rd->gapC = offset; + rd->sect10 = StubSect; + CodeGen_GenDynLinkStub(StubSect, LazySymbolSect, ObjGen_MakeSectReloc(LazySymbolSect)); + StubSect->section.reserved2 = StubSect->glist.size - offset; + } + } +} + +static void GenNonLazyPointers(void) { + ObjectList *list; // r31 + Object *object; // r30 + MachOSection *section; // r29 + SInt32 id; // r29, r27? + UInt32 offset; // r26 + RelocDataT *rd; // r26 + GList *gl; // r25 + SInt32 align; + SInt32 i; + + for (list = toclist; list; list = list->next) { + object = list->object; + + if (object->section == SECT_NONLAZY_PTRS) { + id = ObjGen_GetHashNodeRelocID(object, NULL, 0); + + CError_ASSERT(877, RELOC_DATA(id).type == RT_3); + + if (NonLazySymbolSect == NULL) { + NonLazySymbolSect = ObjGen_GetSection(SECT_NONLAZY_PTRS); + MachO_GetGList(NonLazySymbolSect); + } + + updatesectreloc(&RELOC_DATA(id), NonLazySymbolSect, NonLazySymbolSect->glist.size); + AppendGListLong(&NonLazySymbolSect->glist, 0); + } else if (object->section == SECT_CONST_PTR) { + id = ObjGen_GetHashNodeRelocID(object, NULL, 0); + + CError_ASSERT(901, RELOC_DATA(id).type == RT_6 || RELOC_DATA(id).type == RT_3); + + section = ObjGen_GetSection(object->section); + gl = MachO_GetGList(section); + offset = gl->size; + + align = AlignTo_Section(section, 4); + if ((offset % align) != 0) { + for (i = 0; i < (align - (offset % align)); i++) + AppendGListByte(gl, 0); + } + + rd = &RELOC_DATA(id); + updatesectreloc(rd, section, section->glist.size); + AppendGListLong(§ion->glist, 0); + + id = CMangler_GetLinkName(object)->id; + CError_ASSERT(940, RELOC_DATA(id).type == RT_0); + + ObjGen_Relocate(section, rd->x4, id, RT_4, MW_RELOC_0); + } else { + CError_FATAL(944); + } + } +} + +void ObjGen_DeclareFloatConst(Object *object) { + Section sectionID; + GList *gl; + + if (!TheSegment) + CreateTheSegment(); + + sectionID = object->section; + if (sectionID == SECT_DEFAULT) { + if (object->type->size == 4) + sectionID = SECT_4BYTE_LITERALS; + else + sectionID = SECT_8BYTE_LITERALS; + } + + ObjGen_GetHashNodeRelocID(object, ObjGen_GetSection(sectionID), 0); + + gl = MachO_GetGList(Sections[sectionID]); + if (object->type->size == 4) { + float f = object->u.data.u.floatconst->value; + AppendGListData(gl, &f, 4); + } else if (object->type->size == 8) { + double f = object->u.data.u.floatconst->value; + AppendGListData(gl, &f, 8); + } else { + CError_FATAL(998); + } +} + +void ObjGen_DeclareVectorConst(Object *object) { + Section sectionID; + GList *gl; + + if (!TheSegment) + CreateTheSegment(); + + sectionID = SECT_16BYTE_LITERALS; + ObjGen_GetHashNodeRelocID(object, ObjGen_GetSection(sectionID), 0); + + gl = MachO_GetGList(Sections[sectionID]); + if (object->type->size == 16) { + MWVector128 vec = *object->u.data.u.vector128const; + AppendGListData(gl, &vec, 16); + } else { + CError_FATAL(1034); + } +} + +void ObjGen_Finish(void) { + UInt32 symIndex; + SInt32 rdCount; + RelocDataT *rdArray; + SInt32 rdIndex; + RelocDataT *rd; + Reloc *reloc; + ObjectList *objlist; + SInt32 value; + int flags; + int desc; + enum reloc_type_ppc nextRelType; + UInt32 opMask; + UInt32 argMask; + + if (copts.isGeneratingDebugInfo) + GenStab_SourceFile(""); + + CInit_DeclarePooledStrings(); + DeclarePooledConstants(); + + if (copts.codegen_dynamic) { + GenStubs(); + GenNonLazyPointers(); + } + + MachO_ReOrderSections(); + COS_LockHandle(RelocData.data); + + rdCount = RelocData.size / sizeof(RelocDataT); + + rdArray = &RELOC_DATA(0); + for (rdIndex = 0; rdIndex < (RelocData.size / sizeof(RelocDataT)); rdIndex++) { + rd = rdArray + rdIndex; + if (rd->type == RT_7 && rd->x2 == 0) { + symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, 0, 0); + rd->type = RT_5; + rd->x18 = symIndex; + } + } + + rdArray = &RELOC_DATA(0); + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = rdArray + rdIndex; + if (rd->type == RT_7 && rd->x2 != 0) { + flags = N_EXT; + desc = 0; + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 0; + } + + symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); + rd->type = RT_5; + rd->x18 = symIndex; + } + } + + if (copts.codegen_dynamic && StubSect) + StubSect->section.reserved1 = MachO_NumIndirectSym(); + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = &RELOC_DATA(rdIndex); + if (rd->type == RT_1 && rd->x3 != 0) { + flags = N_EXT; + desc = 0; + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 0; + } + + symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); + rd->x18 = symIndex; + + if (copts.codegen_dynamic && rd->sect10 == StubSect) { + MachOSection *tmpSection; + UInt32 tmpValue; + + MachO_AddIndirectSymbol(symIndex); + + tmpSection = rd->section; + tmpValue = rd->x4; + rd->section = rd->sect10; + rd->x4 = rd->gapC; + rd->sect10 = tmpSection; + rd->gapC = tmpValue; + } else { + rd->x2 = 1; + rd->type = RT_5; + } + } + } + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = rdArray + rdIndex; + if (rd->type == RT_2 && rd->x3 != 0) { + flags = N_EXT; + desc = 0; + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 0; + } + + symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); + rd->type = RT_5; + rd->x18 = symIndex; + } + } + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = rdArray + rdIndex; + if (rd->type == RT_4) { + flags = N_EXT; + desc = 0; + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 4; // REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY? + } + + symIndex = MachO_DeclareSymbol(rd->name, NULL, rd->x4, 0, flags, desc); + rd->type = RT_5; + rd->x18 = symIndex; + } + } + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = rdArray + rdIndex; + if (rd->type == RT_2 & rd->x3 == 0) { // typo alert + flags = N_EXT; + desc = 0; + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 4; // REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY? + } + + symIndex = MachO_DeclareSymbol(rd->name, NULL, rd->x4, 0, flags, desc); + rd->type = RT_5; + rd->x18 = symIndex; + } + } + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = &RELOC_DATA(rdIndex); + if (rd->type == RT_1 && rd->x3 == 0) { + flags = N_EXT; + desc = 1; // REFERENCE_FLAG_UNDEFINED_LAZY? + if (rd->privFlag != 0) { + flags |= N_PEXT; + desc = 5; // REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY? + } + + symIndex = MachO_DeclareSymbol(rd->name, NULL, 0, 0, flags, desc); + rd = &RELOC_DATA(rdIndex); + rd->x18 = symIndex; + + if (copts.codegen_dynamic && rd->sect10 == StubSect) { + MachO_AddIndirectSymbol(symIndex); + rd->section = rd->sect10; + rd->x4 = rd->gapC; + } else { + rd->x2 = 1; + rd->type = RT_5; + } + } + } + + if (copts.codegen_dynamic) { + if (LazySymbolSect) + LazySymbolSect->section.reserved1 = MachO_NumIndirectSym(); + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = &RELOC_DATA(rdIndex); + if (rd->type == RT_1 && rd->x3 != 0 && rd->section == StubSect) { + MachO_AddIndirectSymbol(rd->x18); + + rd = &RELOC_DATA(rdIndex); + rd->x3 = 0; + updatesectreloc(rd, rd->section, rd->x4); + } + } + + for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { + rd = &RELOC_DATA(rdIndex); + if (rd->type == RT_1 && rd->x3 == 0 && rd->section == StubSect) { + MachO_AddIndirectSymbol(rd->x18); + + rd = &RELOC_DATA(rdIndex); + rd->x3 = 0; + updatesectreloc(rd, rd->section, rd->x4); + } + } + } + + if (copts.codegen_dynamic) { + if (NonLazySymbolSect) + NonLazySymbolSect->section.reserved1 = MachO_NumIndirectSym(); + + for (objlist = toclist; objlist; objlist = objlist->next) { + if (objlist->object->section == SECT_NONLAZY_PTRS) { + SInt32 id = CMangler_GetLinkName(objlist->object)->id; + MachO_AddIndirectSymbol(RELOC_DATA(id).x18); + } + } + } + + for (reloc = FirstReloc; reloc; reloc = reloc->next) { + rd = rdArray + reloc->relocID; + value = 0; + switch (rd->type) { + case RT_0: + if (rd->section == StubSect && reloc->mwRelType == MW_RELOC_9) { + symIndex = rd->sect10->num; + value = rd->gapC; + } else { + symIndex = rd->section->num; + value = rd->x4; + flags = 0; + } + break; + case RT_5: + symIndex = rd->x18; + flags = N_EXT; + break; + default: + CError_FATAL(1341); + } + + if (copts.codegen_pic) { + switch (reloc->mwRelType) { + case MW_RELOC_5_LO16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = value & 0xFFFF; + nextRelType = PPC_RELOC_LO16_SECTDIFF; + break; + case MW_RELOC_7_HA16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + if (value & 0x8000) + value += 0x10000; + value = (value >> 16) & 0xFFFF; + nextRelType = PPC_RELOC_HA16_SECTDIFF; + break; + case MW_RELOC_6_HI16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = (value >> 16) & 0xFFFF; + nextRelType = PPC_RELOC_HI16_SECTDIFF; + break; + case MW_RELOC_8: + CError_FATAL(1367); + nextRelType = PPC_RELOC_HI16_SECTDIFF; + break; + case MW_RELOC_0: + case MW_RELOC_9: + opMask = 0; + argMask = 0xFFFFFFFF; + nextRelType = PPC_RELOC_VANILLA; + break; + case MW_RELOC_2_BR24: + opMask = 0xFC000003; + argMask = 0x3FFFFFC; + value = value & 0x3FFFFFC; + nextRelType = PPC_RELOC_BR24; + break; + default: + CError_FATAL(1383); + } + + if (nextRelType == PPC_RELOC_BR24) { + MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 1, flags, nextRelType); + } else if (nextRelType == PPC_RELOC_VANILLA) { + MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); + } else { + CError_ASSERT(1391, rd->type == RT_0); + + MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); + MachO_Relocate(reloc->section, rd->x4, reloc->picOffset, 4, 0, flags, PPC_RELOC_PAIR); + value = 0; + } + + if (value) { + UInt32 *ptr = (UInt32 *) (*reloc->section->glist.data + reloc->offset); + *ptr = (*ptr & opMask) | (argMask & (value + (*ptr & argMask))); + } + } else { + switch (reloc->mwRelType) { + case MW_RELOC_5_LO16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = value & 0xFFFF; + nextRelType = PPC_RELOC_LO16; + break; + case MW_RELOC_7_HA16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + if (value & 0x8000) + value += 0x10000; + value = (value >> 16) & 0xFFFF; + nextRelType = PPC_RELOC_HA16; + break; + case MW_RELOC_6_HI16: + opMask = 0xFFFF0000; + argMask = 0xFFFF; + value = (value >> 16) & 0xFFFF; + nextRelType = PPC_RELOC_HI16; + break; + case MW_RELOC_8: + CError_FATAL(1434); + opMask = 0xFFFF0000; + argMask = 0xFFFF; + nextRelType = PPC_RELOC_HI16; + break; + case MW_RELOC_2_BR24: + opMask = 0xFC000003; + argMask = 0x3FFFFFC; + value = value & 0x3FFFFFC; + nextRelType = PPC_RELOC_BR24; + break; + case MW_RELOC_0: + case MW_RELOC_9: + opMask = 0; + argMask = 0xFFFFFFFF; + nextRelType = PPC_RELOC_VANILLA; + break; + default: + CError_FATAL(1452); + } + + if (value != 0) { + UInt32 *ptr = (UInt32 *) (*reloc->section->glist.data + reloc->offset); + *ptr = (*ptr & opMask) | (argMask & (value + (*ptr & argMask))); + } + + if (nextRelType == PPC_RELOC_BR24) { + MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 1, flags, nextRelType); + } else { + MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); + if (nextRelType == PPC_RELOC_HI16 || nextRelType == PPC_RELOC_HA16 || nextRelType == PPC_RELOC_LO16) + MachO_Relocate(reloc->section, rd->x4, 0xFFFFFF, 4, 0, 0, PPC_RELOC_PAIR); + } + } + } + + COS_UnlockHandle(RelocData.data); + MachO_Finish(); +} + +void ObjGen_Cleanup(void) { + MachO_Cleanup(); + if (RelocData.data) + FreeGList(&RelocData); + + CleanupDumpIR(); + pccleanuplisting(); +} + +void ObjGen_SetupSym(void) { +} + +static void CreateTheSegment(void) { + TheSegment = MachO_CreateSegment("", 7, 7, 0); + Sections[SegmentForceCreate] = ObjGen_GetSection(SegmentForceCreate); +} + +static void patchuplazyptr(Object *object) { + RelocDataT *rd; + Object *toc; + + if (CParser_HasInternalLinkage(object) || !(object->qual & (Q_20000 | Q_OVERLOAD))) { + toc = object->toc; + if (toc->section == SECT_NONLAZY_PTRS) { + toc->section = SECT_CONST_PTR; + rd = &RELOC_DATA(ObjGen_GetHashNodeRelocID(toc, NULL, 0)); + if (rd->type == RT_3) { + rd->type = RT_6; + rd->x18 = ObjGen_GetHashNodeRelocID(object, NULL, 0); + } else { + CError_FATAL(1592); + } + } + } +} + +static void definedatasymbol(Object *object, MachOSection *section, SInt32 value) { + Boolean flag; + + flag = ObjGen_DeclareSymbol(object, section, value); + ObjGen_GetHashNodeRelocID(object, section, 0); + + if (flag && copts.isGeneratingDebugInfo) + GenStab_Var(object); + if (object->toc) + patchuplazyptr(object); +} + +static void declaredata(Object *object, char *data, OLinkList *olinklist, UInt32 size, Boolean isConst) { + Section sectionID; // r30 + MachOSection *section; // r24 + SInt32 offset; // r23 + GList *gl; // r22 + UInt32 align; + OLinkList *scan; + + if (!TheSegment) + CreateTheSegment(); + + if (data) { + if (object->section == SECT_COMMON_VARS) + object->section = SECT_DEFAULT; + + if (object->section == SECT_DEFAULT) { + if (isConst) + object->section = SECT_CONST; + else + object->section = SECT_DATA; + } + + if (object->section == SECT_CONST && olinklist) + object->section = SECT_CONST_PTR; + + object->section = ObjGen_CheckCoalesceSection(object); + + sectionID = object->section; + section = Sections[sectionID]; + if (!section) + section = ObjGen_GetSection(sectionID); + + gl = MachO_GetGList(section); + offset = gl->size; + + align = CMach_AllocationAlignment(object->type, object->qual); + if (!align) + align = 1; + align = AlignTo_Section(section, align); + + if (offset % align) { + SInt32 adjust = align - (offset % align); + AppendGListZeros(gl, adjust); + offset += adjust; + } + + definedatasymbol(object, Sections[sectionID], offset); + + for (scan = olinklist; scan; scan = scan->next) { + if (scan->somevalue) + *((SInt32 *) (data + scan->offset)) = scan->somevalue; + } + + if (sectionID == SECT_8BYTE_LITERALS) + AppendGListData(gl, data, 8); + else if (sectionID == SECT_4BYTE_LITERALS) + AppendGListData(gl, data, 4); + else + AppendGListData(gl, data, size); + + while (olinklist) { + SInt32 extflag; + SInt32 id; + + extflag = ObjGen_IsExternalVar(ObjGen_GetHashNodeRelocID(scan->obj, NULL, 0)); + id = CMangler_GetLinkName(scan->obj)->id; + ObjGen_Relocate(Sections[sectionID], offset + scan->offset, extflag + id, RT_4, MW_RELOC_0); + olinklist = olinklist->next; + } + } else { + if ( + CParser_HasInternalLinkage(object) || + (copts.no_common && !(object->qual & Q_20000)) || + !object->qual & Q_1000000 // typo alert + ) + { + if (object->section == SECT_DEFAULT) { + if (isConst) + object->section = SECT_CONST; + else + object->section = SECT_UDATA; + } + + if (object->section == SECT_CONST && olinklist) + object->section = SECT_CONST_PTR; + + object->section = ObjGen_CheckCoalesceSection(object); + section = ObjGen_GetSection(object->section); + sectionID = object->section; + + if (sectionID == SECT_UDATA) { + align = CMach_AllocationAlignment(object->type, object->qual); + AlignTo_Section(section, align); + offset = section->section.size; + if (!align) + align = 1; + + if (offset % align) { + // issue here + SInt32 adjust = align - (offset % align); + offset = offset + adjust; + } + + section->section.size = offset; + + definedatasymbol(object, Sections[sectionID], offset); + + offset += size; + section->section.size = offset; + } else { + gl = MachO_GetGList(section); + offset = gl->size; + + align = CMach_AllocationAlignment(object->type, object->qual); + if (!align) + align = 1; + align = AlignTo_Section(section, align); + + if (offset % align) { + SInt32 adjust = align - (offset % align); + AppendGListZeros(gl, adjust); + offset += adjust; + } + + definedatasymbol(object, Sections[sectionID], offset); + AppendGListZeros(gl, size); + } + } else { + object->qual |= Q_1000000; + object->section = SECT_COMMON_VARS; + ObjGen_GetHashNodeRelocID(object, NULL, size); + } + } +} + +void ObjGen_DeclareData(Object *object, char *data, OLinkList *olinklist, UInt32 size) { + declaredata(object, data, olinklist, size, 0); +} + +void ObjGen_DeclareReadOnlyData(Object *object, char *data, OLinkList *olinklist, UInt32 size) { + declaredata(object, data, olinklist, size, 1); +} + +void ObjGen_SegmentName(void) { +} + +void ObjGen_SymFunc(Object *function) { + GenStab_Function(function, ObjGen_GetHashNodeRelocID(function, NULL, 0)); +} + +void ObjGenMach_SymFuncEnd(Object *function, UInt32 offset) { + GenStab_FunctionEnd(function, ObjGen_GetHashNodeRelocID(function, NULL, 0), offset); +} + +void ObjGen_CodeSetup(void) { + // empty/unknown args +} + +void ObjGen_CodeCleanup(void) { +} + +void ObjGen_SrcBreakName(HashNameNode *name, SInt32 fileModDate, Boolean flag) { + char *ptr; + char *ptr2; + char *ptr3; + char buf1[1024]; + char buf2[1024]; + + if (copts.isGeneratingDebugInfo) { + if (name) + strncpy(buf1, name->name, sizeof(buf1)); + else + COS_FileGetPathName(buf1, &cparamblkptr->mainFileSpec, &fileModDate); + + if (name && copts.absolutepath) + ptr = buf1 + strlen(buf1); + else + ptr = strrchr(buf1, '/'); + + if ((flag || name) && ptr && copts.absolutepath) { + if (!strncmp(buf1, "Mac OS X:", strlen("Mac OS X:"))) { + strcpy(buf2, "/"); + ptr2 = buf2 + 1; + ptr3 = buf1 + strlen("Mac OS X:"); + } else { + strcpy(buf2, "/Volumes/"); + ptr2 = buf2 + strlen("/Volumes/"); + ptr3 = buf1; + } + + while (ptr3 <= ptr) + *(ptr2++) = *(ptr3++); + *ptr2 = 0; + + if (flag && !name) { + GenStab_SourceFile(buf2); + } else { + GenStab_IncludeFile(buf2); + return; + } + } + + if (ptr) + ptr++; + else + ptr = buf1; + + if (flag && !name) + GenStab_SourceFile(ptr); + else + GenStab_IncludeFile(ptr); + } +} + +GList *ObjGen_GetSectionGList(MachOSection *section) { + return MachO_GetGList(section); +} + +MachOSection *ObjGen_DeclareFunction(Object *object) { + MachOSection *section; + + if (!TheSegment) + CreateTheSegment(); + + if (object->section == SECT_DEFAULT) + object->section = SECT_TEXT; + + object->section = ObjGen_CheckCoalesceSection(object); + section = ObjGen_GetSection(object->section); + + if (object) { + ObjGen_DeclareSymbol(object, section, section->glist.size); + if (CMangler_GetLinkName(object)->id == -1) { + CMangler_GetLinkName(object)->id = ObjGen_MakeSectReloc(section); + } else { + RelocDataT *rd = &RELOC_DATA(CMangler_GetLinkName(object)->id); + if (rd->x3 == 0) { + updatesectreloc(rd, section, section->glist.size); + } else { + rd->section = section; + rd->x4 = section->glist.size; + } + } + } + + return section; +} + +MachOSection *ObjGen_DeclareCode(Object *object) { + MachOSection *section; + + section = ObjGen_DeclareFunction(object); + last_base_offset[object->section] = ObjGen_GetSectionGList(section)->size; + last_function_sect = section; + last_function_sect_id = object->section; + + return section; +} + +MachOSection *ObjGen_DeclareMachSection() { + // unknown args + CError_FATAL(2020); + return NULL; +} + +void ObjGen_Relocate(MachOSection *section, SInt32 offset, SInt32 relocID, RelocType relocType, MWReloc mwRelType) { + Reloc *reloc; + + reloc = galloc(sizeof(Reloc)); + reloc->section = section; + reloc->offset = offset; + reloc->relocID = relocID; + reloc->relocType = relocType; + reloc->mwRelType = mwRelType; + if (copts.codegen_pic) + reloc->picOffset = pic_base_offset; + else + reloc->picOffset = 0; + + reloc->next = NULL; + if (FirstReloc == NULL) + FirstReloc = reloc; + else + LastReloc->next = reloc; + LastReloc = reloc; +} + +void ObjGen_RelocateObj(MachOSection *section, SInt32 offset, Object *object, MWReloc mwRelType) { + Reloc *reloc; + + if (section == last_function_sect) + offset += last_base_offset[last_function_sect_id]; + + if (object) { + reloc = galloc(sizeof(Reloc)); + reloc->section = section; + reloc->offset = offset; + reloc->relocID = ObjGen_GetHashNodeRelocID(object, NULL, 0); + switch (mwRelType) { + case MW_RELOC_0: + case MW_RELOC_2_BR24: + case MW_RELOC_9: + reloc->picOffset = 0; + break; + case MW_RELOC_5_LO16: + case MW_RELOC_6_HI16: + case MW_RELOC_7_HA16: + reloc->picOffset = pic_base_offset; + break; + default: + CError_FATAL(2115); + } + reloc->relocType = RT_4; + reloc->mwRelType = mwRelType; + + reloc->next = NULL; + if (FirstReloc == NULL) + FirstReloc = reloc; + else + LastReloc->next = reloc; + LastReloc = reloc; + } +} + +SInt32 ObjGen_DeclareLiteralString(UInt32 len, char *data, SInt32 align) { + SInt32 offset; + SInt32 relocID; + GList *gl; + MachOSection *section; + UInt32 align2; + SInt32 pad; + SInt32 i; + + if (!TheSegment) + CreateTheSegment(); + + section = ObjGen_GetSection(SECT_TEXT_CSTRING); + gl = MachO_GetGList(section); + offset = gl->size; + if (!align) + align = 1; + + align2 = AlignTo_Section(section, align); + if (offset % align2) { + pad = align2 - (offset % align2); + for (i = 0; i < pad; i++) + AppendGListByte(gl, 0); + } + + relocID = ObjGen_MakeSectReloc(section); + AppendGListData(gl, data, len); + return relocID; +} + +UInt32 ObjGen_GetSectSize(MachOSection *section) { + if (section->glist.data) + return section->glist.size; + else + return section->section.size; +} + +void ObjGen_GetExtName(SInt32 id, char *buf) { + switch (RELOC_DATA(id).type) { + case RT_0: + sprintf(buf, "%s+%08x", RELOC_DATA(id).section->section.sectname, RELOC_DATA(id).x4); + break; + case RT_1: + case RT_2: + case RT_3: + case RT_4: + strcpy(buf, RELOC_DATA(id).name); + break; + case RT_5: + sprintf(buf, "id(%d)", RELOC_DATA(id).x18); + break; + } +} + +void ObjGen_PicRelocate(MachOSection *section, SInt32 offset, SInt32 relocID, SInt32 picOffset) { + Reloc *reloc; + + reloc = galloc(sizeof(Reloc)); + reloc->section = section; + reloc->offset = offset; + reloc->relocID = relocID; + reloc->relocType = RT_4; + reloc->mwRelType = MW_RELOC_0; + reloc->picOffset = picOffset; + + reloc->next = NULL; + if (FirstReloc == NULL) + FirstReloc = reloc; + else + LastReloc->next = reloc; + LastReloc = reloc; +} + +SInt32 ObjGen_GetRelocOffset(SInt32 id) { + switch (RELOC_DATA(id).type) { + case RT_0: + break; + case RT_1: + case RT_2: + if (RELOC_DATA(id).x3) + break; + default: + return 0; + } + + return RELOC_DATA(id).x4; +} + +Boolean ObjGen_IsExternalVar(SInt32 id) { + return RELOC_DATA(id).type == RT_3; +} + +SInt32 ObjGen_DeclareInit(UInt32 len, char *data, SInt32 align) { + SInt32 offset; + SInt32 relocID; + GList *gl; + MachOSection *section; + UInt32 align2; + SInt32 pad; + SInt32 i; + + section = ObjGen_GetSection(SECT_DATA); + gl = MachO_GetGList(section); + offset = gl->size; + if (!align) + align = 1; + + align2 = AlignTo_Section(section, align); + if (offset % align2) { + pad = align2 - (offset % align2); + for (i = 0; i < pad; i++) + AppendGListByte(gl, 0); + } + + relocID = ObjGen_MakeSectReloc(section); + AppendGListData(gl, data, len); + return relocID; +} + +static UInt32 pic_stub[] = { + 0x7C0802A6, + 0x429F0005, + 0x7D6802A6, + 0x7C0803A6, + 0x3D6B0000, + 0x818B0000, + 0x7D8903A6, + 0x396B0000, + 0x4E800420, + 0 +}; +static UInt32 abs_stub[] = { + 0x3D600000, + 0x818B0000, + 0x7D8903A6, + 0x396B0000, + 0x4E800420, + 0 +}; + +void CodeGen_GenDynLinkStub(MachOSection *a, MachOSection *b, SInt32 relocID) { + SInt32 offset; + GList *gl; + SInt32 id; + + id = ObjGen_GetHashNodeRelocID(dyld_stub_binding_helper, NULL, 0); + + offset = ObjGen_GetSectSize(a); + gl = ObjGen_GetSectionGList(a); + + if (copts.codegen_pic) { + UInt32 i; + for (i = 0; i < 9; i++) + AppendGListLong(gl, pic_stub[i]); + pic_base_offset = offset + 8; + ObjGen_Relocate(a, offset + 16, relocID, RT_4, MW_RELOC_7_HA16); + ObjGen_Relocate(a, offset + 20, relocID, RT_4, MW_RELOC_5_LO16); + ObjGen_Relocate(a, offset + 28, relocID, RT_4, MW_RELOC_5_LO16); + } else { + UInt32 i; + for (i = 0; i < 5; i++) + AppendGListLong(gl, abs_stub[i]); + ObjGen_Relocate(a, offset, relocID, RT_4, MW_RELOC_7_HA16); + ObjGen_Relocate(a, offset + 4, relocID, RT_4, MW_RELOC_5_LO16); + ObjGen_Relocate(a, offset + 12, relocID, RT_4, MW_RELOC_5_LO16); + } + + offset = ObjGen_GetSectSize(b); + gl = ObjGen_GetSectionGList(b); + AppendGListLong(gl, 0); + + ObjGen_Relocate(b, offset, id, RT_4, MW_RELOC_0); +} + +void ObjGen_DeclarePICBase(Object *object, SInt32 offset) { + pic_base_offset = offset + ObjGen_GetRelocOffset(CMangler_GetLinkName(object)->id); +} + +void ObjGen_DeclareEntry(Object *object, SInt32 offset) { + RelocDataT r = {0}; + + CError_ASSERT(2415, last_function_sect_id != SECT_DEFAULT); + + ObjGen_DeclareSymbol( + object, + Sections[last_function_sect_id], + offset + last_base_offset[last_function_sect_id]); + + r.privFlag = ObjGen_ComputePrivFlag(object->flags); + + updatesectreloc( + &r, + Sections[last_function_sect_id], + offset + last_base_offset[last_function_sect_id]); + + AppendGListData(&RelocData, &r, sizeof(r)); + CMangler_GetLinkName(object)->id = RelocIndex; + RelocIndex++; +} + +void ObjGen_DeclareExceptionTables(Object *object, SInt32 codesize, char *data, SInt32 len, OLinkList *refs) { + UInt32 offset; + MachOSection *section; + GList *gl; + SInt32 relocID; + Boolean flag22; + char *buf; + char *tmp; + + UInt32 zero; + RelocDataT rd; + UInt32 stuff[3]; + + zero = 0; + flag22 = 1; + if (CParser_HasInternalLinkage(object)) + flag22 = 0; + + if (len == 8) { + if ((*((UInt16 *) data) & 8) >> 3) { + *((UInt16 *) data) &= ~8; + len = 4; + } + } + + if (len != 4) { + section = ObjGen_GetSection(SECT_MW_EX_TABLE); + offset = ObjGen_GetSectSize(section); + + memclrw(&rd, sizeof(rd)); + rd.type = RT_7; + rd.x2 = flag22; + rd.privFlag = 1; + rd.x3 = 1; + rd.x4 = offset; + rd.section = section; + + tmp = CMangler_GetLinkName(object)->name; + buf = galloc(1 + strlen(tmp) + strlen("mwEXTBL@")); + sprintf(buf, "mwEXTBL.%s", tmp); + rd.name = buf; + rd.x18 = -1; + + AppendGListData(&RelocData, &rd, sizeof(rd)); + RelocIndex++; + + gl = ObjGen_GetSectionGList(section); + relocID = ObjGen_MakeSectReloc(section); + AppendGListData(gl, data, len); + if ((len & 3) != 0) + AppendGListData(gl, &zero, 4 - (len & 3)); + + while (refs) { + ObjGen_RelocateObj(section, offset + refs->offset, refs->obj, MW_RELOC_9); + refs = refs->next; + } + } + + section = ObjGen_GetSection(SECT_MW_EX_TABLE_INDEX); + gl = ObjGen_GetSectionGList(section); + offset = ObjGen_GetSectSize(section); + + memclrw(&rd, sizeof(rd)); + rd.type = RT_7; + rd.x2 = flag22; + rd.privFlag = 1; + rd.x3 = 1; + rd.x4 = offset; + rd.section = section; + + tmp = CMangler_GetLinkName(object)->name; + buf = galloc(1 + strlen(tmp) + strlen("mwEXTBL@")); + sprintf(buf, "mwEXIDX.%s", tmp); + rd.name = buf; + rd.x18 = -1; + + AppendGListData(&RelocData, &rd, sizeof(rd)); + RelocIndex++; + + stuff[0] = 0; + stuff[1] = ((len == 4) << 31) | (codesize & 0x7FFFFFFF); + stuff[2] = (len == 4) ? *((UInt32 *) data) : 0; + AppendGListData(gl, stuff, sizeof(stuff)); + + ObjGen_RelocateObj(section, offset, object, MW_RELOC_9); + if (len != 4) + ObjGen_Relocate(section, offset + 8, relocID, RT_4, MW_RELOC_9); +} + +void ObjGen_DeclareCodeLabel(Object *labelobj, SInt32 offset, Object *funcobj) { + SInt32 relocOffset; + GList *gl; + MachOSection *section; + + section = ObjGen_GetSection(SECT_DATA); + gl = MachO_GetGList(section); + relocOffset = ObjGen_GetSectSize(section); + + ObjGen_GetHashNodeRelocID(labelobj, section, 0); + AppendGListData(gl, &offset, 4); + ObjGen_RelocateObj(section, relocOffset, funcobj, MW_RELOC_9); +} + +void ObjGen_DeclareSwitchTable(Object *tableobj, Object *funcobj) { + SInt32 relocOffset; + GList *gl; + int i; + MachOSection *section; + + section = ObjGen_GetSection(SECT_MW_SWITCH); + gl = MachO_GetGList(section); + relocOffset = ObjGen_GetSectSize(section); + + ObjGen_GetHashNodeRelocID(tableobj, section, 0); + AppendGListData(gl, tableobj->u.data.u.switchtable.data, 4 * tableobj->u.data.u.switchtable.size); + for (i = tableobj->u.data.u.switchtable.size; i; i--) { + ObjGen_RelocateObj(section, relocOffset, funcobj, MW_RELOC_9); + relocOffset += 4; + } +} + +void ObjGen_DeclareTracebackTable(Object *tableobj, void *data, SInt32 size) { + MachOSection *section; + GList *gl; + + section = ObjGen_GetSection(SECT_MW_SWITCH); + gl = MachO_GetGList(section); + + ObjGen_GetHashNodeRelocID(tableobj, section, 0); + if (CMangler_GetLinkName(tableobj)->id < 0) { + CMangler_GetLinkName(tableobj)->id = ObjGen_MakeSectReloc(section); + } else { + RelocDataT *rd = &RELOC_DATA(CMangler_GetLinkName(tableobj)->id); + switch (rd->type) { + case RT_2: + updatesectreloc(rd, section, section->glist.size); + break; + default: + CError_FATAL(2628); + } + } + + AppendGListData(gl, data, size); +} + +void ObjGen_DeclareSymInfo(void) { + if (copts.isGeneratingDebugInfo) + SymContainedVars(); +} + +void ObjGen_Line(UInt32 line, UInt32 offset) { + if (copts.isGeneratingDebugInfo && line) + GenStab_Line(line, offset + last_base_offset[last_function_sect_id]); +} + +void ObjGen_OutputDebugInfo(Object *funcobj) { + if (copts.isGeneratingDebugInfo) + GenStab_Function(funcobj, CMangler_GetLinkName(funcobj)->id); +} + +SInt32 ObjGen_OutputStab(SymbolData *symbol, SInt32 strIdx) { + Section sectionID; + RelocDataT *rd; + + sectionID = last_function_sect_id; + if (sectionID == SECT_DEFAULT) + sectionID = SECT_TEXT; + + if (symbol->type == N_FUN) { + if (symbol->u.name[0] == 0) { + if (Sections[sectionID]) { + symbol->section = Sections[sectionID]; + symbol->value = ObjGen_GetSectSize(Sections[sectionID]); + } else { + symbol->section = NULL; + symbol->value = 0; + } + } else { + rd = &RELOC_DATA(symbol->value); + symbol->section = rd->section; + symbol->value = rd->x4; + } + } else if (symbol->type == N_SLINE) { + symbol->u.strx = 0; + if (Sections[sectionID]) + symbol->section = Sections[sectionID]; + else + symbol->section = NULL; + } else if (symbol->type == N_STSYM) { + rd = &RELOC_DATA(symbol->value); + symbol->section = rd->section; + symbol->value = rd->x4; + if (symbol->section && (symbol->section->section.flags & S_ZEROFILL)) + symbol->type = N_LCSYM; + } else if (symbol->type == N_SO || symbol->type == N_SOL) { + if (Sections[sectionID]) { + symbol->section = Sections[sectionID]; + symbol->value = ObjGen_GetSectSize(Sections[sectionID]); + } else { + symbol->section = NULL; + symbol->value = 0; + } + } + + return MachO_OutputStab(symbol, strIdx); +} + +void ObjGen_SetSectName() { + // empty, unknown args +} + +void ObjGen_DeclareInitFunction(Object *funcobj) { + SInt32 offset; + MachOSection *section; + GList *gl; + + section = ObjGen_GetSection(SECT_MOD_INIT_FUNC); + offset = ObjGen_GetSectSize(section); + gl = ObjGen_GetSectionGList(section); + AppendGListLong(gl, 0); + + ObjGen_Relocate(section, offset, ObjGen_GetHashNodeRelocID(funcobj, NULL, 0), RT_4, MW_RELOC_0); +} + +static void SymContainedVars(void) { + ObjectList *list; + + for (list = arguments; list; list = list->next) { + if (list->object->u.var.info->used && list->object->name->name[0] != '@') + GenStab_Parameter(list->object); + } + + for (list = locals; list; list = list->next) { + if (list->object->u.var.info->used && list->object->name->name[0] != '@') + GenStab_Var(list->object); + } +} + +Boolean ObjGen_IsExported(Object *object) { + SInt32 id = ObjGen_GetHashNodeRelocID(object, NULL, -1); + if (id >= 0 && RELOC_DATA(id).type == RT_0) + return 1; + return 0; +} + +static void AppendGListZeros(GList *glist, SInt32 size) { + SInt32 pos = glist->size; + AppendGListNoData(glist, size); + memclr(*glist->data + pos, size); +} diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c index 68883e0..bdf75f9 100644 --- a/compiler_and_linker/unsorted/Operands.c +++ b/compiler_and_linker/unsorted/Operands.c @@ -1,11 +1,16 @@ #include "compiler/Operands.h" #include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" #include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/StackFrame.h" #include "compiler/enode.h" #include "compiler/objects.h" -#include "compiler.h" +#include "compiler/CodeGen.h" +#include "compiler/RegisterInfo.h" unsigned long long uns_to_float_cc = 0x4330000000000000; unsigned long long int_to_float_cc = 0x4330000080000000; @@ -27,8 +32,7 @@ void load_immediate(short reg, SInt32 value) { } static void set_op_flags(Operand *op, ENode *expr) { -#line 118 - CError_ASSERT(op); + CError_ASSERT(118, op); if (expr) { if (expr->type == EINTCONST) { @@ -55,8 +59,7 @@ void symbol_operand(Operand *op, Object *obj) { void indirect(Operand *op, ENode *expr) { switch (op->optype) { case OpndType_GPRPair: -#line 163 - CError_FATAL(); + CError_FATAL(163); case OpndType_CRField: case OpndType_IndirectGPR_ImmOffset: case OpndType_IndirectGPR_Indexed: @@ -91,8 +94,7 @@ void indirect(Operand *op, ENode *expr) { set_op_flags(op, expr); break; default: -#line 215 - CError_FATAL(); + CError_FATAL(215); } } @@ -268,8 +270,7 @@ void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) { opOut->immediate = opA->immediate + opB->immediate; break; default: -#line 415 - CError_FATAL(); + CError_FATAL(415); } } @@ -333,17 +334,16 @@ void coerce_to_addressable(Operand *op) { if (op->optype == OpndType_GPR_ImmOffset) { op->optype = OpndType_IndirectGPR_ImmOffset; } else { -#line 563 - CError_FATAL(); + CError_FATAL(563); } } break; default: -#line 581 - CError_FATAL(); + CError_FATAL(581); } } +void Coerce_to_register(Operand *op, Type *type, short output_reg) { SInt32 offset; short opcode; short reg; @@ -402,8 +402,7 @@ void coerce_to_addressable(Operand *op) { break; } } else { -#line 680 - CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + CError_ASSERT(680, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); } load_store_register(opcode, reg, op->reg, op->object, op->immOffset); setpcodeflags(op->flags); @@ -424,8 +423,7 @@ void coerce_to_addressable(Operand *op) { break; } } else { -#line 724 - CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + CError_ASSERT(724, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); } emitpcode(opcode, reg, op->reg, op->regOffset); setpcodeflags(op->flags); @@ -452,8 +450,7 @@ void coerce_to_addressable(Operand *op) { cond = 1; break; default: -#line 758 - CError_FATAL(); + CError_FATAL(758); } bit_offset = cond + (op->reg << 2); bit_size = 1; @@ -462,8 +459,7 @@ void coerce_to_addressable(Operand *op) { emitpcode(PC_XORI, tmp, tmp, 1); break; default: -#line 769 - CError_FATAL(); + CError_FATAL(769); } op->optype = OpndType_GPR; @@ -479,8 +475,7 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou regHi = -1; -#line 794 - CError_ASSERT(TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8)); + CError_ASSERT(794, TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8)); coerce_to_addressable(op); switch (op->optype) { @@ -494,8 +489,7 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou tmp2 = output_regHi ? output_regHi : op->regHi; if (tmp1 != op->reg) { if (tmp1 == op->regHi) { -#line 818 - CError_ASSERT(tmp1 != tmp2); + CError_ASSERT(818, tmp1 != tmp2); emitpcode(PC_MR, tmp2, op->regHi); emitpcode(PC_MR, tmp1, op->reg); } else { @@ -505,8 +499,7 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou } } else if (tmp2 != op->regHi) { if (tmp2 == op->reg) { -#line 832 - CError_ASSERT(tmp1 != tmp2); + CError_ASSERT(832, tmp1 != tmp2); emitpcode(PC_MR, tmp1, op->reg); emitpcode(PC_MR, tmp2, op->regHi); } else { @@ -520,16 +513,13 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou regHi = op->regHi; break; case OpndType_GPR: -#line 849 - CError_FATAL(); + CError_FATAL(849); break; case OpndType_GPR_ImmOffset: -#line 852 - CError_FATAL(); + CError_FATAL(852); break; case OpndType_GPR_Indexed: -#line 855 - CError_FATAL(); + CError_FATAL(855); break; case OpndType_Absolute: reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; @@ -555,8 +545,7 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; if (op->reg == regHi) { if (op->reg == reg) { -#line 887 - CError_FATAL(); + CError_FATAL(887); } else { load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); setpcodeflags(op->flags); @@ -580,13 +569,11 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou setpcodeflags(op->flags); break; default: -#line 912 - CError_FATAL(); + CError_FATAL(912); } if (regHi == -1) { -#line 916 - CError_FATAL(); + CError_FATAL(916); } else { op->optype = OpndType_GPRPair; op->reg = reg; @@ -614,8 +601,7 @@ void Coerce_to_fp_register(Operand *op, TypeIntegral *tint, short output_reg) { setpcodeflags(op->flags); break; default: -#line 986 - CError_FATAL(); + CError_FATAL(986); } op->optype = OpndType_FPR; @@ -662,16 +648,14 @@ void Coerce_to_v_register(Operand *op, TypeStruct *tstruct, short output_reg) { emitpcode(PC_VSPLTISW, reg, op->immediate); break; default: -#line 1049 - CError_FATAL(); + CError_FATAL(1049); } op->optype = OpndType_VR; op->reg = reg; setpcodeflags(op->flags); break; default: -#line 1059 - CError_FATAL(); + CError_FATAL(1059); } op->optype = OpndType_VR; @@ -695,8 +679,7 @@ void store(short reg, Operand *op, Type *type) { break; } } else { -#line 1171 - CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + CError_ASSERT(1171, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); } load_store_register(opcode, reg, op->reg, op->object, op->immOffset); setpcodeflags(op->flags); @@ -713,23 +696,20 @@ void store(short reg, Operand *op, Type *type) { break; } } else { -#line 1188 - CError_ASSERT(IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + CError_ASSERT(1188, 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(); + CError_FATAL(1193); } } void store_pair(short reg, short regHi, Operand *op, Type *type) { short tmp; -#line 1208 - CError_ASSERT(TYPE_IS_8BYTES(type)); + CError_ASSERT(1208, TYPE_IS_8BYTES(type)); coerce_to_addressable(op); switch (op->optype) { @@ -748,8 +728,7 @@ void store_pair(short reg, short regHi, Operand *op, Type *type) { setpcodeflags(op->flags); break; default: -#line 1228 - CError_FATAL(); + CError_FATAL(1228); } } @@ -765,8 +744,7 @@ void store_fp(short reg, Operand *op, Type *tint) { setpcodeflags(op->flags); break; default: -#line 1259 - CError_FATAL(); + CError_FATAL(1259); } } @@ -782,8 +760,7 @@ void store_v(short reg, Operand *op, Type *tstruct) { setpcodeflags(op->flags); break; default: -#line 1283 - CError_FATAL(); + CError_FATAL(1283); } } @@ -848,8 +825,7 @@ void extend32(Operand *op, Type *type, short output_reg) { } break; default: -#line 1389 - CError_FATAL(); + CError_FATAL(1389); } op->optype = OpndType_GPR; @@ -1037,7 +1013,6 @@ void load_address(short dest_reg, Operand *op) { } else if (op->optype == OpndType_IndirectGPR_Indexed) { emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset); } else { -#line 1849 - CError_FATAL(); + CError_FATAL(1849); } } diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c index 2ebb3c1..922e9cf 100644 --- a/compiler_and_linker/unsorted/PCodeAssembly.c +++ b/compiler_and_linker/unsorted/PCodeAssembly.c @@ -1,27 +1,1614 @@ #include "compiler/PCodeAssembly.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeListing.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" static UInt32 codebase; -static void pcode_update_mem_labeldiff_imm() { +static SInt32 pcode_update_mem_labeldiff_imm(PCode *instr, const PCodeArg *op, WeirdOperand *wop) { + SInt32 offset; + Object *object; + UInt8 arg; + + if (op->kind == PCOp_MEMORY) { + object = op->data.mem.obj; + offset = op->data.mem.offset; + switch (object->datatype) { + case DLOCAL: + switch ((UInt8) op->arg) { + case RefType_1: + offset += local_offset_16(object); + break; + case RefType_D: + offset = local_offset_lo(object, offset); + break; + case RefType_C: + offset = local_offset_ha(object, offset); + break; + default: + CError_FATAL(83); + } + break; + case DDATA: + case DFUNC: + case DVFUNC: + case DNONLAZYPTR: + switch ((UInt8) op->arg) { + case RefType_6: + wop->type = MW_RELOC_5_LO16; + break; + case RefType_2: + wop->type = MW_RELOC_3; + break; + case RefType_3: + wop->type = MW_RELOC_4; + break; + case RefType_8: + wop->type = MW_RELOC_7_HA16; + break; + case RefType_7: + wop->type = MW_RELOC_6_HI16; + break; + default: + CError_FATAL(135); + } + + wop->x2 = object; + CError_ASSERT(144, offset == 0); + break; + default: + CError_FATAL(164); + } + } else if (op->kind == PCOp_LABELDIFF) { + arg = op->arg; + + offset = op->data.labeldiff.labelA->block->codeOffset - op->data.labeldiff.labelB->block->codeOffset; + offset += op->data.labeldiff.offset; + if (arg == 1) + offset = -offset; + + if (offset > 0x7FFF) + PPCError_Error(109); + else if (offset < -0x8000) + PPCError_Error(109); + } else if (op->kind == PCOp_IMMEDIATE) { + offset = op->data.imm.value; + } else { + CError_FATAL(193); + } + + return offset; } -UInt32 assemblepcode(PCode *instr, UInt32 offset, PCodeArg *dummyArg) { +UInt32 assemblepcode(PCode *instr, UInt32 offset, WeirdOperand *wop) { + UInt32 bits; + + bits = opcodeinfo[instr->op].insn; + wop->type = -1; + wop->x6 = 0; + + switch (instr->op) { + case PC_BL: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; + wop->type = MW_RELOC_2_BR24; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_2_BR24; + else + CError_FATAL(246); + } else if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= instr->args[0].data.imm.value & 0x3FFFFFC; + if (flag) + bits |= 2; + } else { + bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; + if (flag) + CError_FATAL(261); + } + break; + } + + case PC_B: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_2_BR24; + else + CError_FATAL(288); + } else if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= instr->args[0].data.imm.value & 0x3FFFFFC; + if (flag) + bits |= 2; + } else { + bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; + if (flag) + CError_FATAL(302); + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BDNZ: + case PC_BDZ: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(333); + } else { + SInt32 value; + if (instr->args[0].kind == PCOp_IMMEDIATE) + value = instr->args[0].data.imm.value; + else + value = instr->args[0].data.label.label->block->codeOffset - offset; + + bits |= value & 0xFFFF; + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BC: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; + + if (instr->args[3].kind == PCOp_MEMORY) { + bits |= instr->args[3].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[3].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(387); + } else { + SInt32 value; + if (instr->args[3].kind == PCOp_IMMEDIATE) + value = instr->args[3].data.imm.value; + else + value = instr->args[3].data.label.label->block->codeOffset - offset; + + bits |= value & 0xFFFF; + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BT: + case PC_BF: + case PC_BDNZT: + case PC_BDNZF: + case PC_BDZT: + case PC_BDZF: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; + + if (instr->args[2].kind == PCOp_MEMORY) { + bits |= instr->args[2].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[2].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(446); + } else { + SInt32 value; + if (instr->args[2].kind == PCOp_IMMEDIATE) { + value = instr->args[2].data.imm.value; + if (flag) + bits |= 2; + } else { + value = instr->args[2].data.label.label->block->codeOffset - offset; + CError_ASSERT(458, !flag); + } + + bits |= value & 0xFFFF; + + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BTLR: + case PC_BTCTR: + case PC_BFLR: + case PC_BFCTR: + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + break; + + case PC_BCLR: + case PC_BCCTR: + bits |= instr->args[0].data.imm.value << 21; + bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; + case PC_BLR: + case PC_BCTR: + case PC_BCTRL: + case PC_BLRL: + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + break; + + case PC_CRAND: + case PC_CRANDC: + case PC_CREQV: + case PC_CRNAND: + case PC_CRNOR: + case PC_CROR: + case PC_CRORC: + case PC_CRXOR: + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 21; + bits |= ((instr->args[2].data.reg.reg * 4 + instr->args[3].data.imm.value) & 31) << 16; + bits |= ((instr->args[4].data.reg.reg * 4 + instr->args[5].data.imm.value) & 31) << 11; + break; + + case PC_MCRF: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 18; + break; + + case PC_LBZ: + case PC_LBZU: + case PC_LHZ: + case PC_LHZU: + case PC_LHA: + case PC_LHAU: + case PC_LWZ: + case PC_LWZU: + case PC_LMW: + case PC_STB: + case PC_STBU: + case PC_STH: + case PC_STHU: + case PC_STW: + case PC_STWU: + case PC_STMW: + case PC_LFS: + case PC_LFSU: + case PC_LFD: + case PC_LFDU: + case PC_STFS: + case PC_STFSU: + case PC_STFD: + case PC_STFDU: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_LBZX: + case PC_LBZUX: + case PC_LHZX: + case PC_LHZUX: + case PC_LHAX: + case PC_LHAUX: + case PC_LHBRX: + case PC_LWZX: + case PC_LWZUX: + case PC_LWBRX: + case PC_STBX: + case PC_STBUX: + case PC_STHX: + case PC_STHUX: + case PC_STHBRX: + case PC_STWX: + case PC_STWUX: + case PC_STWBRX: + case PC_LFSX: + case PC_LFSUX: + case PC_LFDX: + case PC_LFDUX: + case PC_STFSX: + case PC_STFSUX: + case PC_STFDX: + case PC_STFDUX: + case PC_LWARX: + case PC_LSWX: + case PC_STFIWX: + case PC_STSWX: + case PC_STWCX: + case PC_ECIWX: + case PC_ECOWX: + case PC_DCREAD: + case PC_TLBSX: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_DCBF: + case PC_DCBST: + case PC_DCBT: + case PC_DCBTST: + case PC_DCBZ: + case PC_DCBI: + case PC_ICBI: + case PC_DCCCI: + case PC_ICBT: + case PC_ICCCI: + case PC_ICREAD: + case PC_DCBA: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_ADD: + case PC_ADDC: + case PC_ADDE: + case PC_DIVW: + case PC_DIVWU: + case PC_MULHW: + case PC_MULHWU: + case PC_MULLW: + case PC_SUBF: + case PC_SUBFC: + case PC_SUBFE: + bits |= instr->args[2].data.reg.reg << 11; + case PC_ADDME: + case PC_ADDZE: + case PC_NEG: + case PC_SUBFME: + case PC_SUBFZE: + case PC_MFROM: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_ADDI: + case PC_ADDIC: + case PC_ADDICR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_ADDIS: + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[0].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_MULLI: + case PC_SUBFIC: + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_LI: + case PC_LIS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[1], wop) & 0xFFFF; + break; + + case PC_ANDI: + case PC_ANDIS: + case PC_ORI: + case PC_ORIS: + case PC_XORI: + case PC_XORIS: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_AND: + case PC_OR: + case PC_XOR: + case PC_NAND: + case PC_NOR: + case PC_EQV: + case PC_ANDC: + case PC_ORC: + case PC_SLW: + case PC_SRW: + case PC_SRAW: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_EXTSH: + case PC_EXTSB: + case PC_CNTLZW: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_MR: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_NOT: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_SRAWI: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[2].data.imm.value & 31) << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_RLWINM: + case PC_RLWIMI: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[2].data.imm.value & 31) << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_RLWNM: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_CMP: + case PC_CMPL: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_CMPI: + case PC_CMPLI: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_MTXER: + case PC_MTCTR: + case PC_MTLR: + case PC_MTMSR: + case PC_MFMSR: + case PC_MFXER: + case PC_MFCTR: + case PC_MFLR: + case PC_MFCR: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_MFFS: + bits |= instr->args[0].data.reg.reg << 21; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_MTCRF: + bits |= instr->args[0].data.imm.value << 12; + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MTFSF: + bits |= (instr->args[0].data.imm.value & 0xFF) << 17; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_FMR: + case PC_FABS: + case PC_FNEG: + case PC_FNABS: + case PC_FRES: + case PC_FRSQRTE: + case PC_FRSP: + case PC_FCTIW: + case PC_FCTIWZ: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_FADD: + case PC_FADDS: + case PC_FSUB: + case PC_FSUBS: + case PC_FDIV: + case PC_FDIVS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_FMADD: + case PC_FMADDS: + case PC_FMSUB: + case PC_FMSUBS: + case PC_FNMADD: + case PC_FNMADDS: + case PC_FNMSUB: + case PC_FNMSUBS: + case PC_FSEL: + bits |= instr->args[3].data.reg.reg << 11; + case PC_FMUL: + case PC_FMULS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 6; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_FCMPU: + case PC_FCMPO: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_MTSPR: + if (instr->args[0].kind == PCOp_REGISTER) { + CError_ASSERT(1027, instr->args[0].arg == RegClass_SPR); + CError_ASSERT(1028, instr->args[0].data.reg.reg < 4); + bits |= ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x1F) << 16) + + ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x3E0) << 6); + } else if (instr->args[0].kind == PCOp_SYSREG && instr->args[0].arg == 0) { + bits |= ((instr->args[0].data.reg.reg & 0x1F) << 16) + + ((instr->args[0].data.reg.reg & 0x3E0) << 6); + } else { + CError_FATAL(1033); + } + + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MTDCR: + if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= ((instr->args[0].data.imm.value & 0x1F) << 16) + + ((instr->args[0].data.imm.value & 0x3E0) << 6); + } else { + CError_FATAL(1042); + } + + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MFSPR: + bits |= instr->args[0].data.reg.reg << 21; + + if (instr->args[1].kind == PCOp_REGISTER && instr->args[1].arg == RegClass_SPR) { + CError_ASSERT(1055, instr->args[1].data.reg.reg < 4); + bits |= ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x1F) << 16) + + ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x3E0) << 6); + } else if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { + bits |= ((instr->args[1].data.reg.reg & 0x1F) << 16) + + ((instr->args[1].data.reg.reg & 0x3E0) << 6); + } else { + CError_FATAL(1060); + } + break; + + case PC_MFDCR: + bits |= instr->args[0].data.reg.reg << 21; + + if (instr->args[1].kind == PCOp_IMMEDIATE) { + bits |= ((instr->args[1].data.imm.value & 0x1F) << 16) + + ((instr->args[1].data.imm.value & 0x3E0) << 6); + } else { + CError_FATAL(1069); + } + break; + + case PC_LSWI: + case PC_STSWI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 31) << 11; + break; + + case PC_MCRFS: + bits |= (instr->args[1].data.imm.value & 7) << 18; + case PC_MCRXR: + bits |= instr->args[0].data.reg.reg << 23; + break; + + case PC_MFTB: + bits |= instr->args[0].data.reg.reg << 21; + if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { + if (instr->args[1].data.reg.reg == 284) + bits |= 0xC4000u; + else if (instr->args[1].data.reg.reg == 285) + bits |= 0xD4000u; + else + CError_FATAL(1100); + } else { + CError_FATAL(1103); + } + break; + + case PC_MTSR: + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[0].data.imm.value & 15) << 16; + break; + + case PC_MFSR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= (instr->args[1].data.imm.value & 15) << 16; + break; + + case PC_MFSRIN: + case PC_MTSRIN: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_MTFSB0: + case PC_MTFSB1: + bits |= (instr->args[0].data.imm.value & 31) << 21; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_MTFSFI: + bits |= instr->args[0].data.reg.reg << 23; + bits |= (instr->args[1].data.imm.value & 15) << 12; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_FSQRT: + case PC_FSQRTS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_TLBIE: + case PC_TLBLD: + case PC_TLBLI: + bits |= instr->args[0].data.reg.reg << 11; + break; + + case PC_TW: + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_TWI: + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_OPWORD: + CError_ASSERT(1176, instr->args[0].kind != PCOp_MEMORY); + bits = pcode_update_mem_labeldiff_imm(instr, &instr->args[0], wop); + break; + + case PC_MASKG: + case PC_MASKIR: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_LSCBX: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_DIV: + case PC_DIVS: + case PC_DOZ: + case PC_MUL: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_NABS: + case PC_ABS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_CLCS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_DOZI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_RLMI: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_SLE: + case PC_SLEQ: + case PC_SLLQ: + case PC_SLQ: + case PC_SRAQ: + case PC_SRE: + case PC_SREA: + case PC_SREQ: + case PC_SRLQ: + case PC_SRQ: + case PC_RRIB: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_SLIQ: + case PC_SLLIQ: + case PC_SRAIQ: + case PC_SRIQ: + case PC_SRLIQ: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 31) << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 1; + break; + + case PC_TLBRE: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 1) << 11; + break; + + case PC_TLBWE: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 1) << 11; + break; + + case PC_WRTEE: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_WRTEEI: + bits |= instr->args[0].data.imm.value << 15; + break; + + case PC_DSTT: + case PC_DSTSTT: + bits |= 0x2000000u; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 3) << 21; + break; + + case PC_DST: + case PC_DSTST: + bits |= (instr->args[3].data.imm.value & 1) << 25; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 3) << 21; + break; + + case PC_DSSALL: + bits |= 0x2000000u; + break; + + case PC_DSS: + bits |= (instr->args[1].data.imm.value & 1) << 25; + bits |= (instr->args[0].data.imm.value & 3) << 21; + break; + + case PC_LVEBX: + case PC_LVEHX: + case PC_LVEWX: + case PC_LVSL: + case PC_LVSR: + case PC_LVX: + case PC_LVXL: + case PC_STVEBX: + case PC_STVEHX: + case PC_STVEWX: + case PC_STVX: + case PC_STVXL: + case PC_VADDCUW: + case PC_VADDFP: + case PC_VADDSBS: + case PC_VADDSHS: + case PC_VADDSWS: + case PC_VADDUBM: + case PC_VADDUBS: + case PC_VADDUHM: + case PC_VADDUHS: + case PC_VADDUWM: + case PC_VADDUWS: + case PC_VAND: + case PC_VANDC: + case PC_VAVGSB: + case PC_VAVGSH: + case PC_VAVGSW: + case PC_VAVGUB: + case PC_VAVGUH: + case PC_VAVGUW: + case PC_VMAXFP: + case PC_VMAXSB: + case PC_VMAXSH: + case PC_VMAXSW: + case PC_VMAXUB: + case PC_VMAXUH: + case PC_VMAXUW: + case PC_VMINFP: + case PC_VMINSB: + case PC_VMINSH: + case PC_VMINSW: + case PC_VMINUB: + case PC_VMINUH: + case PC_VMINUW: + case PC_VMRGHB: + case PC_VMRGHH: + case PC_VMRGHW: + case PC_VMRGLB: + case PC_VMRGLH: + case PC_VMRGLW: + case PC_VMULESB: + case PC_VMULESH: + case PC_VMULEUB: + case PC_VMULEUH: + case PC_VMULOSB: + case PC_VMULOSH: + case PC_VMULOUB: + case PC_VMULOUH: + case PC_VNOR: + case PC_VOR: + case PC_VPKPX: + case PC_VPKSHSS: + case PC_VPKSHUS: + case PC_VPKSWSS: + case PC_VPKSWUS: + case PC_VPKUHUM: + case PC_VPKUHUS: + case PC_VPKUWUM: + case PC_VPKUWUS: + case PC_VRLB: + case PC_VRLH: + case PC_VRLW: + case PC_VSL: + case PC_VSLB: + case PC_VSLH: + case PC_VSLO: + case PC_VSLW: + case PC_VSR: + case PC_VSRAB: + case PC_VSRAH: + case PC_VSRAW: + case PC_VSRB: + case PC_VSRH: + case PC_VSRO: + case PC_VSRW: + case PC_VSUBCUW: + case PC_VSUBFP: + case PC_VSUBSBS: + case PC_VSUBSHS: + case PC_VSUBSWS: + case PC_VSUBUBM: + case PC_VSUBUBS: + case PC_VSUBUHM: + case PC_VSUBUHS: + case PC_VSUBUWM: + case PC_VSUBUWS: + case PC_VSUMSWS: + case PC_VSUM2SWS: + case PC_VSUM4SBS: + case PC_VSUM4SHS: + case PC_VSUM4UBS: + case PC_VXOR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_VCFSX: + case PC_VCFUX: + case PC_VCTSXS: + case PC_VCTUXS: + case PC_VSPLTB: + case PC_VSPLTH: + case PC_VSPLTW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 31) << 16; + break; + + case PC_VEXPTEFP: + case PC_VLOGEFP: + case PC_VREFP: + case PC_VRFIM: + case PC_VRFIN: + case PC_VRFIP: + case PC_VRFIZ: + case PC_VRSQRTEFP: + case PC_VUPKHPX: + case PC_VUPKHSB: + case PC_VUPKHSH: + case PC_VUPKLPX: + case PC_VUPKLSB: + case PC_VUPKLSH: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_VCMPBFP: + case PC_VCMPEQFP: + case PC_VCMPEQUB: + case PC_VCMPEQUH: + case PC_VCMPEQUW: + case PC_VCMPGEFP: + case PC_VCMPGTFP: + case PC_VCMPGTSB: + case PC_VCMPGTSH: + case PC_VCMPGTSW: + case PC_VCMPGTUB: + case PC_VCMPGTUH: + case PC_VCMPGTUW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + bits |= 0x400; + break; + + case PC_VSPLTISB: + case PC_VSPLTISH: + case PC_VSPLTISW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= (instr->args[1].data.imm.value & 31) << 16; + break; + + case PC_VMHADDSHS: + case PC_VMHRADDSHS: + case PC_VMLADDUHM: + case PC_VMSUMMBM: + case PC_VMSUMSHM: + case PC_VMSUMSHS: + case PC_VMSUMUBM: + case PC_VMSUMUHM: + case PC_VMSUMUHS: + case PC_VPERM: + case PC_VSEL: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= instr->args[3].data.reg.reg << 6; + break; + + case PC_VMADDFP: + case PC_VNMSUBFP: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 6; + bits |= instr->args[3].data.reg.reg << 11; + break; + + case PC_VSLDOI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 15) << 6; + break; + + case PC_VMR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_VMRP: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_MFVSCR: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_MTVSCR: + bits |= instr->args[0].data.reg.reg << 11; + break; + + case PC_EIEIO: + case PC_ISYNC: + case PC_SYNC: + case PC_RFI: + case PC_NOP: + case PC_SC: + case PC_TLBIA: + case PC_TLBSYNC: + case PC_TRAP: + case PC_DSA: + case PC_ESA: + case PC_RFCI: + break; + + default: + CError_FATAL(2203); + } + + return CTool_EndianConvertWord32(bits); } -static void targetinstruction() { +static PCode *targetinstruction(PCodeLabel *label) { + PCodeBlock *block = label->block; + while (block->pcodeCount == 0) + block = block->nextBlock; + return block->firstPCode; } -static void invertybit() { +static void invertybit(PCode *instr, SInt32 value) { + if (instr->op == PC_BC) { + if (instr->args[0].data.imm.value & 1) { + if (value < 0) + instr->flags |= fBranchNotTaken; + else + instr->flags |= fBranchTaken; + } + } else if (instr->op == PC_BCCTR || instr->op == PC_BCLR) { + if (instr->args[0].data.imm.value & 1) + instr->flags |= fBranchTaken; + } + + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; + else if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; + else if (value < 0) + instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; + else + instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; } -static void insertlongbranches() { +static void insertlongbranches(SInt32 mask) { + PCodeBlock *block; + PCodeLabel *label; + SInt32 i; + + i = 0; + for (block = pcbasicblocks; block; block = block->nextBlock) { + block->codeOffset = i; + if (block->pcodeCount) { + i += block->pcodeCount * 4; + if (block->pcodeCount && (block->lastPCode->flags & fPCodeFlag1)) + i += 4; + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount && (block->lastPCode->flags & fPCodeFlag1)) { + switch (block->lastPCode->op) { + case PC_BT: + case PC_BF: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[2].kind == PCOp_LABEL) { + label = block->lastPCode->args[2].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + block->lastPCode->op = (block->lastPCode->op == PC_BT) ? PC_BF : PC_BT; + block->lastPCode->args[2].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BC: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[3].kind == PCOp_LABEL) { + label = block->lastPCode->args[3].data.label.label; + i = label->block->codeOffset - i; + invertybit(block->lastPCode, i); + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->args[0].data.imm.value & 30) { + case 0: + case 2: + case 8: + case 10: + block->lastPCode->args[0].data.imm.value ^= 11; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 16: + case 18: + block->lastPCode->args[0].data.imm.value ^= 3; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 4: + case 12: + block->lastPCode->args[0].data.imm.value ^= 9; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 20: + deletepcode(block->lastPCode); + break; + default: + CError_FATAL(2368); + } + + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BDNZ: + case PC_BDZ: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[0].kind == PCOp_LABEL) { + label = block->lastPCode->args[0].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->op) { + case PC_BDZ: + block->lastPCode->op = PC_BDNZ; + break; + case PC_BDNZ: + block->lastPCode->op = PC_BDZ; + break; + default: + CError_FATAL(2389); + } + + block->lastPCode->args[0].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BDNZT: + case PC_BDNZF: + case PC_BDZT: + case PC_BDZF: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[2].kind == PCOp_LABEL) { + label = block->lastPCode->args[2].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->op) { + case PC_BDNZT: + block->lastPCode->op = PC_BDZF; + break; + case PC_BDNZF: + block->lastPCode->op = PC_BDZT; + break; + case PC_BDZT: + block->lastPCode->op = PC_BDNZF; + break; + case PC_BDZF: + block->lastPCode->op = PC_BDNZT; + break; + default: + CError_FATAL(2420); + } + + block->lastPCode->args[2].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + } + } + } } -void optimizefinalbranches() { +SInt32 optimizefinalbranches(SInt32 codesize) { + PCodeBlock *block; + PCodeBlock *block2; + PCode *instr; + SInt32 offset; + int changed; + int deleted; + PCodeLabel *label; + PCode *target; + + do { + changed = deleted = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount == 0) + continue; + + instr = block->lastPCode; + if (!(instr->flags & fPCodeFlag1)) + continue; + + offset = block->codeOffset + (block->pcodeCount - 1) * 4; + + if (instr->op == PC_B && instr->args[0].kind == PCOp_LABEL) { + label = instr->args[0].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[0].data.label.label) { + instr->args[0].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (target->op == PC_BLR) { + instr->op = PC_BLR; + changed = 1; + } + continue; + } + + if ((instr->op == PC_BT || instr->op == PC_BF) && instr->args[0].kind == PCOp_LABEL) { + block2 = instr->block; + label = instr->args[0].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[2].data.label.label) { + instr->args[2].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (copts.ppc_opt_bclr_bcctr) { + if (target->op == PC_BLR) { + if (instr->op == PC_BT) + instr->op = PC_BTLR; + else + instr->op = PC_BFLR; + instr->argCount = 2; + changed = 1; + } else if (target->op == PC_BCTR) { + if (instr->op == PC_BT) + instr->op = PC_BTCTR; + else + instr->op = PC_BFCTR; + instr->argCount = 2; + changed = 1; + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BLR && + label->block->codeOffset == (offset + 8) + ) { + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if (instr->op == PC_BT) + instr->op = PC_BFLR; + else + instr->op = PC_BTLR; + change_num_operands(instr, 2); + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BCTR && + label->block->codeOffset == (offset + 8) + ) { + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if (instr->op == PC_BT) + instr->op = PC_BFCTR; + else + instr->op = PC_BTCTR; + change_num_operands(instr, 2); + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } + } + continue; + } + + if ( + instr->op == PC_BC && + instr->args[3].kind == PCOp_LABEL && + !(PCODE_FLAG_SET_T(instr) & (fSideEffects | fLink)) + ) + { + block2 = instr->block; + label = instr->args[2].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[3].data.label.label) { + instr->args[3].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (copts.ppc_opt_bclr_bcctr) { + if (target->op == PC_BLR) { + instr->op = PC_BCLR; + instr->argCount = 3; + changed = 1; + } else if (target->op == PC_BCTR) { + instr->op = PC_BCCTR; + instr->argCount = 3; + changed = 1; + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BLR && + label->block->codeOffset == (offset + 8) + ) { + SInt32 val = instr->args[0].data.imm.value & 30; + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if ((val & 30) == 4) + instr->args[0].data.imm.value = val | 12; + else + instr->args[0].data.imm.value = val & 23; + instr->op = PC_BCLR; + instr->argCount = 3; + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BCTR && + label->block->codeOffset == (offset + 8) + ) { + SInt32 val = instr->args[0].data.imm.value & 30; + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if ((val & 30) == 4) + instr->args[0].data.imm.value = val | 12; + else + instr->args[0].data.imm.value = val & 23; + instr->op = PC_BCCTR; + instr->argCount = 3; + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } + } + } + } + + if (deleted) + codesize = pccomputeoffsets(); + } while (changed); + + return codesize; } -static void insert_align_nops() { +static SInt32 insert_align_nops(Object *func, SInt32 codesize) { + PCodeBlock *block; + int changed; + PCodeBlock *prev; + + do { + changed = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if ( + (block->flags & fPCBlockFlag6000) == fPCBlockFlag2000 && + (block->codeOffset & 7) && + block->pcodeCount < 8 && + (prev = block->prevBlock) && + !(prev->flags & fPCBlockFlag2000) + ) + { + if (prev->lastPCode && prev->lastPCode->op == PC_NOP && !(prev->lastPCode->flags & fSideEffects)) { + deletepcode(prev->lastPCode); + } else { + PCode *nop = makepcode(PC_NOP); + nop->flags &= ~fSideEffects; + appendpcode(prev, nop); + } + + codesize = pccomputeoffsets(); + changed = 1; + } + } + + if (changed) { + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSERT ALIGN NOPs"); + if (codesize > 32766) { + insertlongbranches(32766); + codesize = pccomputeoffsets(); + } + } + + } while (changed); + + return codesize; } -void assemblefunction() { +SInt32 assemblefunction(Object *func, EntryPoint *entrypoints) { + void *tbdata; + GList *gl; + PCodeBlock *block; + PCode *instr; + SInt32 offset2; + SInt32 codesize; + SInt32 tbsize; + SInt32 offset; + MachOSection *section; + EntryPoint *ep; + WeirdOperand wop; + + codesize = pccomputeoffsets(); + if (codesize <= 0) + PPCError_Error(190, func->name->name); + + if (copts.peephole || copts.optimizationlevel >= 3) + codesize = optimizefinalbranches(codesize); + + if (codesize > 32766) { + insertlongbranches(32766); + codesize = pccomputeoffsets(); + } + + if (copts.code_alignment > 4) + codesize = insert_align_nops(func, codesize); + + tbsize = 0; + if (copts.traceback) + tbdata = generate_traceback(codesize, CMangler_GetLinkName(func)->name, &tbsize, func); + + if (func->section == SECT_DEFAULT) + func->section = SECT_TEXT; + + offset = tbsize; + section = ObjGen_DeclareCode(func); + gl = ObjGen_GetSectionGList(section); + + codebase = gl->size; + AppendGListNoData(gl, codesize + tbsize); + + if (copts.isGeneratingDebugInfo) { + ObjGen_SymFunc(func); + ObjGen_Line(functionbodyoffset, 0); + ObjGen_DeclareSymInfo(); + } + + if (uses_globals && pic_base_reg) + ObjGen_DeclarePICBase(func, pic_base_pcodelabel->block->codeOffset); + + if (entrypoints) { + for (ep = entrypoints; ep; ep = ep->next) { + ObjGen_DeclareEntry(ep->object, ep->block->codeOffset); + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (offset2 = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset2 += 4) { + if (copts.isGeneratingDebugInfo && instr->sourceoffset != -1) + ObjGen_Line(instr->sourceoffset, offset2); + + *((UInt32 *) (*gl->data + codebase + offset2)) = assemblepcode(instr, offset2, &wop); + + if (wop.type != -1) + ObjGen_RelocateObj(section, offset2, wop.x2, wop.type); + } + } + + if (copts.isGeneratingDebugInfo) + ObjGenMach_SymFuncEnd(func, codesize); + + if (copts.traceback) + memcpy(*gl->data + codebase + codesize, tbdata, offset); + + if (copts.traceback) + return codesize + tbsize; + else + return codesize; } diff --git a/compiler_and_linker/unsorted/PCodeInfo.c b/compiler_and_linker/unsorted/PCodeInfo.c index 3646930..c93176c 100644 --- a/compiler_and_linker/unsorted/PCodeInfo.c +++ b/compiler_and_linker/unsorted/PCodeInfo.c @@ -1,8 +1,18 @@ -#include "compiler.h" -#include "compiler/objects.h" #include "compiler/PCodeInfo.h" -#include "compiler/PCodeUtilities.h" #include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" +#include "compiler/types.h" #pragma pool_strings on @@ -38,8 +48,7 @@ void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo) { *lo = -(1 << (bits - 1)); } } else { -#line 65 - CError_FATAL(); + CError_FATAL(65); } } @@ -83,8 +92,7 @@ int pcode_check_imm_bits(SInt32 value, int bits, char typechar) { if (forcedBits > 0 && value != ((value >> forcedBits) << forcedBits)) return 1; } else if (bits > 32) { -#line 110 - CError_FATAL(); + CError_FATAL(110); } return 0; @@ -154,10 +162,8 @@ PCode *vformatpcode(short opcode, va_list argList) { lastArg = pcode->args + pcode->argCount; arg = pcode->args; while (*format) { - if (arg >= lastArg) { -#line 189 - CError_FATAL(); - } + if (arg >= lastArg) + CError_FATAL(189); if (*format == ',' || *format == ';') format++; @@ -274,12 +280,10 @@ PCode *vformatpcode(short opcode, va_list argList) { arg->data.reg.effect = effect; break; case 'P': - if (isdigit(format[1])) { + if (isdigit(format[1])) format += pcode_const_from_format(format + 1, &thing); - } else { -#line 319 - CError_FATAL(); - } + else + CError_FATAL(319); tmp = va_arg(argList, int); tmp2 = -1; for (i = 0; i < 4; i++) { @@ -318,8 +322,7 @@ PCode *vformatpcode(short opcode, va_list argList) { arg->data.reg.reg = 0x11D; arg->data.reg.effect = effect; } else { -#line 353 - CError_FATAL(); + CError_FATAL(353); } pcsetsideeffects(pcode); arg->kind = PCOp_SYSREG; @@ -330,12 +333,10 @@ PCode *vformatpcode(short opcode, va_list argList) { case 'S': tmp2 = -1; - if (isdigit(format[1])) { + if (isdigit(format[1])) format += pcode_const_from_format(format + 1, &thing2); - } else { -#line 371 - CError_FATAL(); - } + else + CError_FATAL(371); for (i = 0; i < 4; i++) { if (thing2 == spr_to_sysreg[i]) { @@ -368,12 +369,10 @@ PCode *vformatpcode(short opcode, va_list argList) { tmp2 = (unsigned char) c; thing3 = 16; if (*format == 'a') { - if (isdigit(format[1])) { + if (isdigit(format[1])) tmp2 = (unsigned char) *(++format); - } else { -#line 408 - CError_FATAL(); - } + else + CError_FATAL(408); } if (isdigit(format[1])) { format += pcode_const_from_format(format + 1, &thing3); @@ -381,30 +380,24 @@ PCode *vformatpcode(short opcode, va_list argList) { 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(); - } + if (pcode_check_imm_bits(arg->data.imm.value, thing3, tmp2)) + CError_FATAL(419); 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(); - } + if (pcode_check_imm_bits(arg->data.imm.value, 6, 'u')) + CError_FATAL(429); 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(); - } + if (pcode_check_imm_bits(arg->data.imm.value, 10, 'u')) + CError_FATAL(438); break; case 'B': @@ -412,10 +405,8 @@ PCode *vformatpcode(short opcode, va_list argList) { 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(); - } + if (pcode_check_imm_bits(arg->data.imm.value, 5, 'u')) + CError_FATAL(448); break; case 'Q': @@ -428,10 +419,8 @@ PCode *vformatpcode(short opcode, va_list argList) { 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(); - } + if (pcode_check_imm_bits(arg->data.imm.value, 4, 'u')) + CError_FATAL(463); break; case 'l': @@ -441,8 +430,7 @@ PCode *vformatpcode(short opcode, va_list argList) { } else { arg->kind = PCOp_MEMORY; obj = va_arg(argList, Object *); -#line 476 - CError_ASSERT(obj->otype == OT_OBJECT); + CError_ASSERT(476, obj->otype == OT_OBJECT); arg->data.mem.obj = obj; arg->data.mem.offset = 0; arg->arg = 1; @@ -450,8 +438,7 @@ PCode *vformatpcode(short opcode, va_list argList) { break; case 'd': -#line 490 - CError_ASSERT(format[1] == '('); + CError_ASSERT(490, format[1] == '('); effect = EffectRead; format += 2; if (*format == '=') { @@ -462,8 +449,7 @@ PCode *vformatpcode(short opcode, va_list argList) { format++; } -#line 502 - CError_ASSERT(format[0] == 'b'); + CError_ASSERT(502, format[0] == 'b'); tmp = va_arg(argList, int); if (tmp == 0) @@ -477,8 +463,7 @@ PCode *vformatpcode(short opcode, va_list argList) { case 'm': obj = va_arg(argList, Object *); if (obj) { -#line 515 - CError_ASSERT(obj->otype == OT_OBJECT); + CError_ASSERT(515, obj->otype == OT_OBJECT); if (obj->datatype == DABSOLUTE) { arg->kind = PCOp_IMMEDIATE; @@ -490,7 +475,7 @@ PCode *vformatpcode(short opcode, va_list argList) { 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)); + pcode->alias = 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)) @@ -498,10 +483,9 @@ PCode *vformatpcode(short opcode, va_list argList) { pcode->flags |= fIsConst; } else { if (pcode->op == PC_ADDI) - pcode->_18 = make_alias(obj, arg->data.mem.offset, 1); + pcode->alias = make_alias(obj, arg->data.mem.offset, 1); } -#line 536 - CError_ASSERT(obj->datatype == DLOCAL || arg->data.mem.offset == 0); + CError_ASSERT(536, 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)) @@ -534,8 +518,7 @@ PCode *vformatpcode(short opcode, va_list argList) { case 'M': obj = va_arg(argList, Object *); if (obj) { -#line 578 - CError_ASSERT(obj->otype == OT_OBJECT); + CError_ASSERT(578, obj->otype == OT_OBJECT); if (obj->datatype == DABSOLUTE) { arg->kind = PCOp_IMMEDIATE; @@ -546,8 +529,7 @@ PCode *vformatpcode(short opcode, va_list argList) { 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); + CError_ASSERT(590, 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)) @@ -581,8 +563,7 @@ PCode *vformatpcode(short opcode, va_list argList) { break; default: -#line 629 - CError_FATAL(); + CError_FATAL(629); } while (format[1] && strchr("/<>|*", format[1])) { @@ -595,14 +576,13 @@ PCode *vformatpcode(short opcode, va_list argList) { case '*': case '|': case '>': - if (format[1] == 'p') { + if (format[1] == 'p') format++; - } else if (isdigit(format[1])) { + else if (isdigit(format[1])) format += pcode_const_from_format(format + 1, &thing4); - } else { -#line 659 - CError_FATAL(); - } + else + CError_FATAL(659); + break; } } @@ -736,10 +716,8 @@ int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, in 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) == 0 || strlen(name) > 3200 || name[0] < 0) + CError_FATAL(849); if (strlen(name) > 50) tmp = sprintf(buf, "%45.45s...", name); else @@ -911,32 +889,26 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); break; case 'X': -#line 1124 - CError_ASSERT(pa->data.reg.reg == 0); + CError_ASSERT(1124, 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); + CError_ASSERT(1129, 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); + CError_ASSERT(1134, 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); + CError_ASSERT(1139, pa->data.reg.reg == 0); buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); break; case 'P': - if (isdigit(format[1])) { + if (isdigit(format[1])) format += pcode_const_from_format(format + 1, &thing); - } else { -#line 1149 - CError_FATAL(); - } + else + CError_FATAL(1149); case 'S': case 'T': case 's': @@ -945,8 +917,7 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { } else { for (i = 0; i < 4; i++) { if (pa->data.reg.reg == spr_to_sysreg[i]) { -#line 1161 - CError_FATAL(); + CError_FATAL(1161); break; } } @@ -1002,8 +973,7 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { format++; tmp = *format; } else { -#line 1227 - CError_FATAL(); + CError_FATAL(1227); } } if ((tmp2 = isdigit(format[1]))) @@ -1046,14 +1016,12 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { 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] == '('); + CError_ASSERT(1283, format[1] == '('); format++; *(buf++) = *(format++); if (*format == '+') format++; -#line 1291 - CError_ASSERT(format[0] == 'b'); + CError_ASSERT(1291, 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; @@ -1088,8 +1056,7 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { case 'M': if (pa->kind == PCOp_MEMORY) { -#line 1335 - CError_ASSERT(pa->arg == RefType_8 || pa->arg == RefType_B || pa->arg == RefType_C); + CError_ASSERT(1335, 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); @@ -1107,8 +1074,7 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { break; default: -#line 1465 - CError_FATAL(); + CError_FATAL(1465); } while (format[1] && strchr("/<>|*", format[1])) { @@ -1121,14 +1087,13 @@ void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { case '*': case '|': case '>': - if (format[1] == 'p') { + if (format[1] == 'p') format++; - } else if (isdigit(format[1])) { + else if (isdigit(format[1])) format += pcode_const_from_format(format + 1, &thing4); - } else { -#line 1495 - CError_FATAL(); - } + else + CError_FATAL(1495); + break; } } @@ -1286,13 +1251,11 @@ int nbytes_loaded_or_stored_by(PCode *pcode) { return 16; default: -#line 2011 - CError_FATAL(); + CError_FATAL(2011); } } -#line 2014 - CError_FATAL(); + CError_FATAL(2014); return 0; } diff --git a/compiler_and_linker/unsorted/PCodeListing.c b/compiler_and_linker/unsorted/PCodeListing.c index 922b63f..c95400d 100644 --- a/compiler_and_linker/unsorted/PCodeListing.c +++ b/compiler_and_linker/unsorted/PCodeListing.c @@ -134,10 +134,8 @@ static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) { fflush(pcfile); - if (pclist_bad_operand) { -#line 252 - CError_FATAL(); - } + if (pclist_bad_operand) + CError_FATAL(252); } static void pclistonoff(int flag) { @@ -282,10 +280,8 @@ void pclistblocks_start_scheduler(char *str1, char *str2) { } void pclistblocks_end_scheduler(void) { - if (pclist_bad_operand) { -#line 1318 - CError_FATAL(); - } + if (pclist_bad_operand) + CError_FATAL(1318); } static void printheapsize(void) { @@ -316,10 +312,8 @@ int formatalias(Alias *alias, char *buf, int bufSize) { case AliasType0: case AliasType1: name = CMangler_GetLinkName(alias->object)->name; - if (!strlen(name) || name[0] < 0) { -#line 1458 - CError_FATAL(); - } + if (!strlen(name) || name[0] < 0) + CError_FATAL(1458); if (strlen(name) + 16 > bufSize) return sprintf(buf, "..."); @@ -369,8 +363,7 @@ int formatalias(Alias *alias, char *buf, int bufSize) { return len; default: -#line 1543 - CError_FATAL(); + CError_FATAL(1543); return 0; } } @@ -399,10 +392,8 @@ int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) { case AliasType0: case AliasType1: name = CMangler_GetLinkName(alias->object)->name; - if (!strlen(name) || name[0] < 0) { -#line 1581 - CError_FATAL(); - } + if (!strlen(name) || name[0] < 0) + CError_FATAL(1581); switch (alias->object->datatype) { case DNONLAZYPTR: @@ -472,8 +463,7 @@ int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) { return len; default: -#line 1661 - CError_FATAL(); + CError_FATAL(1661); return 0; } } diff --git a/compiler_and_linker/unsorted/PCodeUtilities.c b/compiler_and_linker/unsorted/PCodeUtilities.c index b0191e9..89c4c1f 100644 --- a/compiler_and_linker/unsorted/PCodeUtilities.c +++ b/compiler_and_linker/unsorted/PCodeUtilities.c @@ -1,10 +1,11 @@ #include "compiler/PCodeUtilities.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" -#include "compiler/CError.h" +#include "compiler/Registers.h" #include "compiler/enode.h" #include "compiler/objects.h" -#include "compiler.h" void pcsetrecordbit(PCode *pc) { int reg; @@ -29,14 +30,12 @@ void pcsetrecordbit(PCode *pc) { change_num_operands(pc, 5); pc->op = PC_ADDICR; -#line 76 - CError_ASSERT(pc->args[3].kind == PCOp_PLACEHOLDEROPERAND); + CError_ASSERT(76, 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); + CError_ASSERT(80, 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; @@ -59,8 +58,7 @@ void pcsetrecordbit(PCode *pc) { pc->argCount++; } -#line 105 - CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND); + CError_ASSERT(105, arg->kind == PCOp_PLACEHOLDEROPERAND); arg->kind = PCOp_REGISTER; arg->arg = RegClass_CRFIELD; arg->data.reg.reg = reg; @@ -103,8 +101,7 @@ void pcsetlinkbit(PCode *pc) { argIdx--; } -#line 169 - CError_ASSERT(arg->kind == PCOp_PLACEHOLDEROPERAND); + CError_ASSERT(169, arg->kind == PCOp_PLACEHOLDEROPERAND); arg->kind = PCOp_REGISTER; arg->arg = RegClass_SPR; arg->data.reg.reg = 1; @@ -164,7 +161,7 @@ void branch_always(PCodeLabel *label) { makepcblock(); } -void branch_decrement_always(short opcode, PCodeLabel *label) { +void branch_decrement_always(Opcode opcode, PCodeLabel *label) { PCodeLabel *tmplabel = makepclabel(); emitpcode(opcode, label); pcbranch(pclastblock, label); @@ -181,10 +178,10 @@ void branch_indirect(Object *obj) { int branch_count_volatiles(void) { int count = 0; int i; - char rclass; + RegClass rclass; for (rclass = 0; rclass < RegClassMax; rclass++) { - for (i = 0; i < n_scratch_registers[(char)rclass]; i++) { + for (i = 0; i < n_scratch_registers[rclass]; i++) { count++; } } @@ -194,15 +191,15 @@ int branch_count_volatiles(void) { PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) { int i; - char rclass; + RegClass rclass; for (rclass = RegClassMax - 1; rclass >= 0; rclass--) { - for (i = 0; i < n_scratch_registers[(char)rclass]; i++) { + for (i = 0; i < n_scratch_registers[rclass]; i++) { arglist->kind = PCOp_REGISTER; arglist->arg = rclass; - arglist->data.reg.reg = scratch_registers[(char)rclass][i]; + arglist->data.reg.reg = scratch_registers[rclass][i]; arglist->data.reg.effect = EffectWrite; - if (masks[(char)rclass] & (1 << scratch_registers[(char)rclass][i])) + if (masks[rclass] & (1 << scratch_registers[rclass][i])) arglist->data.reg.effect |= EffectRead; arglist++; } @@ -254,7 +251,7 @@ void branch_subroutine_ctr(UInt32 *masks) { recordexceptionactions(pc, current_statement->dobjstack); } -void add_immediate(short dest_reg, short base_reg, Object *obj, short offset) { +void add_immediate(short dest_reg, short base_reg, Object *obj, SInt16 offset) { short tmp_reg = base_reg; if (obj && offset && obj->datatype != DLOCAL) { @@ -269,11 +266,10 @@ void add_immediate(short dest_reg, short base_reg, Object *obj, short offset) { 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 *add_immediate_lo(short dest_reg, short base_reg, Object *obj, SInt16 offset, char add_to_block) { PCode *pc; -#line 577 - CError_ASSERT(obj); + CError_ASSERT(577, obj); pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset); if (add_to_block) @@ -289,12 +285,10 @@ PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, 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); + CError_ASSERT(601, tmp_reg); pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset); } else { -#line 606 - CError_ASSERT(base_reg == 0); + CError_ASSERT(606, base_reg == 0); pc = makepcode(PC_LIS, dest_reg, obj, offset); } @@ -303,7 +297,7 @@ PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, return pc; } -void load_store_register(short opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) { +void load_store_register(Opcode opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) { short addi_tmp; short offset_reg1; short offset_reg2; diff --git a/compiler_and_linker/unsorted/PPCError.c b/compiler_and_linker/unsorted/PPCError.c index 2ba28bd..7b87e05 100644 --- a/compiler_and_linker/unsorted/PPCError.c +++ b/compiler_and_linker/unsorted/PPCError.c @@ -8,8 +8,7 @@ static void PPCError_GetErrorString(char *str, short code) { short scode; scode = (short) code; -#line 40 - CError_ASSERT(scode >= 100 && scode < 212); + CError_ASSERT(40, scode >= 100 && scode < 212); COS_GetString(str, 10001, scode - 99); } diff --git a/compiler_and_linker/unsorted/Peephole.c b/compiler_and_linker/unsorted/Peephole.c index e69de29..3779d39 100644 --- a/compiler_and_linker/unsorted/Peephole.c +++ b/compiler_and_linker/unsorted/Peephole.c @@ -0,0 +1,2753 @@ +#include "compiler/Peephole.h" +#include "compiler/CompilerTools.h" +#include "compiler/InstrSelection.h" +#include "compiler/PCode.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/Scheduler.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Alias.h" +#include "compiler/CParser.h" + +typedef int (*PeepholeFunc)(PCode *instr, UInt32 *masks); + +typedef struct Pattern { + struct Pattern *next; + PeepholeFunc func; +} Pattern; + +typedef struct LiveRegs { + UInt32 x0; + UInt32 x4; + UInt32 x8; + UInt32 xC; +} LiveRegs; + +static LiveRegs *liveregs[RegClassMax]; +static Pattern *peepholepatterns[OPCODE_MAX]; +static PCode **defininginstruction; + +static void computeregisterusedefs(void) { + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + int i; + RegClass rclass; + LiveRegs *lr; + UInt32 array1[RegClassMax]; + UInt32 array2[RegClassMax]; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (rclass = 0; rclass < RegClassMax; rclass++) { + array1[rclass] = 0; + array2[rclass] = 0; + } + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectRead) && + !((1 << op->data.reg.reg) & array2[op->arg]) + ) + array1[op->arg] |= 1 << op->data.reg.reg; + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectWrite) && + !((1 << op->data.reg.reg) & array1[op->arg]) + ) + array2[op->arg] |= 1 << op->data.reg.reg; + } + } + + for (rclass = 0; rclass < RegClassMax; rclass++) { + lr = liveregs[rclass] + block->blockIndex; + lr->x0 = array1[rclass]; + lr->x4 = array2[rclass]; + if (rclass == RegClass_GPR) { + lr->x8 = 1 << 1; + lr->xC = 1 << 1; + } else { + lr->x8 = 0; + lr->xC = 0; + } + } + } +} + +static void computeliveness(LiveRegs *lrarray, UInt32 x) { + PCodeBlock *block; + LiveRegs *lr; + PCLink *link; + UInt32 newC; + UInt32 new8; + int i; + int flag; + + flag = 1; + while (flag) { + flag = 0; + i = pcblockcount; + while (i) { + if ((block = depthfirstordering[--i])) { + lr = lrarray + block->blockIndex; + newC = x; + for (link = block->successors; link; link = link->nextLink) + newC |= lrarray[link->block->blockIndex].x8; + lr->xC = newC; + + new8 = lr->x0 | (lr->xC & ~lr->x4); + if (new8 != lr->x8) { + lr->x8 = new8; + flag = 1; + } + } + } + } +} + +static void computeliveregisters(Object *func) { + Type *returntype; + RegClass rclass; + + returntype = TYPE_FUNC(func->type)->functype; + + for (rclass = 0; rclass < RegClassMax; rclass++) + liveregs[rclass] = lalloc(sizeof(LiveRegs) * pcblockcount); + + computedepthfirstordering(); + computeregisterusedefs(); + + if (TYPE_FITS_IN_REGISTER(returntype)) { + liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 3; + if (TYPE_IS_8BYTES(returntype)) + liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 4; + } else if (IS_TYPE_FLOAT(returntype)) { + liveregs[RegClass_FPR][epilogue->blockIndex].x0 |= 1 << 1; + } else if (IS_TYPE_VECTOR(returntype)) { + liveregs[RegClass_VR][epilogue->blockIndex].x0 |= 1 << 2; + } + + for (rclass = 0; rclass < RegClassMax; rclass++) { + if (rclass == RegClass_GPR) + computeliveness(liveregs[rclass], 2); + else + computeliveness(liveregs[rclass], 0); + } +} + +static void computeinstructionpredecessors(PCodeBlock *block) { + PCode *nop; + RegClass rclass; + SInt32 i; + SInt32 defID; + SInt32 totalOps; + PCode *instr; + PCodeArg *op; + PCode *array[RegClassMax][32]; + + nop = makepcode(PC_NOP); + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (i = 0; i < 32; i++) { + array[rclass][i] = nop; + } + } + + totalOps = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) + totalOps += instr->argCount; + + if (totalOps) { + defininginstruction = oalloc(sizeof(PCode *) * totalOps); + for (i = 0; i < totalOps; i++) + defininginstruction[i] = nop; + + defID = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + instr->defID = defID; + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) + defininginstruction[defID + i] = array[op->arg][op->data.reg.reg]; + } + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + array[op->arg][op->data.reg.reg] = instr; + } + + defID += instr->argCount; + } + } +} + +static int dead(PCode *instr, UInt32 *masks) { + int i; + PCodeArg *op; + + if (instr->block->flags & (fPCBlockFlag1 | fPCBlockFlag2)) + return 0; + if (instr->flags & (fPCodeFlag1 | fPCodeFlag4 | fPCodeFlag8 | fIsVolatile | fSideEffects)) + return 0; + if (!instr->block->predecessors) + return 1; + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectWrite) && + ((1 << op->data.reg.reg) & masks[op->arg]) + ) + return 0; + } + + return 1; +} + +static int definedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { + PCode *instr; + PCodeArg *op; + int i; + + for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) + return 1; + } + } + + return 0; +} + +static int usedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { + PCode *instr; + PCodeArg *op; + int i; + + for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) + return 1; + } + } + + return 0; +} + +static int isSPRlive(PCode *instr, int reg) { + PCode *scan; + PCodeArg *op; + int i; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, RegClass_SPR, reg)) + return 1; + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_SPR, reg)) + return 0; + } + } + + return 0; +} + +static SInt32 extractedbits(PCode *instr) { + SInt32 a = instr->args[2].data.imm.value; + SInt32 b = instr->args[3].data.imm.value; + SInt32 c = instr->args[4].data.imm.value; + SInt32 val; + + if (b <= c) + val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) & ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); + else + val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) | ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); + + return ((UInt32) val >> a) | (val << (32 - a)); +} + +static int canmergemasks(SInt32 b1, SInt32 c1, SInt32 a, SInt32 b2, SInt32 c2, short *first, short *last) { + SInt32 val1; + SInt32 val2; + + if (b1 <= c1) + val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) & ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); + else + val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) | ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); + + if (b2 <= c2) + val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) & ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); + else + val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) | ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); + + return ismaskconstant(val2 & ((val1 << a) | ((UInt32) val1 >> (32 - a))), first, last); +} + +static int canuseupdatetest(PCodeBlock *block, PCode *instr, int count1, int count2, int count3, int count4, int count5) { + int i; + PCLink *link; + + while (instr) { + if (++count1 > 17) + return 1; + + switch (instr->op) { + case PC_DIVW: + case PC_DIVWU: + case PC_MULHW: + case PC_MULHWU: + case PC_MULLI: + case PC_MULLW: + return count3 == 0; + case PC_MTXER: + case PC_MTCTR: + case PC_MTLR: + case PC_MTCRF: + case PC_MTMSR: + case PC_MTSPR: + case PC_MFMSR: + case PC_MFSPR: + case PC_MFXER: + case PC_MFCTR: + case PC_MFLR: + case PC_MFCR: + case PC_ECIWX: + case PC_ECOWX: + case PC_DCBI: + case PC_ICBI: + case PC_MCRFS: + case PC_MCRXR: + case PC_MFTB: + case PC_MFSR: + case PC_MTSR: + case PC_MFSRIN: + case PC_MTSRIN: + case PC_MTFSB0: + case PC_MTFSB1: + case PC_MTFSFI: + case PC_SC: + case PC_TLBIA: + case PC_TLBIE: + case PC_TLBLD: + case PC_TLBLI: + case PC_TLBSYNC: + case PC_TW: + case PC_TRAP: + case PC_TWI: + case PC_MFROM: + case PC_DSA: + case PC_ESA: + return 1; + case PC_CRAND: + case PC_CRANDC: + case PC_CREQV: + case PC_CRNAND: + case PC_CRNOR: + case PC_CROR: + case PC_CRORC: + case PC_CRXOR: + case PC_MCRF: + if (++count5 > 1) + return 1; + } + + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) { + if (++count4 > 1) + return 1; + } else if (instr->flags & fPCodeFlag1) { + if (++count2 > 2) + return 1; + + for (i = 0; i < instr->argCount; i++) { + if (PC_OP_IS_ANY_REGISTER(&instr->args[i], RegClass_CRFIELD)) { + ++count3; + break; + } + } + } + + instr = instr->nextPCode; + } + + if (block && block->successors) { + for (link = block->successors; link; link = link->nextLink) { + if (link->block && !canuseupdatetest(link->block, link->block->firstPCode, count1, count2, count3, count4, count5)) + return 0; + } + } + + return 1; +} + +static int canuseupdate(PCode *instr) { + return canuseupdatetest(instr->block, instr->nextPCode, 0, 0, 0, 0, 0); +} + +static int MR_Rx_Rx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int FMR_Fx_Fx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_Vx_Vx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int MR_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_MR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !definedbetween(instr, defInstr, &instr->args[0]) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int FMR_FMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_FMR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_VMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_VMR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_VMRP(PCode *instr, UInt32 *masks) { + PCode *prev = instr->prevPCode; + PCode *next = instr->nextPCode; + int prevFlag = 0; + int prevPermute = 0; + int nextFlag = 0; + int nextPermute = 0; + + if (prev) { + prevFlag = (prev->flags & fPCodeFlagC0000000) == fPCodeFlagC0000000; + prevPermute = uses_vpermute_unit(prev); + } + if (next) { + nextFlag = (next->flags & fPCodeFlagC0000000) == fPCodeFlagC0000000; + nextPermute = uses_vpermute_unit(next); + } + + if (prev) { + if (next) { + if (prevFlag && !prevPermute) { + if (nextFlag) { + if (!nextPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } else { + change_opcode(instr, PC_VMRP); + return 1; + } + } + } else { + if (prevFlag && !prevPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } + } else { + if (next && nextFlag && !nextPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } + + return 0; +} + +static int MR_CMPI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + PCodeArg op; + + if ( + instr->args[0].data.reg.reg == 0 && + instr->args[2].data.imm.value == 0 && + (PCODE_FLAG_SET_F(defInstr) & (fSideEffects | fPCodeFlag8000000 | fPCodeFlag80000000)) == (fPCodeFlag8000000 | fPCodeFlag80000000) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + if (defInstr->op == PC_ADDI) { + op.kind = PCOp_REGISTER; + op.arg = RegClass_SPR; + op.data.reg.reg = 0; + op.data.reg.effect = EffectRead | EffectWrite; + if (usedbetween(instr, defInstr, &op)) + return 0; + } + + pcsetrecordbit(defInstr); + deletepcode(instr); + return 1; + } + + return 0; +} + +static int EXTSB_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_EXTSB && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (extractedbits(instr) & 0xFFFFFF00) == 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int EXTSH_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_EXTSH && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (extractedbits(instr) & 0xFFFF0000) == 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int LBZ_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->op == PC_LBZ || defInstr->op == PC_LBZX) && + instr->args[2].data.imm.value == 0 && + instr->args[3].data.imm.value <= 24 && + instr->args[4].data.imm.value == 31 && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int LHZ_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->op == PC_LHZ || defInstr->op == PC_LHZX) && + instr->args[2].data.imm.value == 0 && + instr->args[3].data.imm.value <= 16 && + instr->args[4].data.imm.value == 31 && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int LHA_EXTSH(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_LHA && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + if ( + defInstr->op == PC_EXTSB && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + ) + { + if (defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg) { + if ( + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, PC_EXTSB); + deletepcode(defInstr); + return 1; + } + } else { + if (!definedbetween(instr, defInstr, &defInstr->args[1])) { + change_opcode(instr, PC_EXTSB); + instr->args[1] = defInstr->args[1]; + } else { + change_opcode(instr, PC_MR); + } + return 1; + } + } + + return 0; +} + +static int ADDI_L_S(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + SInt32 addleft; + SInt32 addright; + + if (defInstr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { + if (!PC_OP_IS_REGISTER(&instr->args[0], RegClass_GPR, instr->args[1].data.reg.reg)) { + if ( + instr->args[2].data.imm.value == 0 && + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) || canuseupdate(instr)) + ) + { + if (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) { + instr->args[2] = defInstr->args[2]; + } else { + instr->op++; + instr->args[1].data.reg.effect |= EffectWrite; + instr->args[2] = defInstr->args[2]; + } + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + addleft = 0x1FFFF; + addright = instr->args[2].data.imm.value; + if (defInstr->args[2].kind == PCOp_IMMEDIATE) { + addleft = defInstr->args[2].data.imm.value; + } else if (defInstr->args[2].kind == PCOp_MEMORY) { + if (defInstr->args[2].data.mem.obj->datatype == DLOCAL) + addleft = defInstr->args[2].data.mem.offset + defInstr->args[2].data.mem.obj->u.var.uid; + else if (addright == 0) + addleft = 0; + else + return 0; + } + + if (!FITS_IN_SHORT(addleft + addright)) + return 0; + + if ( + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if (defInstr->args[2].kind == PCOp_MEMORY) { + instr->args[2] = defInstr->args[2]; + instr->args[2].data.mem.offset += addright; + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { + instr->alias = make_alias( + instr->args[2].data.mem.obj, + instr->args[2].data.mem.offset, + nbytes_loaded_or_stored_by(instr) + ); + } + } else { + instr->args[2].data.imm.value = addleft + addright; + } + + deletepcode(defInstr); + return 1; + } + + if ( + instr->args[1].data.reg.reg != defInstr->args[1].data.reg.reg && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + if (defInstr->args[2].kind == PCOp_MEMORY && defInstr->args[2].data.mem.obj->datatype != DLOCAL) + return 0; + + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if (defInstr->args[2].kind == PCOp_MEMORY) { + instr->args[2] = defInstr->args[2]; + instr->args[2].data.mem.offset += addright; + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { + instr->alias = make_alias( + instr->args[2].data.mem.obj, + instr->args[2].data.mem.offset, + nbytes_loaded_or_stored_by(instr) + ); + } + } else { + instr->args[2].data.imm.value = addleft + addright; + } + + return 1; + } + } + } else { + if ( + defInstr->op == PC_MR && + PC_OP_IS_ANY_REGISTER(&defInstr->args[1], RegClass_GPR) && + defInstr->args[1].data.reg.reg != 0 && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + } + } + + return 0; +} + +static int ADDI_LU_SU(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + defInstr->op == PC_ADDI && + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) + ) + { + if ((instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) == 0) { + instr->op--; + instr->args[1].data.reg.effect &= ~EffectWrite; + instr->args[2].data.imm.value = 0; + } else { + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + } + + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int L_S_ADDI(PCode *instr, UInt32 *masks) { + PCode *scan; + PCodeArg *op; + int i; + short reg; + + if (instr->args[2].kind != PCOp_IMMEDIATE) + return 0; + + reg = instr->args[1].data.reg.reg; + if (!canuseupdate(instr)) + return 0; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, RegClass_GPR, reg)) + return 0; + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { + if (scan->op != PC_ADDI) + return 0; + if (scan->args[2].kind != PCOp_IMMEDIATE) + return 0; + + if ( + instr->args[2].data.imm.value == scan->args[2].data.imm.value && + scan->args[0].data.reg.reg == scan->args[1].data.reg.reg && + !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) + ) + { + if (!(masks[RegClass_GPR] & (1 << scan->args[0].data.reg.reg))) { + instr->args[2] = scan->args[2]; + } else { + instr->op++; + instr->args[1].data.reg.effect |= EffectWrite; + instr->args[2] = scan->args[2]; + } + + change_opcode(scan, PC_NOP); + change_num_operands(scan, 0); + deletepcode(scan); + return 1; + } + + return 0; + } + } + } + + return 0; +} + +static int LI_CMP_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + PCLink *link; + PCLink **ptr; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if ((defInstr->op == PC_CMPLI || defInstr->op == PC_CMPI) && defInstr->args[0].data.reg.reg == 0) { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + defInstr2->op == PC_LI && + defInstr2->args[1].kind == PCOp_IMMEDIATE && + (instr->op == PC_BT) == (defInstr2->args[1].data.imm.value == defInstr->args[2].data.imm.value) + ) + { + change_opcode(instr, PC_B); + instr->args[0] = instr->args[2]; + change_num_operands(instr, 1); + + defininginstruction[instr->defID] = defininginstruction[instr->defID + 1]; + + for (ptr = &instr->block->successors; (link = *ptr); ptr = &link->nextLink) { + if (link->block == instr->block->nextBlock) { + *ptr = link->nextLink; + break; + } + } + + for (ptr = &instr->block->nextBlock->predecessors; (link = *ptr); ptr = &link->nextLink) { + if (link->block == instr->block) { + *ptr = link->nextLink; + break; + } + } + } + } + } + + return 0; +} + +static int RLWINM_CMPLI_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if (defInstr->op == PC_CMPLI && defInstr->args[0].data.reg.reg == 0 && defInstr->args[2].data.imm.value == 0) { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + (PCODE_FLAG_SET_F(defInstr2) & (fSideEffects | fPCodeFlag8000000 | fPCodeFlag80000000)) == (fPCodeFlag8000000 | fPCodeFlag80000000) && + !usedbetween(defInstr, defInstr2, &defInstr->args[0]) && + !definedbetween(defInstr, defInstr2, &defInstr->args[0]) + ) + { + pcsetrecordbit(defInstr2); + defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + } + } + + return 0; +} + +static int LBZ_EXTSB_CMPI_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if ( + ( + (defInstr->op == PC_CMPI || defInstr->op == PC_CMPLI) && + defInstr->args[2].data.imm.value >= 0 && + defInstr->args[2].data.imm.value <= 127 + ) + || + ( + (defInstr->op == PC_EXTSB || defInstr->op == PC_EXTSH) && + (PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) + ) + ) + { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + defInstr2->op == PC_EXTSB && + defininginstruction[defInstr2->defID + 1]->op == PC_LBZ && + !(masks[RegClass_GPR] & (1 << defInstr2->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr2->args[0]) && + !usedbetween(defInstr, defInstr2, &defInstr2->args[0]) && + !definedbetween(defInstr, defInstr2, &defInstr2->args[1]) + ) + { + defInstr->args[1].data.reg.reg = defInstr2->args[1].data.reg.reg; + defininginstruction[defInstr->defID + 1] = defininginstruction[defInstr2->defID + 1]; + deletepcode(defInstr2); + return 1; + } + } + } + + return 0; +} + +static int FRSP_STFS(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID]; + + if ( + defInstr->op == PC_FRSP && + !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + instr->args[0].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int NOT_AND(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 2]; + + if ( + defInstr->op == PC_NOT && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + instr->args[2].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr->defID + 1]; + change_opcode(instr, PC_ANDC); + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int LI_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_LI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, PC_LI); + instr->args[1] = defInstr->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int VSPLTIS_VMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + short opcode = defInstr->op; + + if ( + (opcode == PC_VSPLTISB || opcode == PC_VSPLTISH || opcode == PC_VSPLTISW) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_VR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, opcode); + instr->args[1] = defInstr->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int L_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->flags & fPCodeFlag2) && + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int L_FMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->flags & fPCodeFlag2) && + !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int L_S(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID]; + SInt32 isIndexed; + SInt32 isFloat; + SInt32 isVector; + PCode *scan; + SInt32 loadSize; + SInt32 defInstrOffset; + SInt32 scanOffset; + SInt32 storeSize; + + if (PCODE_FLAG_SET_F(instr) & (fIsVolatile | fSideEffects | fPCodeFlag2000000)) + return 0; + if (PCODE_FLAG_SET_F(defInstr) & (fIsVolatile | fSideEffects | fPCodeFlag2000000)) + return 0; + + if ( + (defInstr->flags & fPCodeFlag2) && + PC_OP_IS_REGISTER(&defInstr->args[1], RegClass_GPR, instr->args[1].data.reg.reg) && + defInstr->args[2].kind == instr->args[2].kind && + !definedbetween(instr, defInstr, &instr->args[1]) + ) + { + if (instr->args[2].kind == PCOp_IMMEDIATE) { + if (instr->args[2].data.imm.value != defInstr->args[2].data.imm.value) + return 0; + } else if (instr->args[2].kind == PCOp_MEMORY) { + if (instr->args[2].data.mem.offset != defInstr->args[2].data.mem.offset || + instr->args[2].data.mem.obj != defInstr->args[2].data.mem.obj) + return 0; + } else if (instr->args[2].kind == PCOp_REGISTER && instr->args[2].arg == RegClass_GPR) { + if (instr->args[2].data.reg.reg != defInstr->args[2].data.reg.reg || + definedbetween(instr, defInstr, &instr->args[2])) + return 0; + } else { + return 0; + } + + isIndexed = 0; + isFloat = 0; + isVector = 0; + switch (defInstr->op) { + case PC_LBZX: + isIndexed = 1; + case PC_LBZ: + loadSize = 1; + break; + case PC_LHZX: + case PC_LHAX: + isIndexed = 1; + case PC_LHZ: + case PC_LHA: + loadSize = 2; + break; + case PC_LWZX: + isIndexed = 1; + case PC_LWZ: + loadSize = 4; + break; + case PC_LFSX: + isIndexed = 1; + case PC_LFS: + isFloat = 1; + loadSize = 4; + break; + case PC_LFDX: + isIndexed = 1; + case PC_LFD: + isFloat = 1; + loadSize = 8; + break; + case PC_LVX: + case PC_LVXL: + isIndexed = 1; + isVector = 1; + loadSize = 16; + break; + default: + return 0; + } + + switch (instr->op) { + case PC_STBX: + if (!isIndexed) return 0; + case PC_STB: + if (isFloat) return 0; + if (loadSize != 1) return 0; + break; + case PC_STHX: + if (!isIndexed) return 0; + case PC_STH: + if (isFloat) return 0; + if (loadSize != 2) return 0; + break; + case PC_STWX: + if (!isIndexed) return 0; + case PC_STW: + if (isFloat) return 0; + if (loadSize != 4) return 0; + break; + case PC_STFSX: + if (!isIndexed) return 0; + case PC_STFS: + if (!isFloat) return 0; + if (loadSize != 4) return 0; + break; + case PC_STFDX: + if (!isIndexed) return 0; + case PC_STFD: + if (!isFloat) return 0; + if (loadSize != 8) return 0; + break; + case PC_STVX: + case PC_STVXL: + if (!isIndexed) return 0; + if (!isVector) return 0; + if (loadSize != 16) return 0; + break; + default: + return 0; + } + + for (scan = instr->prevPCode; scan && scan != defInstr; scan = scan->prevPCode) { + if (scan->flags & fPCodeFlag4) { + if (scan->args[1].data.reg.reg != instr->args[1].data.reg.reg) + return 0; + if (scan->args[2].kind != defInstr->args[2].kind) + return 0; + + if (scan->args[2].kind == PCOp_MEMORY) { + if (instr->args[2].data.mem.obj == scan->args[2].data.mem.obj) { + if (instr->args[2].data.mem.offset == defInstr->args[2].data.mem.offset) + return 0; + defInstrOffset = defInstr->args[2].data.mem.offset; + scanOffset = scan->args[2].data.mem.offset; + } + } else if (scan->args[2].kind == PCOp_IMMEDIATE) { + if (instr->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + if (instr->args[2].data.imm.value == scan->args[2].data.imm.value) + return 0; + defInstrOffset = defInstr->args[2].data.imm.value; + scanOffset = scan->args[2].data.imm.value; + } else { + return 0; + } + + switch (scan->op) { + case PC_STB: + case PC_STBX: + storeSize = 1; + break; + case PC_STH: + case PC_STHX: + storeSize = 2; + break; + case PC_STW: + case PC_STWX: + case PC_STFS: + case PC_STFSX: + storeSize = 4; + break; + case PC_STFD: + case PC_STFDX: + storeSize = 8; + break; + case PC_STVX: + case PC_STVXL: + storeSize = 16; + break; + default: + return 0; + } + + if (defInstrOffset > scanOffset) { + if ((scanOffset + storeSize) > defInstrOffset) + return 0; + } else { + if ((defInstrOffset + loadSize) > scanOffset) + return 0; + } + } + } + + deletepcode(instr); + return 1; + } + + return 0; +} + +static int RLWINM_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + short start; + short end; + + if ( + defInstr->op == PC_RLWINM && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !( + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + ( + (defInstr->args[0].data.reg.reg != instr->args[0].data.reg.reg && (masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) || + usedbetween(instr, defInstr, &defInstr->args[0]) + ) + ) && + canmergemasks( + defInstr->args[3].data.imm.value, + defInstr->args[4].data.imm.value, + instr->args[2].data.imm.value, + instr->args[3].data.imm.value, + instr->args[4].data.imm.value, + &start, &end) + ) + { + if (instr->op == PC_RLWIMI) { + if (instr->args[0].data.reg.reg == defInstr->args[0].data.reg.reg) + return 0; + if (start != instr->args[3].data.imm.value || end != instr->args[4].data.imm.value) + return 0; + } + + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value = (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) & 31; + instr->args[3].data.imm.value = start; + instr->args[4].data.imm.value = end; + + if ( + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + deletepcode(defInstr); + + return 1; + } + + if ( + defInstr->op == PC_MR && + instr->op == PC_RLWINM && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if ( + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + deletepcode(defInstr); + + return 1; + } + + return 0; +} + +static int MULLI_MULLI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_MULLI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + FITS_IN_SHORT(instr->args[2].data.imm.value * defInstr->args[2].data.imm.value) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value *= defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int ADDI_ADDI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_ADDI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int SRAWI_SRAWI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_SRAWI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fPCodeFlag20000000) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) < 32 && + (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) > 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int MR_ADDI(PCode *instr, UInt32 *masks) { + PCode *prev = instr->prevPCode; + PCode *next = instr->nextPCode; + int prevFlag = 0; + int nextFlag = 0; + + if (copts.cpu == CPU_PPC603e) { + if (prev) + prevFlag = (prev->flags & fPCodeFlagC0000000) == fPCodeFlag80000000; + if (next) + nextFlag = (next->flags & fPCodeFlagC0000000) == fPCodeFlag80000000; + + if ( + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + instr->argCount >= 2 && + instr->args[1].data.reg.reg != 0 && + (prevFlag || nextFlag) + ) + { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = 0; + instr->args[2].data.imm.obj = NULL; + change_num_operands(instr, 3); + } + } + + return 0; +} + +static int rotatedefinedusedtest(UInt32 *masks, PCode *instr, PCode *a, PCode *b, PCode *subfic) { + PCode *scan; + PCodeArg *op; + int i; + int reg1; + int reg2; + + if ( + (masks[RegClass_GPR] & (1 << subfic->args[0].data.reg.reg)) && + subfic->args[0].data.reg.reg != instr->args[0].data.reg.reg && + subfic->args[0].data.reg.reg != a->args[2].data.reg.reg + ) + return 1; + + for (scan = instr->block->firstPCode; scan != instr->block->lastPCode; scan = scan->nextPCode) { + if (scan == a) break; + if (scan == b) break; + if (scan == subfic) break; + } + + reg1 = a->args[1].data.reg.reg; + reg2 = subfic->args[1].data.reg.reg; + while (scan != instr) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + ( + ( + (op->data.reg.reg == reg1 || op->data.reg.reg == reg2) && + (op->data.reg.effect & EffectWrite) + ) + || + ( + op->data.reg.reg == subfic->args[0].data.reg.reg && (op->data.reg.effect & EffectRead) + ) + ) && + scan != a && + scan != b && + scan != subfic + ) + return 1; + } + + scan = scan->nextPCode; + } + + return 0; +} + +static int SRW_SUBFIC_RLW_OR(PCode *instr, UInt32 *masks) { + PCode *subfic; + PCode *defInstr1 = defininginstruction[instr->defID + 1]; + PCode *defInstr2 = defininginstruction[instr->defID + 2]; + + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + return 0; + + if ( + (masks[RegClass_GPR] & (1 << instr->args[1].data.reg.reg)) && + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) + return 0; + + if ( + (masks[RegClass_GPR] & (1 << instr->args[2].data.reg.reg)) && + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) + return 0; + + if (defInstr1->op != PC_SRW && defInstr1->op != PC_SLW) + return 0; + if (defInstr2->op != PC_SRW && defInstr2->op != PC_SLW) + return 0; + + if (usedbetween(instr, defInstr1, &defInstr1->args[0])) + return 0; + if (usedbetween(instr, defInstr2, &defInstr2->args[0])) + return 0; + + if ( + defInstr1->op == PC_SRW && defInstr2->op == PC_SLW && + defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg + ) + { + subfic = defininginstruction[defInstr1->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr2->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + deletepcode(subfic); + return 1; + } + + subfic = defininginstruction[defInstr2->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr2->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + return 1; + } + } else if ( + defInstr1->op == PC_SLW && defInstr2->op == PC_SRW && + defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg + ) + { + subfic = defininginstruction[defInstr1->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr1->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + return 1; + } + + subfic = defininginstruction[defInstr2->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr1->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + deletepcode(subfic); + return 1; + } + } + + return 0; +} + +static int RLWINM_RLWIMI_STW(PCode *instr, UInt32 *masks) { + PCode *newInstr; + Boolean isZeroOffset; + int flags; + PCode *scan; + int i; + PCode *array[4]; + + flags = 0; + isZeroOffset = 0; + if (instr->op == PC_STW && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) + isZeroOffset = 1; + + scan = instr; + for (i = 0; i < 4; i++) { + if (scan->op == PC_RLWINM) + array[i] = defininginstruction[scan->defID + 1]; + else + array[i] = defininginstruction[scan->defID]; + + scan = array[i]; + if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + + if (i < 3) { + if (scan->op != PC_RLWIMI) + return 0; + } else { + if (scan->op != PC_RLWINM) + return 0; + } + + if (scan->args[2].data.imm.value == 8) { + if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { + if (flags & 1) + return 0; + flags |= 1; + } else if (scan->args[3].data.imm.value == 8 && scan->args[4].data.imm.value == 15) { + if (flags & 4) + return 0; + flags |= 4; + } else { + return 0; + } + } else if (scan->args[2].data.imm.value == 24) { + if (scan->args[3].data.imm.value == 0 && scan->args[4].data.imm.value == 7) { + if (flags & 8) + return 0; + flags |= 8; + } else if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { + if (flags & 2) + return 0; + flags |= 2; + } else { + return 0; + } + } else { + return 0; + } + } + + if (definedbetween(instr, array[3], &array[0]->args[1])) + return 0; + + if (instr->op == PC_STWX) { + change_opcode(instr, PC_STWBRX); + instr->args[0] = array[0]->args[1]; + defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; + return 1; + } + + if (instr->op == PC_STW) { + if (!isZeroOffset) { + if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) + return 0; + + if (usedbetween(array[2], array[3], &array[0]->args[0])) + return 0; + if (usedbetween(array[1], array[2], &array[0]->args[0])) + return 0; + if (usedbetween(array[0], array[1], &array[0]->args[0])) + return 0; + if (usedbetween(instr, array[0], &array[0]->args[0])) + return 0; + } + + defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; + + if (!isZeroOffset) { + newInstr = makepcode(PC_STWBRX, array[3]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); + newInstr->alias = instr->alias; + change_opcode(instr, PC_ADDI); + insertpcodeafter(instr, newInstr); + + masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; + masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; + instr->args[0].data.reg.effect &= ~EffectRead; + instr->args[0].data.reg.effect |= EffectWrite; + defininginstruction[instr->defID] = instr; + + deletepcode(array[0]); + deletepcode(array[1]); + deletepcode(array[2]); + deletepcode(array[3]); + } else { + change_opcode(instr, PC_STWBRX); + instr->args[0] = array[0]->args[1]; + instr->args[2] = instr->args[1]; + defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; + + instr->args[1].kind = PCOp_REGISTER; + instr->args[1].arg = RegClass_GPR; + instr->args[1].data.reg.reg = 0; + instr->args[1].data.reg.effect = 0; + } + + return 1; + } + + return 0; +} + +static int RLWINM_RLWIMI_STH(PCode *instr, UInt32 *masks) { + PCode *newInstr; + Boolean isZeroOffset; + int flags; + PCode *scan; + int i; + PCode *array[2]; + + flags = 0; + isZeroOffset = 0; + if (instr->op == PC_STH && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) + isZeroOffset = 1; + + scan = instr; + for (i = 0; i < 2; i++) { + if (scan->op == PC_RLWINM) + array[i] = defininginstruction[scan->defID + 1]; + else + array[i] = defininginstruction[scan->defID]; + + scan = array[i]; + if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + + if (i < 1) { + if (scan->op != PC_RLWIMI) + return 0; + } else { + if (scan->op != PC_RLWINM) + return 0; + } + + if (scan->args[2].data.imm.value == 8) { + if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { + if (flags & 2) + return 0; + flags |= 2; + } else { + return 0; + } + } else if (scan->args[2].data.imm.value == 24) { + if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { + if (flags & 1) + return 0; + flags |= 1; + } else { + return 0; + } + } else { + return 0; + } + } + + if (definedbetween(instr, array[1], &array[0]->args[1])) + return 0; + + if (instr->op == PC_STHX) { + change_opcode(instr, PC_STHBRX); + instr->args[0] = array[0]->args[1]; + defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; + return 1; + } + + if (instr->op == PC_STH) { + if (!isZeroOffset) { + if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) + return 0; + + if (usedbetween(array[0], array[1], &array[0]->args[0])) + return 0; + if (usedbetween(instr, array[0], &array[0]->args[0])) + return 0; + } + + defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; + + if (!isZeroOffset) { + newInstr = makepcode(PC_STHBRX, array[1]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); + newInstr->alias = instr->alias; + change_opcode(instr, PC_ADDI); + + instr->args[0].data.reg.effect &= ~EffectRead; + instr->args[0].data.reg.effect |= EffectWrite; + defininginstruction[instr->defID] = instr; + + insertpcodeafter(instr, newInstr); + + masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; + masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; + + deletepcode(array[0]); + deletepcode(array[1]); + } else { + change_opcode(instr, PC_STHBRX); + instr->args[0] = array[0]->args[1]; + instr->args[2] = instr->args[1]; + defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; + + instr->args[1].kind = PCOp_REGISTER; + instr->args[1].arg = RegClass_GPR; + instr->args[1].data.reg.reg = 0; + instr->args[1].data.reg.effect = 0; + } + + return 1; + } + + return 0; +} + +static void peepholeoptimizeblock(PCodeBlock *block) { + RegClass rclass; + PCode *instr; + PCodeArg *op; + int i; + Pattern *pattern; + UInt32 masks[RegClassMax]; + + for (rclass = 0; rclass < RegClassMax; rclass++) + masks[rclass] = liveregs[rclass][block->blockIndex].xC; + + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (dead(instr, masks)) { + deletepcode(instr); + } else { + pattern = peepholepatterns[instr->op]; + + while (pattern) { + if (pattern->func(instr, masks)) { + if (!instr->block) + break; + pattern = peepholepatterns[instr->op]; + } else { + pattern = pattern->next; + } + } + + if (instr->block) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + masks[op->arg] &= ~(1 << op->data.reg.reg); + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) + masks[op->arg] |= 1 << op->data.reg.reg; + } + } + } + } +} + +static SInt32 computepossiblemask(PCode *instr, short reg) { + SInt32 mask; + SInt32 val; + PCodeArg *op; + int i; + + mask = 0xFFFFFFFF; + while (instr) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { + switch (instr->op) { + case PC_LBZ: + case PC_LBZU: + case PC_LBZX: + case PC_LBZUX: + mask = 0xFF; + break; + + case PC_LHZ: + case PC_LHZU: + case PC_LHZX: + case PC_LHZUX: + mask = 0xFFFF; + break; + + case PC_LI: + mask = instr->args[1].data.imm.value; + break; + + case PC_SRAWI: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) >> instr->args[2].data.imm.value; + break; + + case PC_RLWINM: + val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); + + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + mask &= val; + break; + + case PC_RLWIMI: + val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); + + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + mask &= val; + mask |= computepossiblemask(instr->prevPCode, instr->args[0].data.reg.reg); + break; + + case PC_OR: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) | + computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); + break; + + case PC_ORI: + mask = instr->args[2].data.imm.value | + computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + + case PC_AND: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) & + computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); + break; + + case PC_ANDI: + mask = instr->args[2].data.imm.value & + computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + + case PC_MR: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + } + + return mask; + } + } + instr = instr->prevPCode; + } + + return mask; +} + +static UInt32 fillmaskholes(UInt32 mask) { + UInt32 oneBit; + UInt32 allBits; + UInt32 result; + + oneBit = 1; + allBits = 0xFFFFFFFF; + result = 0; + + if ((mask & 1) && (mask & 0x80000000)) { + result = 0xFFFFFFFF; + while ((mask & oneBit) == 1) { + oneBit <<= 1; + } + + while ((mask & oneBit) == 0) { + result &= ~oneBit; + oneBit <<= 1; + } + + return result; + } else { + while ((mask & oneBit) == 0 && (mask & allBits) != 0) { + oneBit <<= 1; + allBits <<= 1; + } + while ((mask & allBits) != 0) { + result |= oneBit; + oneBit <<= 1; + allBits <<= 1; + } + return result; + } +} + +static int canuseinsert(PCode *instr1, PCode *instr2, short reg) { + if (computepossiblemask(instr2, reg) & fillmaskholes(computepossiblemask(instr1, instr1->args[0].data.reg.reg))) + return 0; + return 1; +} + +static PCode *find_def_backwords(PCode *instr, short reg) { + int i; + + while (instr) { + for (i = 0; i < instr->argCount; i++) { + if (PC_OP_IS_WRITE_REGISTER(&instr->args[i], RegClass_GPR, reg)) + return instr; + } + instr = instr->prevPCode; + } + + return NULL; +} + +static void adjustforward(PCodeBlock *block) { + PCode *instr; + PCode *scan; + PCode *tmp; + PCodeArg *op; + int i; + short opcode; + short reg0; + short reg1; + SInt32 valA; + SInt32 valB; + + instr = block->firstPCode; + while (instr) { + if (instr->op == PC_RLWINM) { + SInt32 val2; + SInt32 val3; + SInt32 val4; + short start; + short end; + + short flag1 = 0; + short flag2 = 0; + reg0 = instr->args[0].data.reg.reg; + reg1 = instr->args[1].data.reg.reg; + val2 = instr->args[2].data.imm.value; + val3 = instr->args[3].data.imm.value; + val4 = instr->args[4].data.imm.value; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + opcode = scan->op; + if (opcode == PC_RLWINM && scan->args[1].data.reg.reg == reg0) { + if ( + scan->args[3].data.imm.value == val3 && + scan->args[4].data.imm.value == val4 && + scan->args[2].data.imm.value == 0 + ) + { + if (PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) { + if (!flag1) { + pcsetrecordbit(instr); + change_opcode(scan, PC_MR); + scan->flags &= ~fPCodeFlag20000000; + scan->flags |= fPCodeFlag10; + change_num_operands(scan, 2); + } else { + change_opcode(scan, PC_MR); + scan->args[2] = scan->args[5]; + change_num_operands(scan, 3); + } + } else { + change_opcode(scan, PC_MR); + change_num_operands(scan, 2); + } + } + else if ( + reg0 != reg1 && + !flag2 && + canmergemasks( + val3, + val4, + scan->args[2].data.imm.value, + scan->args[3].data.imm.value, + scan->args[4].data.imm.value, + &start, &end) + ) + { + scan->args[1].data.reg.reg = reg1; + scan->args[2].data.imm.value = (scan->args[2].data.imm.value + instr->args[2].data.imm.value) & 31; + scan->args[3].data.imm.value = start; + scan->args[4].data.imm.value = end; + } + } + else if ( + opcode == PC_SRAWI && + scan->args[1].data.reg.reg == reg0 && + reg0 != reg1 && + instr->args[2].data.imm.value == 0 && + !(computepossiblemask(instr, reg0) & 0x80000000) && + !flag2 && + canmergemasks(val3, val4, 32 - scan->args[2].data.imm.value, scan->args[2].data.imm.value, 31, &start, &end) && + !isSPRlive(scan, 0) + ) + { + insertpcodeafter(scan, makepcode( + PC_RLWINM, scan->args[0].data.reg.reg, reg1, + 32 - scan->args[2].data.imm.value, start, end + )); + if (PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) + pcsetrecordbit(scan->nextPCode); + deletepcode(scan); + } + else if ( + opcode == PC_OR && + !flag2 && + reg0 != reg1 && + !(PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) && + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + scan->args[0].data.reg.reg != instr->args[1].data.reg.reg + ) + { + if (scan->args[1].data.reg.reg == reg0 && canuseinsert(instr, scan, scan->args[2].data.reg.reg)) { + op = &scan->args[2]; + tmp = find_def_backwords(scan->prevPCode, scan->args[2].data.reg.reg); + if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + else + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + + if (valA == ~valB) + op = &tmp->args[1]; + } + + change_opcode(scan, PC_MR); + scan->args[1] = *op; + change_num_operands(scan, 2); + + tmp = copypcode(instr); + change_opcode(tmp, PC_RLWIMI); + tmp->args[0] = scan->args[0]; + tmp->args[0].data.reg.effect |= EffectRead; + + if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { + tmp->args[3].data.imm.value = start; + tmp->args[4].data.imm.value = end; + } + + insertpcodeafter(scan, tmp); + break; + } + + if ( + scan->args[2].data.reg.reg == reg0 && + canuseinsert(instr, scan, scan->args[1].data.reg.reg) + ) + { + op = &scan->args[1]; + tmp = find_def_backwords(scan->prevPCode, scan->args[1].data.reg.reg); + if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + else + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + + if (valA == ~valB) + op = &tmp->args[1]; + } + + change_opcode(scan, PC_MR); + scan->args[1] = *op; + change_num_operands(scan, 2); + + tmp = copypcode(instr); + change_opcode(tmp, PC_RLWIMI); + tmp->args[0] = scan->args[0]; + tmp->args[0].data.reg.effect |= EffectRead; + + if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { + tmp->args[3].data.imm.value = start; + tmp->args[4].data.imm.value = end; + } + + insertpcodeafter(scan, tmp); + break; + } + } + else if ( + !flag2 && + reg0 != reg1 && + val4 == 31 && + instr->args[2].data.imm.value == 0 && + ( + ((opcode == PC_STB || opcode == PC_STBX) && val3 <= 24) || + ((opcode == PC_STH || opcode == PC_STHX) && val3 <= 16) + ) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if ( + opcode == PC_EXTSH && + scan->args[1].data.reg.reg == reg0 && + val2 == 0 && + val3 > 16 && + val3 < val4 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) && !flag1) { + pcsetrecordbit(instr); + scan->flags &= ~fPCodeFlag20000000; + scan->flags |= fPCodeFlag10; + change_num_operands(scan, 2); + } + } + else if ( + opcode == PC_EXTSB && + scan->args[1].data.reg.reg == reg0 && + val2 == 0 && + val3 > 24 && + val3 < val4 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) && !flag1) { + pcsetrecordbit(instr); + scan->flags &= ~fPCodeFlag20000000; + scan->flags |= fPCodeFlag10; + change_num_operands(scan, 2); + } + } + + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg0)) { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg1)) + flag2 = 1; + + if (PC_OP_IS_REGISTER(op, RegClass_GPR, 0)) + flag1 = 1; + } + } + + } else if ( + instr->op == PC_EXTSB && + (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) + ) + { + short flag = 0; + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ( + (scan->op >= PC_STB && scan->op <= PC_STBUX) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if ( + (scan->op == PC_EXTSH || scan->op == PC_EXTSB) && + scan->args[1].data.reg.reg == reg0 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) && !flag) { + pcsetrecordbit(instr); + scan->flags &= ~fPCodeFlag20000000; + scan->flags |= fPCodeFlag10; + change_num_operands(scan, 2); + } + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && + (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) + ) + { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_REGISTER(op, RegClass_GPR, 0)) + flag = 1; + } + } + } else if ( + instr->op == PC_EXTSH && + (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) + ) + { + short flag = 0; + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ( + ((scan->op >= PC_STB && scan->op <= PC_STBUX) || (scan->op >= PC_STH && scan->op <= PC_STHUX)) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if (scan->op == PC_EXTSH && scan->args[1].data.reg.reg == reg0) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fPCodeFlag20000000) && !flag) { + pcsetrecordbit(instr); + scan->flags &= ~fPCodeFlag20000000; + scan->flags |= fPCodeFlag10; + change_num_operands(scan, 2); + } + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && + (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) + ) + { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_REGISTER(op, RegClass_GPR, 0)) + flag = 1; + } + } + } else if ( + instr->op == PC_ADDI && + (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) && + instr->args[2].kind == PCOp_IMMEDIATE + ) + { + Boolean flag1 = 0; + Boolean flag2 = 0; + SInt32 val2 = instr->args[2].data.imm.value; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ((scan->flags & fPCodeFlag4) && scan->args[0].data.reg.reg == reg0) + break; + + if ( + (scan->flags & (fPCodeFlag2 | fPCodeFlag4)) && + scan->args[1].data.reg.reg == reg0 && + scan->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) + ) + { + scan->args[2].data.imm.value += val2; + tmp = instr->prevPCode; + if ( + (scan->flags & fPCodeFlag2) && + scan->args[0].data.reg.reg == reg0 && + scan->args[0].kind == PCOp_REGISTER && + scan->args[0].arg == RegClass_GPR + ) + { + deletepcode(instr); + } else { + deletepcode(instr); + insertpcodeafter(scan, instr); + } + instr = tmp; + break; + } + + if ( + scan->op == PC_ADDI && + scan->args[1].data.reg.reg == reg0 && + scan->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) + ) + { + scan->args[2].data.imm.value += val2; + tmp = instr->prevPCode; + if (scan->args[0].data.reg.reg == reg0) { + deletepcode(instr); + } else { + deletepcode(instr); + insertpcodeafter(scan, instr); + } + instr = tmp; + break; + } + + if (scan->flags & (fPCodeFlag1 | fPCodeFlag8)) { + if (flag1 && scan->prevPCode != instr) { + tmp = instr->prevPCode; + deletepcode(instr); + insertpcodebefore(scan, instr); + instr = tmp; + } + break; + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_R_OR_W_REGISTER(op, RegClass_GPR, reg0)) { + if (flag1 && scan->prevPCode != instr) { + tmp = instr->prevPCode; + deletepcode(instr); + insertpcodebefore(scan, instr); + instr = tmp; + } + flag2 = 1; + break; + } + } + + if (flag2) + break; + + if (scan->op != PC_ADDI) + flag1 = 1; + + if (flag1 && !scan->nextPCode) { + tmp = instr->prevPCode; + deletepcode(instr); + appendpcode(block, instr); + instr = tmp; + break; + } + } + } + + if (instr) + instr = instr->nextPCode; + else + instr = block->firstPCode; + } +} + +static void installpattern(Opcode opcode, PeepholeFunc func) { + Pattern *pattern = lalloc(sizeof(Pattern)); + pattern->func = func; + pattern->next = peepholepatterns[opcode]; + peepholepatterns[opcode] = pattern; +} + +static void installpeepholepatterns(void) { + int i; + + for (i = 0; i < OPCODE_MAX; i++) + peepholepatterns[i] = NULL; + + installpattern(PC_AND, NOT_AND); + installpattern(PC_MR, LI_MR); + installpattern(PC_MR, L_MR); + installpattern(PC_FMR, L_FMR); + installpattern(PC_MR, MR_MR); + installpattern(PC_MR, MR_Rx_Rx); + installpattern(PC_FMR, FMR_FMR); + installpattern(PC_FMR, FMR_Fx_Fx); + installpattern(PC_VMR, VMR_VMRP); + installpattern(PC_VMR, VMR_VMR); + installpattern(PC_VMR, VMR_Vx_Vx); + installpattern(PC_VMR, VSPLTIS_VMR); + installpattern(PC_CMPI, MR_CMPI); + installpattern(PC_RLWIMI, RLWINM_RLWINM); + installpattern(PC_RLWINM, RLWINM_RLWINM); + installpattern(PC_RLWINM, EXTSB_RLWINM); + installpattern(PC_RLWINM, EXTSH_RLWINM); + installpattern(PC_RLWINM, LBZ_RLWINM); + installpattern(PC_RLWINM, LHZ_RLWINM); + installpattern(PC_EXTSH, LHA_EXTSH); + installpattern(PC_STW, RLWINM_RLWIMI_STW); + installpattern(PC_STWX, RLWINM_RLWIMI_STW); + installpattern(PC_STH, RLWINM_RLWIMI_STH); + installpattern(PC_STHX, RLWINM_RLWIMI_STH); + installpattern(PC_LBZ, ADDI_L_S); + installpattern(PC_LHZ, ADDI_L_S); + installpattern(PC_LHA, ADDI_L_S); + installpattern(PC_LWZ, ADDI_L_S); + installpattern(PC_STB, ADDI_L_S); + installpattern(PC_STH, ADDI_L_S); + installpattern(PC_STW, ADDI_L_S); + installpattern(PC_LFS, ADDI_L_S); + installpattern(PC_LFD, ADDI_L_S); + installpattern(PC_STFS, ADDI_L_S); + installpattern(PC_STFD, ADDI_L_S); + installpattern(PC_LBZU, ADDI_LU_SU); + installpattern(PC_LHZU, ADDI_LU_SU); + installpattern(PC_LHAU, ADDI_LU_SU); + installpattern(PC_LWZU, ADDI_LU_SU); + installpattern(PC_STBU, ADDI_LU_SU); + installpattern(PC_STHU, ADDI_LU_SU); + installpattern(PC_STWU, ADDI_LU_SU); + installpattern(PC_LFSU, ADDI_LU_SU); + installpattern(PC_LFDU, ADDI_LU_SU); + installpattern(PC_STFSU, ADDI_LU_SU); + installpattern(PC_STFDU, ADDI_LU_SU); + installpattern(PC_LBZ, L_S_ADDI); + installpattern(PC_LHZ, L_S_ADDI); + installpattern(PC_LHA, L_S_ADDI); + installpattern(PC_LWZ, L_S_ADDI); + installpattern(PC_STB, L_S_ADDI); + installpattern(PC_STH, L_S_ADDI); + installpattern(PC_STW, L_S_ADDI); + installpattern(PC_LFS, L_S_ADDI); + installpattern(PC_LFD, L_S_ADDI); + installpattern(PC_STFS, L_S_ADDI); + installpattern(PC_STFD, L_S_ADDI); + installpattern(PC_STB, L_S); + installpattern(PC_STH, L_S); + installpattern(PC_STW, L_S); + installpattern(PC_STFS, L_S); + installpattern(PC_STFD, L_S); + installpattern(PC_STBX, L_S); + installpattern(PC_STHX, L_S); + installpattern(PC_STWX, L_S); + installpattern(PC_STFSX, L_S); + installpattern(PC_STFDX, L_S); + installpattern(PC_BT, LBZ_EXTSB_CMPI_BC); + installpattern(PC_BF, LBZ_EXTSB_CMPI_BC); + installpattern(PC_BT, RLWINM_CMPLI_BC); + installpattern(PC_BF, RLWINM_CMPLI_BC); + installpattern(PC_BT, LI_CMP_BC); + installpattern(PC_BF, LI_CMP_BC); + installpattern(PC_RLWINM, RLWINM_RLWINM); + installpattern(PC_MULLI, MULLI_MULLI); + installpattern(PC_ADDI, ADDI_ADDI); + installpattern(PC_SRAWI, SRAWI_SRAWI); + installpattern(PC_MR, MR_ADDI); + installpattern(PC_OR, SRW_SUBFIC_RLW_OR); +} + +void peepholeoptimizeforward(Object *func) { + PCodeBlock *block; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount >= 2) + adjustforward(block); + } +} + +void peepholemergeblocks(Object *func, Boolean flag) { + PCodeBlock *block; + PCodeBlock *next; + Boolean flag2; + PCode *instr; + PCode *nextinstr; + PCLink *link; + PCLink *link2; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + flag2 = 0; + next = block->nextBlock; + + if (!flag) { + flag2 = next && (next->flags & fPCBlockFlag2); + if (block->flags & fPCBlockFlag1) + continue; + } + + if (block->pcodeCount > 0) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & (fPCodeFlag8 | fSideEffects)) + break; + } + + if (instr) + continue; + + instr = block->lastPCode; + if (instr && instr->op == PC_B) { + if (instr->args[0].kind == PCOp_LABEL && instr->args[0].data.label.label->block == next) + deletepcode(instr); + else + continue; + } + + instr = block->lastPCode; + if (instr && (instr->flags & fPCodeFlag1) && instr->op != PC_B) + continue; + + while ( + block->successors->block == next && + block->successors->nextLink == NULL && + next->predecessors->block == block && + next->predecessors->nextLink == NULL && + !flag2 && + !(next->flags & fPCBlockFlag8000) && + (block->pcodeCount + next->pcodeCount) <= 100 + ) + { + if (next->pcodeCount > 0) { + for (instr = next->firstPCode; instr; instr = nextinstr) { + nextinstr = instr->nextPCode; + if (instr->flags & (fPCodeFlag8 | fSideEffects)) + break; + + deletepcode(instr); + if (instr->op != PC_B) { + appendpcode(block, instr); + } else if (instr->args[0].kind == PCOp_LABEL) { + if (instr->args[0].data.label.label->block != next->nextBlock) + appendpcode(block, instr); + } else { + appendpcode(block, instr); + } + } + } + + if (next->pcodeCount != 0) + break; + if (next == epilogue) + break; + + block->successors = next->successors; + + for (link = block->successors; link; link = link->nextLink) { + for (link2 = link->block->predecessors; link2; link2 = link2->nextLink) { + if (link2->block == next) { + link2->block = block; + break; + } + } + } + + block->nextBlock = next->nextBlock; + if (block->nextBlock) + block->nextBlock->prevBlock = block; + + next->flags |= fPCBlockFlag20; + next = block->nextBlock; + + if (!flag) + flag2 = next && (next->flags & fPCBlockFlag2); + } + } + } +} + +void peepholeoptimizepcode(Object *func) { + PCodeBlock *block; + + installpeepholepatterns(); + computeliveregisters(func); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount >= 1) { + computeinstructionpredecessors(block); + peepholeoptimizeblock(block); + freeoheap(); + } + } +} diff --git a/compiler_and_linker/unsorted/RegisterInfo.c b/compiler_and_linker/unsorted/RegisterInfo.c index 3ee9373..a5e9966 100644 --- a/compiler_and_linker/unsorted/RegisterInfo.c +++ b/compiler_and_linker/unsorted/RegisterInfo.c @@ -42,8 +42,7 @@ void asm_used_register(RegClass rclass, short reg) { void retain_register(Object *obj, RegClass rclass, short reg) { VarInfo *vi; -#line 95 - CError_ASSERT((short) reg < RegisterMax); + CError_ASSERT(95, (short) reg < RegisterMax); if (reg_state[rclass][reg] == RegState0) { assignable_registers[rclass]--; @@ -96,8 +95,7 @@ char GetRegisterClassName(RegClass rclass) { case RegClass_GPR: return 'r'; case RegClass_FPR: return 'f'; default: -#line 242 - CError_FATAL(); + CError_FATAL(242); return '?'; } } @@ -207,8 +205,7 @@ void assign_register_by_type(Object *obj) { if (vi->rclass < RegClassMax) { if (flag) { -#line 520 - CError_ASSERT(vi->rclass == RegClass_GPR); + CError_ASSERT(520, vi->rclass == RegClass_GPR); if (assignable_registers[vi->rclass] > 1) assign_GPR_pair(obj); } else { @@ -228,8 +225,7 @@ void assign_GPR_pair(Object *obj) { reg = used_virtual_registers[RegClass_GPR]++; regHi = used_virtual_registers[RegClass_GPR]++; } else { -#line 554 - CError_ASSERT(assignable_registers[RegClass_GPR] >= 2); + CError_ASSERT(554, assignable_registers[RegClass_GPR] >= 2); reg = obtain_nonvolatile_register(RegClass_GPR); regHi = obtain_nonvolatile_register(RegClass_GPR); retain_GPR_pair(obj, reg, regHi); @@ -241,8 +237,7 @@ void assign_GPR_pair(Object *obj) { vi->reg = reg; vi->regHi = regHi; } else { -#line 567 - CError_FATAL(); + CError_FATAL(567); } } @@ -279,18 +274,14 @@ VarInfo *Registers_GetVarInfo(Object *obj) { 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(); + CError_FATAL(639); obj->u.toc.info = CodeGen_GetNewVarInfo(); } return obj->u.toc.info; case DLOCAL: - if (!obj->u.var.info) { -#line 647 - CError_FATAL(); - } + if (!obj->u.var.info) + CError_FATAL(647); return obj->u.var.info; case DABSOLUTE: // not sure if this is the right union @@ -298,8 +289,7 @@ VarInfo *Registers_GetVarInfo(Object *obj) { obj->u.data.info = Registers_GetNewVarInfo(); return obj->u.data.info; default: -#line 660 - CError_FATAL(); + CError_FATAL(660); return NULL; } } diff --git a/compiler_and_linker/unsorted/ScanFloat.c b/compiler_and_linker/unsorted/ScanFloat.c new file mode 100644 index 0000000..8883b64 --- /dev/null +++ b/compiler_and_linker/unsorted/ScanFloat.c @@ -0,0 +1,9 @@ +#include "compiler/ScanFloat.h" + +char *ScanFloat(const char *str, double *result, Boolean *failed) { + char *end; + + *result = strtod(str, &end); + *failed = 0; + return end; +} diff --git a/compiler_and_linker/unsorted/Scheduler.c b/compiler_and_linker/unsorted/Scheduler.c index 5a26a20..e3c8ac7 100644 --- a/compiler_and_linker/unsorted/Scheduler.c +++ b/compiler_and_linker/unsorted/Scheduler.c @@ -268,8 +268,7 @@ static void findsuccessors(DGNode *nodes, DGNode *node) { op->data.reg.reg > used_virtual_registers[(char) op->arg] ) { -#line 491 - CError_FATAL(); + CError_FATAL(491); } if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { diff --git a/compiler_and_linker/unsorted/SpillCode.c b/compiler_and_linker/unsorted/SpillCode.c index e583613..bfafbac 100644 --- a/compiler_and_linker/unsorted/SpillCode.c +++ b/compiler_and_linker/unsorted/SpillCode.c @@ -79,8 +79,7 @@ static Object *makespilltemporary(Type *type) { static PCode *rematerialize_spilled_register(short reg, IGNode *node) { PCode *instr = copypcode(node->instr8); -#line 128 - CError_ASSERT(instr->args[0].kind == PCOp_REGISTER); + CError_ASSERT(128, instr->args[0].kind == PCOp_REGISTER); instr->args[0].data.reg.reg = reg; return instr; @@ -113,23 +112,19 @@ static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) opcode = PC_LWZ; break; default: -#line 187 - CError_FATAL(); + CError_FATAL(187); } memclrw(&operand, sizeof(Operand)); operand.optype = OpndType_Symbol; operand.object = node->spillTemporary; -#line 222 - CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + CError_ASSERT(222, node->spillTemporary->datatype == DLOCAL); coerce_to_addressable(&operand); -#line 233 - CError_ASSERT(operand.optype == OpndType_GPR_ImmOffset); + CError_ASSERT(233, operand.optype == OpndType_GPR_ImmOffset); -#line 237 - CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + CError_ASSERT(237, node->spillTemporary->datatype == DLOCAL); if (node->flags & fPairLow) offset = low_offset; @@ -141,8 +136,7 @@ static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) break; case RegClass_FPR: -#line 253 - CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + CError_ASSERT(253, node->spillTemporary->datatype == DLOCAL); if (node->flags & fPairLow) offset = low_offset; @@ -165,8 +159,7 @@ static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) break; case RegClass_VR: -#line 320 - CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + CError_ASSERT(320, node->spillTemporary->datatype == DLOCAL); object = node->spillTemporary; newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); @@ -176,8 +169,7 @@ static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) break; default: -#line 333 - CError_FATAL(); + CError_FATAL(333); } } @@ -209,8 +201,7 @@ static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, opcode = PC_STW; break; default: -#line 391 - CError_FATAL(); + CError_FATAL(391); } if (node->flags & fPairLow) @@ -249,8 +240,7 @@ static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, break; default: -#line 527 - CError_FATAL(); + CError_FATAL(527); } } @@ -270,8 +260,7 @@ static void spillinstruction(PCodeBlock *block, PCode *instr) { regs = used_virtual_registers[coloring_class]; flag = 0; for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { -#line 563 - CError_ASSERT(instr->block != NULL); + CError_ASSERT(563, instr->block != NULL); if ( PC_OP_IS_ANY_REGISTER(op, coloring_class) && @@ -401,8 +390,7 @@ static void assign_spill_locations(void) { type = TYPE(&stvectorunsignedchar); break; default: -#line 771 - CError_FATAL(); + CError_FATAL(771); } node->spillTemporary = makespilltemporary(type); diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c index 18cb6fd..a78552d 100644 --- a/compiler_and_linker/unsorted/StackFrame.c +++ b/compiler_and_linker/unsorted/StackFrame.c @@ -1,10 +1,16 @@ #include "compiler/StackFrame.h" #include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" #include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" #include "compiler/objects.h" -#include "compiler.h" +#include "compiler/types.h" #define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) ) #define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) ) @@ -62,7 +68,7 @@ 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); +static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size); void init_stack_globals(Object *funcobj) { char rclass; @@ -236,8 +242,7 @@ void compute_frame_sizes(void) { SInt32 altivec_size; SInt32 altivec_offset; -#line 897 - CError_ASSERT(alloca_alignment == 0 || alloca_alignment == frame_alignment); + CError_ASSERT(897, alloca_alignment == 0 || alloca_alignment == frame_alignment); update_asm_nonvolatile_registers(); LR_save_offset = 8; @@ -265,8 +270,7 @@ void compute_frame_sizes(void) { 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); + CError_ASSERT(1005, !dynamic_align_stack); linkage_area_size = 0; frame_size = 0; genuine_frame_size = local_data_size + nonvolatile_save_size; @@ -276,8 +280,7 @@ void compute_frame_sizes(void) { 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); + CError_ASSERT(1019, !large_data_far_size); large_data_near_size += parameter_area_size; parameter_area_size = 0; } @@ -295,12 +298,10 @@ void compute_frame_sizes(void) { static void allocate_new_frame(int reg1, int reg2) { if (dynamic_align_stack) { -#line 1116 - CError_ASSERT(reg1 != _CALLER_SP_); + CError_ASSERT(1116, reg1 != _CALLER_SP_); emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31); if (frame_size > 0x7FFF) { -#line 1122 - CError_FATAL(); + CError_FATAL(1122); return; } @@ -314,12 +315,10 @@ static void allocate_new_frame(int reg1, int reg2) { emitpcode(PC_STWUX, 1, 1, reg1); } else { - if (frame_size > 0x7FFF) { -#line 1153 - CError_FATAL(); - } else { + if (frame_size > 0x7FFF) + CError_FATAL(1153); + else emitpcode(PC_STWU, 1, 1, 0, -frame_size); - } if (reg2) emitpcode(PC_MR, reg2, 1); @@ -347,10 +346,9 @@ void generate_prologue(PCodeBlock *block, Boolean has_varargs) { 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(); - } + ) + CError_FATAL(1197); + _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg; deletepcode(setup_caller_sp); setup_caller_sp = NULL; @@ -401,8 +399,7 @@ void generate_prologue(PCodeBlock *block, Boolean has_varargs) { } allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0); } else { -#line 1326 - CError_ASSERT(!dynamic_align_stack); + CError_ASSERT(1326, !dynamic_align_stack); if (vrsave_mask) emitpcode(PC_MFSPR, vrsave_register, 256); } @@ -626,9 +623,9 @@ static void restore_nonvolatile_GPRs(int reg, SInt32 offset) { } } -static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) { +static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { load_store_register(PC_LWZ, reg2, 1, NULL, 0); - if (flag1) { + if (isConstantSize) { size = ALIGN(size, frame_alignment); if (size < 0x8000) { emitpcode(PC_STWU, reg2, 1, 0, -size); @@ -645,10 +642,10 @@ static void do_allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, S } } -void allocate_dynamic_stack_space(Boolean flag1, int reg1, int reg2, SInt32 size) { +void allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { if (copts.altivec_model) update_frame_align(16); - do_allocate_dynamic_stack_space(flag1, reg1, reg2, size); + do_allocate_dynamic_stack_space(isConstantSize, reg1, reg2, size); add_immediate(reg1, 1, dummylocal, 0); } @@ -796,10 +793,8 @@ void check_dynamic_aligned_frame(void) { 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_); + CError_ASSERT(2091, !has_varargs || _CALLER_SP_ != -1); + CError_ASSERT(2096, _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); @@ -894,7 +889,7 @@ void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVara flag = hasVarargs; if (flag) { pos = ALIGN(pos + 24, 16) - 24; - obj->u.var.offset = pos; + obj->u.var.uid = pos; pos += 16; update_in_param_align(16); Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; @@ -907,8 +902,7 @@ void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVara } in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size; -#line 2408 - CError_ASSERT(!dummyvaparam); + CError_ASSERT(2408, !dummyvaparam); } SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) { @@ -991,23 +985,22 @@ SInt32 local_offset_32(Object *obj) { return offset + localsbase(); } -SInt16 local_offset_lo(Object *obj, SInt32 offset) { +SInt32 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 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 local_offset_16(Object *obj) { SInt32 offset32 = local_offset_32(obj); SInt16 offset16 = (SInt16) offset32; -#line 2662 - CError_ASSERT(offset32 == offset16); + CError_ASSERT(2662, offset32 == offset16); return offset16; } @@ -1050,15 +1043,13 @@ static UInt32 align_bits(UInt32 value, UInt8 bitcount) { case 0x1000: return base + 19; case 0x2000: return base + 18; default: - #line 2754 - CError_FATAL(); + CError_FATAL(2754); return base + 27; } } Boolean is_large_frame(void) { -#line 2769 - CError_ASSERT(frame_size != -1); + CError_ASSERT(2769, frame_size != -1); return large_stack; } @@ -1082,12 +1073,10 @@ SInt32 get_alloca_alignment(void) { if (copts.altivec_model) align = ALIGN(align, 16); - if (!alloca_alignment) { + if (!alloca_alignment) alloca_alignment = align; - } else { -#line 2825 - CError_ASSERT(alloca_alignment == align); - } + else + CError_ASSERT(2825, alloca_alignment == align); return align_bits(align, 0); } @@ -1106,8 +1095,7 @@ static Boolean use_helper_function(char rclass) { 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(); + CError_FATAL(2862); return 0; } } @@ -1178,8 +1166,7 @@ static SInt32 nearest_power_of_two(SInt32 n) { power <<= 1; } while (power && power < n); -#line 2933 - CError_ASSERT(power != 0); + CError_ASSERT(2933, power != 0); return power; } diff --git a/compiler_and_linker/unsorted/StrengthReduction.c b/compiler_and_linker/unsorted/StrengthReduction.c index e9bc134..462653a 100644 --- a/compiler_and_linker/unsorted/StrengthReduction.c +++ b/compiler_and_linker/unsorted/StrengthReduction.c @@ -620,12 +620,10 @@ static void combineinductionvariables(Loop *loop, BasicInductionVar *biv1, Basic instr2 = NULL; reg1 = biv1->reg; -#line 930 - CError_ASSERT(reg1 >= 0); + CError_ASSERT(930, reg1 >= 0); reg2 = biv2->reg; -#line 934 - CError_ASSERT(reg2 >= 0); + CError_ASSERT(934, reg2 >= 0); if (!FITS_IN_SHORT(difference)) return; diff --git a/compiler_and_linker/unsorted/StructMoves.c b/compiler_and_linker/unsorted/StructMoves.c index e69de29..a07ef03 100644 --- a/compiler_and_linker/unsorted/StructMoves.c +++ b/compiler_and_linker/unsorted/StructMoves.c @@ -0,0 +1,792 @@ +#include "compiler/StructMoves.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" + +void make_addressable(Operand *opnd, SInt32 offset, int unusedArg) { + int reg; + + if (opnd->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opnd); + + if (opnd->optype != OpndType_IndirectGPR_ImmOffset || (opnd->immOffset + offset) > 0x7FFF) { + reg = used_virtual_registers[RegClass_GPR]++; + load_address(reg, opnd); + opnd->optype = OpndType_IndirectGPR_ImmOffset; + opnd->reg = reg; + opnd->object = NULL; + opnd->immOffset = 0; + } +} + +static void load_displaced_address(Operand *opnd, SInt32 offset) { + int reg; + + reg = used_virtual_registers[RegClass_GPR]++; + if (opnd->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opnd); + + if (opnd->optype == OpndType_IndirectGPR_ImmOffset) { + offset += opnd->immOffset; + if (!FITS_IN_SHORT(offset)) { + add_immediate(reg, opnd->reg, opnd->object, opnd->immOffset); + emitpcode(PC_ADDI, reg, reg, 0, offset - opnd->immOffset); + } else { + add_immediate(reg, opnd->reg, opnd->object, offset); + } + } else if (opnd->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_ADD, reg, opnd->reg, opnd->regOffset); + emitpcode(PC_ADDI, reg, reg, 0, offset); + } else { + CError_FATAL(80); + } + + opnd->optype = OpndType_IndirectGPR_ImmOffset; + opnd->reg = reg; + opnd->object = NULL; + opnd->immOffset = 0; +} + +static void move_block_via_load_store(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + SInt32 step; + SInt32 pos; + int floatReg; + int reg; + + if (src->optype == OpndType_IndirectSymbol) + coerce_to_addressable(src); + if (dst->optype == OpndType_IndirectSymbol) + coerce_to_addressable(dst); + + if (len == 8) { + floatReg = used_virtual_registers[RegClass_FPR]++; + if (src->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register(PC_LFD, floatReg, src->reg, src->object, src->immOffset); + setpcodeflags(src->flags); + } else if (src->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_LFDX, floatReg, src->reg, src->regOffset); + setpcodeflags(src->flags); + } else { + CError_FATAL(145); + } + + if (dst->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register(PC_STFD, floatReg, dst->reg, dst->object, dst->immOffset); + setpcodeflags(dst->flags); + } else if (dst->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_STFDX, floatReg, dst->reg, dst->regOffset); + setpcodeflags(dst->flags); + } else { + CError_FATAL(157); + } + + return; + } + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; + } + + if (step != len) { + if (dst->optype == OpndType_IndirectGPR_Indexed) + make_addressable(dst, len, 0); + if (src->optype == OpndType_IndirectGPR_Indexed) + make_addressable(src, len, 0); + } + + for (pos = 0; len != 0; len -= step, pos += step) { + reg = used_virtual_registers[RegClass_GPR]++; + if (src->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + } else if (src->optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + (step == 1) ? PC_LBZX : (step == 2) ? PC_LHZX : PC_LWZX, + reg, + src->reg, + src->regOffset + ); + setpcodeflags(src->flags); + } else { + CError_FATAL(183); + } + + if (dst->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + } else if (dst->optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + (step == 1) ? PC_STBX : (step == 2) ? PC_STHX : PC_STWX, + reg, + dst->reg, + dst->regOffset + ); + setpcodeflags(dst->flags); + } else { + CError_FATAL(195); + } + } +} + +static void move_block_via_load_store_sequence(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + SInt32 pos; + int i; + SInt32 step; + + pos = 0; + make_addressable(dst, len, 0); + make_addressable(src, len, 0); + + if ((align % 8) == 0) { + while (len >= 16) { + int reg1 = used_virtual_registers[RegClass_FPR]++; + int reg2 = used_virtual_registers[RegClass_FPR]++; + load_store_register(PC_LFD, reg1, src->reg, src->object, src->immOffset + pos); + setpcodeflags(src->flags); + load_store_register(PC_LFD, reg2, src->reg, src->object, src->immOffset + pos + 8); + setpcodeflags(src->flags); + + load_store_register(PC_STFD, reg1, dst->reg, dst->object, dst->immOffset + pos); + setpcodeflags(dst->flags); + load_store_register(PC_STFD, reg2, dst->reg, dst->object, dst->immOffset + pos + 8); + setpcodeflags(dst->flags); + + pos += 16; + len -= 16; + } + } + + while (len >= 8) { + if ((align % 8) == 0) { + int reg = used_virtual_registers[RegClass_FPR]++; + + load_store_register(PC_LFD, reg, src->reg, src->object, src->immOffset + pos); + setpcodeflags(src->flags); + + load_store_register(PC_STFD, reg, dst->reg, dst->object, dst->immOffset + pos); + setpcodeflags(dst->flags); + + pos += 8; + len -= 8; + } else { + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp > 2) ? 2 : 1; + } else { + step = 4; + } + + for (i = 0; i < 8; i += (step * 2)) { + int reg1 = used_virtual_registers[RegClass_GPR]++; + int reg2 = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg1, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg2, + src->reg, + src->object, + src->immOffset + pos + step + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg1, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg2, + dst->reg, + dst->object, + dst->immOffset + pos + step + ); + setpcodeflags(dst->flags); + + pos += (step * 2); + len -= (step * 2); + } + } + } + + while (len) { + int reg; + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; + } + + reg = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + + len -= step; + pos += step; + } +} + +static void move_block_via_inline_loop(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + PCodeLabel *label; // r25 + SInt32 pos; // r25 + SInt32 step; // r24 + int reg1; // r22 + int reg2; // r23 + SInt32 remainder; // r23 + + label = makepclabel(); + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = 4; + } + + load_displaced_address(dst, -step); + load_displaced_address(src, -step); + + CError_ASSERT(377, (len / step) != 0); + + reg1 = used_virtual_registers[RegClass_GPR]++; + load_immediate(reg1, len / (step * 2)); + emitpcode(PC_MTCTR, reg1); + branch_label(label); + + reg1 = used_virtual_registers[RegClass_GPR]++; + reg2 = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg1, + src->reg, + NULL, + step + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_LBZU : (step == 2) ? PC_LHZU : PC_LWZU, + reg2, + src->reg, + NULL, + step * 2 + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg1, + dst->reg, + NULL, + step + ); + setpcodeflags(dst->flags); + + load_store_register( + (step == 1) ? PC_STBU : (step == 2) ? PC_STHU : PC_STWU, + reg2, + dst->reg, + NULL, + step * 2 + ); + setpcodeflags(dst->flags); + + branch_decrement_always(PC_BDNZ, label); + + for (remainder = len & 7, pos = step; remainder != 0; remainder -= step, pos += step) { + int reg; + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > remainder) ? remainder : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) remainder > 4) ? 4 : ((UInt32) remainder <= 2) ? remainder : 2; + } + + reg = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + NULL, + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + NULL, + pos + ); + setpcodeflags(dst->flags); + } +} + +void move_block(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + Operand myDst; + + myDst = *dst; + + CError_ASSERT(447, myDst.optype >= OpndType_IndirectGPR_ImmOffset); + CError_ASSERT(449, src->optype >= OpndType_IndirectGPR_ImmOffset); + + if (len == 1 || len == 2 || len == 4) + move_block_via_load_store(&myDst, src, len, align); + else if (len == 8 && align == 8) + move_block_via_load_store(&myDst, src, len, align); + else if (len <= 16 || (copts.optimize_for_size == 0 && len <= 64)) + move_block_via_load_store_sequence(&myDst, src, len, align); + else + move_block_via_inline_loop(&myDst, src, len, align); +} + +static void load_word_of_small_struct(short dstReg, short srcReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { + short tmpReg; + short extra = 0; + + switch (len) { + case 1: + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + break; + case 2: + case 3: + if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); + extra += 2; + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); + extra += 2; + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); + setpcodeflags(opnd->flags); + } + if (len == 3) { + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + extra); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); + setpcodeflags(opnd->flags); + } + break; + case 4: + if (align > 2) { + load_store_register(PC_LWZ, dstReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + } else if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); + setpcodeflags(opnd->flags); + + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 16, 31); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 3); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 24, 31); + setpcodeflags(opnd->flags); + } + break; + } +} + +void load_small_block_into_reg(short dstReg, Operand *srcOpnd, Type *type, SInt32 align) { + short finalReg; + short tmpReg; + SInt32 absAddress; + + coerce_to_addressable(srcOpnd); + + if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(557); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, srcOpnd); + srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; + srcOpnd->reg = tmpReg; + srcOpnd->object = NULL; + srcOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + switch (srcOpnd->optype) { + case OpndType_GPRPair: + return; + case OpndType_GPR: + return; + case OpndType_GPR_ImmOffset: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + add_immediate(finalReg, srcOpnd->reg, srcOpnd->object, srcOpnd->immOffset); + break; + case OpndType_GPR_Indexed: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, finalReg, srcOpnd->reg, srcOpnd->regOffset); + break; + case OpndType_Absolute: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + absAddress = srcOpnd->immediate; + if (FITS_IN_SHORT(absAddress)) { + emitpcode(PC_LI, finalReg, absAddress); + } else { + tmpReg = finalReg; + if (copts.optimizationlevel > 1 && absAddress) + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); + if (absAddress) + emitpcode(PC_ADDI, finalReg, tmpReg, 0, LOW_PART(absAddress)); + } + break; + case OpndType_IndirectGPR_ImmOffset: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + load_word_of_small_struct(finalReg, srcOpnd->reg, srcOpnd, srcOpnd->immOffset, type->size, align); + break; + default: + CError_FATAL(606); + } + + srcOpnd->optype = OpndType_GPR; + srcOpnd->reg = finalReg; +} + +void load_small_block_into_reg_pair(short dstRegLo, short dstRegHi, Operand *srcOpnd, Type *type, SInt32 align) { + short finalRegLo; + short finalRegHi; + short tmpRegLo; + short tmpRegHi; + short tmpReg; + SInt32 absAddress; + + finalRegHi = -1; + coerce_to_addressable(srcOpnd); + + if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(624); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, srcOpnd); + srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; + srcOpnd->reg = tmpReg; + srcOpnd->object = NULL; + srcOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + switch (srcOpnd->optype) { + case OpndType_GPRPair: + if (dstRegLo != 0 && dstRegHi == 0) + dstRegHi = used_virtual_registers[RegClass_GPR]++; + if (dstRegHi != 0 && dstRegLo == 0) + dstRegLo = used_virtual_registers[RegClass_GPR]++; + + if (srcOpnd->reg != dstRegLo || srcOpnd->regHi != dstRegHi) { + tmpRegLo = dstRegLo ? dstRegLo : srcOpnd->reg; + tmpRegHi = dstRegHi ? dstRegHi : srcOpnd->regHi; + + if (tmpRegLo != srcOpnd->reg) { + if (tmpRegLo == srcOpnd->regHi) { + CError_ASSERT(657, tmpRegLo != tmpRegHi); + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + } else { + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + if (srcOpnd->regHi != tmpRegHi) + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + } + } else if (tmpRegHi != srcOpnd->regHi) { + if (tmpRegHi == srcOpnd->reg) { + CError_ASSERT(671, tmpRegLo != tmpRegHi); + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + } else { + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + if (srcOpnd->reg != tmpRegLo) + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + } + } + } + + finalRegLo = srcOpnd->reg; + finalRegHi = srcOpnd->regHi; + break; + case OpndType_GPR: + CError_FATAL(688); + break; + case OpndType_GPR_ImmOffset: + CError_FATAL(691); + break; + case OpndType_GPR_Indexed: + CError_FATAL(694); + break; + case OpndType_Absolute: + finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; + absAddress = srcOpnd->immediate; + if (FITS_IN_SHORT(absAddress)) { + emitpcode(PC_LI, finalRegLo, absAddress); + } else { + tmpReg = finalRegLo; + if (copts.optimizationlevel > 1 && absAddress) + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); + if (absAddress) + emitpcode(PC_ADDI, finalRegLo, tmpReg, 0, LOW_PART(absAddress)); + } + + finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; + if (is_unsigned(type) || absAddress >= 0) + load_immediate(finalRegHi, 0); + else + load_immediate(finalRegHi, -1); + + break; + case OpndType_IndirectGPR_ImmOffset: + finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; + finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; + if (srcOpnd->reg == finalRegHi) { + if (srcOpnd->reg == finalRegLo) { + CError_FATAL(726); + } else { + load_word_of_small_struct( + finalRegLo, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + low_offset, type->size - 4, align); + load_word_of_small_struct( + finalRegHi, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + high_offset, 4, align); + } + } else { + load_word_of_small_struct( + finalRegHi, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + high_offset, 4, align); + load_word_of_small_struct( + finalRegLo, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + low_offset, type->size - 4, align); + } + break; + default: + CError_FATAL(737); + } + + if (finalRegHi == -1) { + CError_FATAL(741); + } else { + srcOpnd->optype = OpndType_GPRPair; + srcOpnd->reg = finalRegLo; + srcOpnd->regHi = finalRegHi; + } +} + +static void store_word_of_small_struct(short srcReg, short dstReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { + short tmpReg; + short extra = 0; + + switch (len) { + case 1: + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + break; + case 2: + case 3: + if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); + extra += 2; + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); + extra += 2; + setpcodeflags(opnd->flags); + } + if (len == 3) { + emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + extra); + setpcodeflags(opnd->flags); + } + break; + case 4: + if (align > 2) { + load_store_register(PC_STW, srcReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + } else if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + load_store_register(PC_STH, srcReg, dstReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + + load_store_register(PC_STB, srcReg, dstReg, opnd->object, offset + 3); + setpcodeflags(opnd->flags); + } + break; + } +} + +void store_small_block_from_reg(short srcReg, Operand *dstOpnd, Type *type, SInt32 align) { + short tmpReg; + + coerce_to_addressable(dstOpnd); + + if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(839); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, dstOpnd); + dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; + dstOpnd->reg = tmpReg; + dstOpnd->object = NULL; + dstOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + store_word_of_small_struct(srcReg, dstOpnd->reg, dstOpnd, dstOpnd->immOffset, type->size, align); +} + +void store_small_block_from_reg_pair(short srcRegLo, short srcRegHi, Operand *dstOpnd, Type *type, SInt32 align) { + short tmpReg; + + coerce_to_addressable(dstOpnd); + + if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(860); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, dstOpnd); + dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; + dstOpnd->reg = tmpReg; + dstOpnd->object = NULL; + dstOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + store_word_of_small_struct( + srcRegLo, dstOpnd->reg, dstOpnd, + dstOpnd->immOffset + low_offset, type->size - 4, align); + store_word_of_small_struct( + srcRegHi, dstOpnd->reg, dstOpnd, + dstOpnd->immOffset + high_offset, 4, align); +} diff --git a/compiler_and_linker/unsorted/Switch.c b/compiler_and_linker/unsorted/Switch.c index 185ec71..8fd45b8 100644 --- a/compiler_and_linker/unsorted/Switch.c +++ b/compiler_and_linker/unsorted/Switch.c @@ -126,8 +126,7 @@ static void treecompare(SInt32 start, SInt32 end) { int count; count = end - start; -#line 175 - CError_ASSERT(selector_type->size <= 4); + CError_ASSERT(175, selector_type->size <= 4); r29 = start + (count >> 1) + 1; currange = caseranges + r29; @@ -398,8 +397,7 @@ static void generate_table(ENode *expr, SwitchInfo *info) { } table = create_switch_table(); -#line 553 - CError_ASSERT(!TYPE_IS_8BYTES(expr->rtype)); + CError_ASSERT(553, !TYPE_IS_8BYTES(expr->rtype)); GEN_NODE(expr, &op1); if (expr->rtype->size < 4) @@ -446,8 +444,7 @@ static void generate_table(ENode *expr, SwitchInfo *info) { } if (op2.optype != OpndType_GPR) { -#line 599 - CError_FATAL(); + CError_FATAL(599); } else { if (op2.reg != reg2) emitpcode(PC_MR, reg2, op2.reg); @@ -482,8 +479,7 @@ void switchstatement(ENode *expr, SwitchInfo *info) { ncases++; } -#line 656 - CError_ASSERT(ncases >= 0 && ncases <= 0x3333332U); + CError_ASSERT(656, ncases >= 0 && ncases <= 0x3333332U); if (!info->defaultlabel->pclabel) info->defaultlabel->pclabel = makepclabel(); @@ -510,8 +506,7 @@ void dumpswitchtables(Object *funcobj) { for (list = switchtables; list; list = list->next) { table = list->object; -#line 694 - CError_ASSERT(table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA); + CError_ASSERT(694, table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA); size = table->u.data.u.switchtable.size; array = (UInt32 *) table->u.data.u.switchtable.data; diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c index 94ecb27..49ae3e1 100644 --- a/compiler_and_linker/unsorted/TOC.c +++ b/compiler_and_linker/unsorted/TOC.c @@ -2,16 +2,22 @@ #include "compiler/TOC.h" #include "compiler/CDecl.h" #include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" #include "compiler/CInt64.h" #include "compiler/CFunc.h" #include "compiler/CMachine.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CodeGen.h" +#include "compiler/Exceptions.h" #include "compiler/InstrSelection.h" +#include "compiler/ObjGenMachO.h" #include "compiler/Operands.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" #include "compiler/StackFrame.h" #include "compiler/CompilerTools.h" #include "compiler/enode.h" @@ -142,8 +148,7 @@ void referenceIndirectPointer(Object *obj) { } Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) { -#line 622 - CError_ASSERT(!copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000)); + CError_ASSERT(622, !copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000)); if (CParser_HasInternalLinkage(obj)) return NULL; @@ -191,14 +196,12 @@ Object *createfloatconstant(Type *type, Float *data) { obj->sclass = OBJECT_SCLASS_102; obj->qual = Q_CONST | Q_10000; obj->datatype = DDATA; - if (type->size == 8) { + if (type->size == 8) obj->section = SECT_8BYTE_LITERALS; - } else if (type->size == 4) { + else if (type->size == 4) obj->section = SECT_4BYTE_LITERALS; - } else { -#line 807 - CError_FATAL(); - } + else + CError_FATAL(807); obj->flags |= OBJECT_FLAGS_2; @@ -238,12 +241,10 @@ Object *createvectorconstant(Type *type, MWVector128 *data) { obj->sclass = OBJECT_SCLASS_102; obj->qual = Q_CONST | Q_10000; obj->datatype = DDATA; - if (type->size == 16) { + if (type->size == 16) obj->section = SECT_16BYTE_LITERALS; - } else { -#line 900 - CError_FATAL(); - } + else + CError_FATAL(900); obj->flags |= OBJECT_FLAGS_2; @@ -542,8 +543,7 @@ static Type *common_type(Type *type1, Type *type2) { if (type1 == (Type *) &stsignedlong) { type1 = (Type *) &stunsignedlong; } else { -#line 1789 - CError_ASSERT(type1 == (Type *) &stsignedlonglong); + CError_ASSERT(1789, type1 == (Type *) &stsignedlonglong); type1 = (Type *) &stunsignedlonglong; } } @@ -1016,8 +1016,7 @@ static Boolean DetectCondSideAffect(ENode *expr) { case ECONDASS: return 1; default: -#line 2523 - CError_FATAL(); + CError_FATAL(2523); return 1; } } @@ -1261,8 +1260,7 @@ void Optimize64bitMath(ENode *expr) { SInt32 totalsize; // r22 int unsignedflag; // r4 -#line 2886 - CError_ASSERT(TYPE_IS_8BYTES(expr->rtype)); + CError_ASSERT(2886, TYPE_IS_8BYTES(expr->rtype)); left = expr->data.diadic.left; right = expr->data.diadic.right; @@ -1312,8 +1310,7 @@ void Optimize64bitMath(ENode *expr) { case 16: break; default: -#line 2975 - CError_FATAL(); + CError_FATAL(2975); } } @@ -1382,8 +1379,7 @@ static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) { case EANDASS: case EXORASS: case EORASS: -#line 3033 - CError_FATAL(); + CError_FATAL(3033); return 0; } if (OptimizeNestedAssginments(&expr->data.diadic.right, check)) @@ -1431,8 +1427,7 @@ static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) { case EASSBLK: return 0; default: -#line 3083 - CError_FATAL(); + CError_FATAL(3083); return 0; } } @@ -1469,8 +1464,7 @@ static void expandTOCexpression(ENode *expr, Type *type, int ignored) { break; case EOBJREF: obj = expr->data.objref; -#line 3203 - CError_ASSERT(obj->datatype != DALIAS); + CError_ASSERT(3203, obj->datatype != DALIAS); if (obj->datatype == DFUNC || obj->datatype == DVFUNC) uses_globals = 1; if (obj->datatype == DDATA) { diff --git a/compiler_and_linker/unsorted/Unmangle.c b/compiler_and_linker/unsorted/Unmangle.c index e69de29..c0168c7 100644 --- a/compiler_and_linker/unsorted/Unmangle.c +++ b/compiler_and_linker/unsorted/Unmangle.c @@ -0,0 +1,1022 @@ +#include "compiler/Unmangle.h" + +typedef struct UnmangleBuffer { + char *buf; + size_t remaining; +} UnmangleBuffer; + +// forward decls +static const char *Unmangle_Type(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p); + +static void Unmangle_Error(jmp_buf errorbuf) { + longjmp(errorbuf, 1); +} + +static void Unmangle_BufferInit(UnmangleBuffer *ub, char *buf, size_t size) { + ub->buf = buf; + ub->remaining = size - 1; +} + +static void Unmangle_BufferAppendChar(UnmangleBuffer *ub, char ch) { + if (ub && ub->remaining) { + *(ub->buf++) = ch; + ub->remaining--; + } +} + +static void Unmangle_BufferAppendString(UnmangleBuffer *ub, const char *str) { + size_t len; + + if (ub) { + len = strlen(str); + if (ub->remaining < len) + len = ub->remaining; + + memcpy(ub->buf, str, len); + ub->buf += len; + ub->remaining -= len; + } +} + +static void Unmangle_BufferTerminate(UnmangleBuffer *ub) { + ub->buf[0] = 0; + ub->remaining = 0; +} + +static const char *Unmangle_TemplateParams(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) { + const char *p2; + + Unmangle_BufferAppendChar(ub, '<'); + + while (1) { + switch (*p) { + case '&': + case '=': + if (*(p++) == '&') + Unmangle_BufferAppendChar(ub, '&'); + + while (1) { + switch (*p) { + case ',': + case '>': + break; + case 0: + Unmangle_Error(errorbuf); + break; + default: + Unmangle_BufferAppendChar(ub, *(p++)); + continue; + } + break; + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + p2 = p + 1; + while (1) { + if (*p2 == 0) + Unmangle_Error(errorbuf); + + if (*p2 == ',' || *p2 == '>') { + do { + Unmangle_BufferAppendChar(ub, *(p++)); + } while (*p != '>' && *p != ','); + break; + } else if (!(*p2 >= '0' && *p2 <= '9')) { + p = Unmangle_Type(errorbuf, ub, p); + break; + } + + p2++; + } + break; + + default: + p = Unmangle_Type(errorbuf, ub, p); + } + + if (*p == '>') + break; + + if (*(p++) != ',') + Unmangle_Error(errorbuf); + + Unmangle_BufferAppendString(ub, ", "); + } + + Unmangle_BufferAppendChar(ub, '>'); + return p + 1; +} + +static const char *Unmangle_SpecialName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) { + const char *what; + Boolean flag = 0; + + switch (*(p++)) { + case 'a': + switch (*(p++)) { + case 'a': + switch (*(p++)) { + case '_': + what = "operator &&"; + p--; + break; + case 'd': + what = "operator &="; + break; + default: + return NULL; + } + break; + case 'd': + switch (*(p++)) { + case '_': + what = "operator &"; + p--; + break; + case 'v': + what = "operator /="; + break; + default: + return NULL; + } + break; + case 'e': + switch (*(p++)) { + case 'r': + what = "operator ^="; + break; + default: + return NULL; + } + break; + case 'l': + switch (*(p++)) { + case 's': + what = "operator <<="; + break; + default: + return NULL; + } + break; + case 'm': + switch (*(p++)) { + case 'd': + what = "operator %="; + break; + case 'i': + what = "operator -="; + break; + case 'u': + what = "operator *="; + break; + default: + return NULL; + } + break; + case 'o': + switch (*(p++)) { + case 'r': + what = "operator |="; + break; + default: + return NULL; + } + break; + case 'p': + switch (*(p++)) { + case 'l': + what = "operator +="; + break; + default: + return NULL; + } + break; + case 'r': + switch (*(p++)) { + case 's': + what = "operator >>="; + break; + default: + return NULL; + } + break; + case 's': + what = "operator ="; + break; + default: + return NULL; + } + break; + case 'c': + switch (*(p++)) { + case 'l': + what = "operator ()"; + break; + case 'm': + what = "operator ,"; + break; + case 'o': + what = "operator ~"; + break; + case 't': + what = "!"; + break; + default: + return NULL; + } + break; + case 'd': + switch (*(p++)) { + case 'l': + if (*p == 'a') { + what = "operator delete[]"; + p++; + } else { + what = "operator delete"; + } + break; + case 't': + what = "~"; + break; + case 'v': + what = "operator /"; + break; + default: + return NULL; + } + break; + case 'e': + switch (*(p++)) { + case 'q': + what = "operator =="; + break; + case 'r': + what = "operator ^"; + break; + default: + return NULL; + } + break; + case 'g': + switch (*(p++)) { + case 'e': + what = "operator >="; + break; + case 't': + what = "operator >"; + break; + default: + return NULL; + } + break; + case 'l': + switch (*(p++)) { + case 'e': + what = "operator <="; + break; + case 's': + what = "operator <<"; + break; + case 't': + what = "operator <"; + break; + default: + return NULL; + } + break; + case 'm': + switch (*(p++)) { + case 'd': + what = "operator %"; + break; + case 'i': + what = "operator -"; + break; + case 'l': + what = "operator *"; + break; + case 'm': + what = "operator --"; + break; + default: + return NULL; + } + break; + case 'n': + switch (*(p++)) { + case 'e': + what = "operator !="; + break; + case 't': + what = "operator !"; + break; + case 'w': + if (*p == 'a') { + what = "operator new[]"; + p++; + } else { + what = "operator new"; + } + break; + default: + return NULL; + } + break; + case 'o': + switch (*(p++)) { + case 'r': + what = "operator |"; + break; + case 'o': + what = "operator ||"; + break; + case 'p': + Unmangle_BufferAppendString(ub, "operator "); + p = Unmangle_Type(errorbuf, ub, p); + flag = 1; + break; + default: + return NULL; + } + break; + case 'p': + switch (*(p++)) { + case 'l': + what = "operator +"; + break; + case 'p': + what = "operator ++"; + break; + default: + return NULL; + } + break; + case 'r': + switch (*(p++)) { + case 'f': + what = "operator ->"; + break; + case 's': + what = "operator >>"; + break; + case 'm': + what = "operator ->*"; + break; + default: + return NULL; + } + break; + case 'v': + switch (*(p++)) { + case 'c': + what = "operator []"; + break; + default: + return NULL; + } + break; + default: + return NULL; + } + + if (!flag) { + if (*p) { + Unmangle_BufferAppendString(ub, what); + if (*p == '<') + p = Unmangle_TemplateParams(errorbuf, ub, p + 1); + if (!(*(p++) == '_' && *(p++) == '_')) + return NULL; + } + } else { + if (!(*(p++) == '_' && *(p++) == '_')) + return NULL; + } + + Unmangle_BufferTerminate(ub); + return p; +} + +static const char *Unmangle_ClassName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, size_t len, Boolean flag) { + int ch; + const char *p2; + + while (len--) { + ch = *(p++); + if (!ch) + Unmangle_Error(errorbuf); + + if (ch == '<') { + p2 = Unmangle_TemplateParams(errorbuf, flag ? ub : NULL, p); + len -= (p2 - p); + if (len == 0) + return p2; + Unmangle_Error(errorbuf); + } else { + Unmangle_BufferAppendChar(ub, ch); + } + } + + return p; +} + +static const char *Unmangle_QClassName(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, Boolean flag1, Boolean flag2) { + const char *lastPiece; + size_t len; + int i; + int ch; + int count; + + if (*p == 'Q') { + p++; + count = *(p++) - '0'; + if (count < 1 || count > 9) + Unmangle_Error(errorbuf); + } else { + count = 1; + } + + for (i = 0; i < count; i++) { + if (i && ub) + Unmangle_BufferAppendString(ub, "::"); + + if (*p < '0' || *p > '9') + Unmangle_Error(errorbuf); + + len = 0; + while ((ch = *p) >= '0' && ch <= '9') { + len = len * 10 + ch - '0'; + p++; + } + + if (len == 0) + Unmangle_Error(errorbuf); + + lastPiece = p; + p = Unmangle_ClassName(errorbuf, ub, p, len, 1); + } + + if (flag1 && ub) { + if (flag2) + Unmangle_BufferAppendString(ub, "::~"); + else + Unmangle_BufferAppendString(ub, "::"); + Unmangle_ClassName(errorbuf, ub, lastPiece, len, 0); + } + + return p; +} + +static const char *Unmangle_Modifiers(UnmangleBuffer *ub, const char *p) { + const char *what; + Boolean isFirst = 1; + + while (1) { + switch (*p) { + case 'U': + what = "unsigned"; + break; + case 'C': + what = "const"; + break; + case 'V': + what = "volatile"; + break; + case 'S': + what = "signed"; + break; + default: + return p; + } + + if (!isFirst) + Unmangle_BufferAppendChar(ub, ' '); + Unmangle_BufferAppendString(ub, what); + + isFirst = 0; + p++; + } +} + +static const char *Unmangle_PointerType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) { + const char *modifiers; + + modifiers = p; + p = Unmangle_Modifiers(NULL, p); + if (modifiers == p) + modifiers = NULL; + + switch (*p) { + case 'P': + p = Unmangle_PointerType(errorbuf, ub, p + 1); + if (ub) { + Unmangle_BufferAppendChar(ub, '*'); + if (modifiers) + Unmangle_Modifiers(ub, modifiers); + } + return p; + case 'R': + p = Unmangle_PointerType(errorbuf, ub, p + 1); + if (ub) { + Unmangle_BufferAppendChar(ub, '&'); + if (modifiers) + Unmangle_Modifiers(ub, modifiers); + } + return p; + case 'M': + p = Unmangle_QClassName(errorbuf, ub, p + 1, 0, 0); + if (ub) { + Unmangle_BufferAppendString(ub, "::*"); + if (modifiers) + Unmangle_Modifiers(ub, modifiers); + } + return p; + default: + return p; + } +} + +static const char *Unmangle_ArrayType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *pointer) { + const char *digits; + + digits = ++p; + + while (1) { + switch (*(p++)) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + continue; + case '_': + if (*p == 'A') { + p++; + continue; + } + break; + default: + Unmangle_Error(errorbuf); + } + break; + } + + p = Unmangle_Type(errorbuf, ub, p); + + if (ub) { + if (pointer) { + Unmangle_BufferAppendString(ub, " ("); + Unmangle_PointerType(errorbuf, ub, pointer); + Unmangle_BufferAppendChar(ub, ')'); + } + + Unmangle_BufferAppendChar(ub, '['); + + while (1) { + switch (*digits) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Unmangle_BufferAppendChar(ub, *(digits++)); + continue; + case '_': + if (digits[1] == 'A') { + Unmangle_BufferAppendString(ub, "]["); + digits += 2; + continue; + } + break; + default: + Unmangle_Error(errorbuf); + } + break; + } + + Unmangle_BufferAppendChar(ub, ']'); + } + + return p; +} + +static const char *Unmangle_FunctionType(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *pointer) { + const char *returnType; + + returnType = ++p; + + while (*p != '_') + p = Unmangle_Type(errorbuf, NULL, p); + + p = Unmangle_Type(errorbuf, ub, p + 1); + + if (ub) { + if (pointer) { + Unmangle_BufferAppendString(ub, " ("); + Unmangle_PointerType(errorbuf, ub, pointer); + Unmangle_BufferAppendChar(ub, ')'); + } + + Unmangle_BufferAppendChar(ub, '('); + + if (*returnType != '_') { + while (1) { + returnType = Unmangle_Type(errorbuf, ub, returnType); + if (*returnType == '_') + break; + Unmangle_BufferAppendString(ub, ", "); + } + } + + Unmangle_BufferAppendChar(ub, ')'); + } + + return p; +} + +static const char *Unmangle_Pointer(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *modifiers, char c) { + const char *pointer; + const char *tmp; + + pointer = p; + tmp = Unmangle_PointerType(errorbuf, NULL, p); + switch (*tmp) { + case 'A': + if (modifiers) + pointer = modifiers; + return Unmangle_ArrayType(errorbuf, ub, tmp, pointer); + case 'F': + if (modifiers) + pointer = modifiers; + return Unmangle_FunctionType(errorbuf, ub, tmp, pointer); + default: + if (c == 'M') { + p = Unmangle_QClassName(errorbuf, NULL, p + 1, 0, 0); + p = Unmangle_Type(errorbuf, ub, p); + if (ub) { + Unmangle_BufferAppendChar(ub, ' '); + Unmangle_QClassName(errorbuf, ub, pointer + 1, 0, 0); + Unmangle_BufferAppendString(ub, "::*"); + if (modifiers) + Unmangle_Modifiers(ub, modifiers); + } + } else { + p = Unmangle_Type(errorbuf, ub, p + 1); + if (ub) { + Unmangle_BufferAppendChar(ub, c); + if (modifiers) + Unmangle_Modifiers(ub, modifiers); + } + } + return p; + } +} + +static const char *Unmangle_Vector(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p, const char *modifiers) { + const char *p2 = p + 2; + switch (p[1]) { + case 'U': + switch (p[2]) { + case 'c': + p2++; + Unmangle_BufferAppendString(ub, "vector unsigned char"); + break; + case 's': + p2++; + Unmangle_BufferAppendString(ub, "vector unsigned short"); + break; + case 'i': + p2++; + Unmangle_BufferAppendString(ub, "vector unsigned int"); + break; + } + break; + case 'c': + Unmangle_BufferAppendString(ub, "vector signed char"); + break; + case 'C': + Unmangle_BufferAppendString(ub, "vector bool char"); + break; + case 's': + Unmangle_BufferAppendString(ub, "vector signed short"); + break; + case 'S': + Unmangle_BufferAppendString(ub, "vector bool short"); + break; + case 'i': + Unmangle_BufferAppendString(ub, "vector signed int"); + break; + case 'I': + Unmangle_BufferAppendString(ub, "vector bool int"); + break; + case 'f': + Unmangle_BufferAppendString(ub, "vector float"); + break; + case 'p': + Unmangle_BufferAppendString(ub, "vector pixel"); + break; + default: + p2 = p + 1; + } + + return p2; +} + +static const char *Unmangle_Type(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) { + const char *modifiers; + const char *what; + + modifiers = p; + p = Unmangle_Modifiers(NULL, p); + if (modifiers == p) + modifiers = NULL; + + switch (*p) { + case 'b': + what = "bool"; + break; + case 'v': + what = "void"; + break; + case 'c': + what = "char"; + break; + case 'w': + what = "wchar_t"; + break; + case 's': + what = "short"; + break; + case 'i': + what = "int"; + break; + case 'l': + what = "long"; + break; + case 'x': + what = "long long"; + break; + case 'f': + what = "float"; + break; + case 'D': + what = "short double"; + break; + case 'd': + what = "double"; + break; + case 'r': + what = "long double"; + break; + case 'X': + return Unmangle_Vector(errorbuf, ub, p, modifiers); + case 'P': + return Unmangle_Pointer(errorbuf, ub, p, modifiers, '*'); + case 'R': + return Unmangle_Pointer(errorbuf, ub, p, modifiers, '&'); + case 'M': + return Unmangle_Pointer(errorbuf, ub, p, modifiers, 'M'); + case 'A': + return Unmangle_ArrayType(errorbuf, ub, p, NULL); + case 'F': + return Unmangle_FunctionType(errorbuf, ub, p, NULL); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'Q': + if (modifiers) { + Unmangle_Modifiers(ub, modifiers); + Unmangle_BufferAppendChar(ub, ' '); + } + return Unmangle_QClassName(errorbuf, ub, p, 0, 0); + default: + Unmangle_Error(errorbuf); + } + + if (modifiers) { + Unmangle_Modifiers(ub, modifiers); + Unmangle_BufferAppendChar(ub, ' '); + } + Unmangle_BufferAppendString(ub, what); + + return p + 1; +} + +static void Unmangle_FuncArgList(jmp_buf errorbuf, UnmangleBuffer *ub, const char *p) { + Boolean is_volatile; + Boolean is_const; + + is_volatile = is_const = 0; + + if (*p == 'C') { + is_const = 1; + p++; + } + if (*p == 'V') { + is_volatile = 1; + p++; + } + + if (*(p++) != 'F') + Unmangle_Error(errorbuf); + + Unmangle_BufferAppendChar(ub, '('); + + if (!(p[0] == 'v' && p[1] == 0)) { + while (1) { + if (*p == 'e') { + if (p[1]) + Unmangle_Error(errorbuf); + Unmangle_BufferAppendString(ub, "..."); + break; + } + + if (*p == '_') { + p = Unmangle_Type(errorbuf, NULL, p + 1); + if (p[0]) + Unmangle_Error(errorbuf); + break; + } + + p = Unmangle_Type(errorbuf, ub, p); + if (!*p) + break; + + if (*p != '_') + Unmangle_BufferAppendChar(ub, ','); + } + } + + Unmangle_BufferAppendChar(ub, ')'); + + if (is_const) + Unmangle_BufferAppendString(ub, " const"); + if (is_volatile) + Unmangle_BufferAppendString(ub, " volatile"); + + Unmangle_BufferTerminate(ub); +} + +void MWUnmangleClassName(const char *input, char *output, size_t maxLen) { + UnmangleBuffer ub; + jmp_buf errorbuf; + const char *p; + Boolean flag; + + if (input[0] == 'Q' && (input[1] >= '1' && input[1] <= '9')) { + if (setjmp(errorbuf) == 0) { + Unmangle_BufferInit(&ub, output, maxLen); + Unmangle_QClassName(errorbuf, &ub, input, 0, 0); + Unmangle_BufferTerminate(&ub); + return; + } + } + + p = input; + flag = 0; + while (1) { + switch (*p) { + case 0: + break; + case '<': + flag = 1; + default: + p++; + continue; + } + break; + } + + if (flag) { + if (setjmp(errorbuf) == 0) { + Unmangle_BufferInit(&ub, output, maxLen); + Unmangle_ClassName(errorbuf, &ub, input, p - input, 1); + Unmangle_BufferTerminate(&ub); + return; + } + } + + strncpy(output, input, maxLen); + output[maxLen - 1] = 0; +} + +void MWUnmangle(const char *input, char *output, size_t maxLen) { + UnmangleBuffer ub_internal; + UnmangleBuffer ub; + jmp_buf errorbuf; + char mybuf[256]; + const char *p; + Boolean flag; + int ch; + + switch (*input) { + case '.': + if ("_"[0] == '.') + input++; + break; + case '_': + if ("_"[0] == '_') + input++; + switch (input[1]) { + case '%': + case '#': + case '@': + input += 2; + break; + } + break; + } + + if (setjmp(errorbuf) == 0) { + Unmangle_BufferInit(&ub_internal, mybuf, sizeof(mybuf)); + Unmangle_BufferInit(&ub, output, maxLen); + + if (!(input[0] == '_' && input[1] == '_' && (p = Unmangle_SpecialName(errorbuf, &ub_internal, input + 2)))) { + flag = 0; + Unmangle_BufferInit(&ub_internal, mybuf, sizeof(mybuf)); + for (p = input; *p == '_'; p++) + Unmangle_BufferAppendChar(&ub_internal, '_'); + + while ((ch = *(p++))) { + if (ch == '_' && *p == '_') { + while (*(++p) == '_') + Unmangle_BufferAppendChar(&ub_internal, '_'); + flag = 1; + break; + } + Unmangle_BufferAppendChar(&ub_internal, ch); + } + + Unmangle_BufferTerminate(&ub_internal); + + if (!flag) { + Unmangle_BufferAppendString(&ub, mybuf); + Unmangle_BufferTerminate(&ub); + return; + } + } + + switch (*p) { + case 'F': + if (mybuf[1] != 0 || (mybuf[0] != '!' && mybuf[0] != '~')) { + Unmangle_BufferAppendString(&ub, mybuf); + Unmangle_FuncArgList(errorbuf, &ub, p); + return; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'Q': + if (mybuf[1] == 0 && (mybuf[0] == '!' || mybuf[0] == '~')) { + p = Unmangle_QClassName(errorbuf, &ub, p, 1, mybuf[0] == '~'); + } else { + p = Unmangle_QClassName(errorbuf, &ub, p, 0, 0); + Unmangle_BufferAppendString(&ub, "::"); + Unmangle_BufferAppendString(&ub, mybuf); + if (*p == 0) { + Unmangle_BufferTerminate(&ub); + return; + } + } + Unmangle_FuncArgList(errorbuf, &ub, p); + return; + } + } + + strncpy(output, input, maxLen); + output[maxLen - 1] = 0; +} diff --git a/compiler_and_linker/unsorted/ValueNumbering.c b/compiler_and_linker/unsorted/ValueNumbering.c index e8e05c6..670471d 100644 --- a/compiler_and_linker/unsorted/ValueNumbering.c +++ b/compiler_and_linker/unsorted/ValueNumbering.c @@ -260,8 +260,7 @@ static int matchvalues(AvailableValue *av, PCode *match) { return 0; break; case PCOp_SYSREG: -#line 572 - CError_FATAL(); + CError_FATAL(572); } } } @@ -511,13 +510,11 @@ static void functioncall(PCode *pcode) { } static void operatefrommemory(PCode *pcode) { -#line 980 - CError_FATAL(); + CError_FATAL(980); } static void operatetomemory(PCode *pcode) { -#line 1011 - CError_FATAL(); + CError_FATAL(1011); } static void propagatecopiesto(PCode *pcode) { diff --git a/compiler_and_linker/unsorted/VectorArraysToRegs.c b/compiler_and_linker/unsorted/VectorArraysToRegs.c index 25a86a9..c6c4735 100644 --- a/compiler_and_linker/unsorted/VectorArraysToRegs.c +++ b/compiler_and_linker/unsorted/VectorArraysToRegs.c @@ -442,8 +442,7 @@ static void convert_array_to_register(LocalVectorArray *arrays, int addiID) { useInstr->args[0].data.reg.reg = newReg; useInstr->args[0].data.reg.effect = EffectWrite; } else { -#line 661 - CError_FATAL(); + CError_FATAL(661); } } deletepcode(addi->instr); diff --git a/compiler_and_linker/unsorted/uDump.c b/compiler_and_linker/unsorted/uDump.c new file mode 100644 index 0000000..52ab09f --- /dev/null +++ b/compiler_and_linker/unsorted/uDump.c @@ -0,0 +1,639 @@ +#include "compiler/uDump.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/Exceptions.h" +#include "compiler/Switch.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static FILE *outfile; + +// forward decls +static void spell(Type *type, char *buf); + +static void WritePString(FILE *file, char *str, int len) { + while (len--) { + switch (*str) { + case 0: + fputs("\\x00", file); + break; + case 7: + fputs("\\a", file); + break; + case 8: + fputs("\\b", file); + break; + case 12: + fputs("\\f", file); + break; + case 10: + fputs("\\n", file); + break; + case 13: + fputs("\\r", file); + break; + case 9: + fputs("\\t", file); + break; + case 11: + fputs("\\v", file); + break; + case '"': + case '\'': + case '?': + case '\\': + fputc('\\', file); + default: + fputc(*str, file); + break; + } + str++; + } +} + +static void WriteCString(FILE *file, char *str) { + WritePString(file, str, strlen(str)); +} + +static void StaticSetupDumpIR(void) { +} + +void SetupDumpIR(void) { + // unknown args + StaticSetupDumpIR(); +} + +void CleanupDumpIR(void) { +} + +void DumpIR(Statement *statements, Object *func) { +} + +void DumpExpression(ENode *expr, int indent) { + static int bt; + static int i; + static char *nodenames[] = { + "EPOSTINC", + "EPOSTDEC", + "EPREINC", + "EPREDEC", + "EINDIRECT", + "EMONMIN", + "EBINNOT", + "ELOGNOT", + "EFORCELOAD", + "EMUL", + "EMULV", + "EDIV", + "EMODULO", + "EADDV", + "ESUBV", + "EADD", + "ESUB", + "ESHL", + "ESHR", + "ELESS", + "EGREATER", + "ELESSEQU", + "EGREATEREQU", + "EEQU", + "ENOTEQU", + "EAND", + "EXOR", + "EOR", + "ELAND", + "ELOR", + "EASS", + "EMULASS", + "EDIVASS", + "EMODASS", + "EADDASS", + "ESUBASS", + "ESHLASS", + "ESHRASS", + "EANDASS", + "EXORASS", + "EORASS", + "ECOMMA", + "EPMODULO", + "EROTL", + "EROTR", + "EBCLR", + "EBTST", + "EBSET", + "ETYPCON", + "EBITFIELD", + "EINTCONST", + "EFLOATCONST", + "ESTRINGCONST", + "ECOND", + "EFUNCCALL", + "EFUNCCALLP", + "EOBJREF", + "EMFPOINTER", + "ENULLCHECK", + "EPRECOMP", + "ETEMP", + "EARGOBJ", + "ELOCOBJ", + "ELABEL", + "ESETCONST", + "ENEWEXCEPTION", + "ENEWEXCEPTIONARRAY", + "EINITTRYCATCH", + "EOBJLIST", + "EMEMBER", + "ETEMPLDEP", + "EINSTRUCTION", + "EDEFINE", + "EREUSE", + "EASSBLK", + "EVECTOR128CONST", + "ECONDASS", + NULL + }; + char buf[64]; + ENodeList *list; + + while (1) { + for (i = 0; i < indent; i++) + fputc('\t', outfile); + + if (expr->flags) + fprintf(outfile, "%s {%02X}", nodenames[expr->type], expr->flags); + else + fprintf(outfile, "%s", nodenames[expr->type]); + + switch (expr->type) { + case EINTCONST: + if (expr->rtype->size > 4) + fprintf(outfile, "[0x%.8lX%.8lX]", expr->data.intval.hi, expr->data.intval.lo); + else + fprintf(outfile, "[%ld]", expr->data.intval.lo); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case EFLOATCONST: + CMach_PrintFloat(buf, expr->data.floatval); + fprintf(outfile, "[%s]", buf); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ESTRINGCONST: + if (expr->data.string.ispascal) { + fputs("[\"", outfile); + WritePString(outfile, expr->data.string.data, expr->data.string.size); + fputs("\"]", outfile); + } else { + fputs("[\"", outfile); + WriteCString(outfile, expr->data.string.data); + fputs("\"]", outfile); + } + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case EVECTOR128CONST: + fprintf(outfile, "[0x%.8lX%.8lX%.8lX%.8lX]", + expr->data.vector128val.ul[0], + expr->data.vector128val.ul[1], + expr->data.vector128val.ul[2], + expr->data.vector128val.ul[3]); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ECOND: + case ECONDASS: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.cond.cond, indent + 1); + DumpExpression(expr->data.cond.expr1, indent + 1); + expr = expr->data.cond.expr2; + indent++; + break; + + case EFUNCCALL: + case EFUNCCALLP: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.funccall.funcref, indent + 1); + for (list = expr->data.funccall.args; list; list = list->next) + DumpExpression(list->node, indent + 1); + return; + + case EOBJREF: + switch (expr->data.objref->datatype) { + case DFUNC: + fprintf(outfile, "[%s{PR}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + case DDATA: + fprintf(outfile, "[%s{RW}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + case DNONLAZYPTR: + fprintf(outfile, "[%s{NL}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + default: + fprintf(outfile, "[%s]", expr->data.objref->name->name); + break; + } + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + ENODE_CASE_DIADIC_1: + case ELAND: + case ELOR: + ENODE_CASE_ASSIGN: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.diadic.left, indent + 1); + expr = expr->data.diadic.right; + indent++; + break; + + ENODE_CASE_MONADIC: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + expr = expr->data.monadic; + indent++; + break; + + case EMFPOINTER: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.mfpointer.accessnode, indent + 1); + expr = expr->data.mfpointer.mfpointer; + indent++; + break; + + case ENULLCHECK: + fprintf(outfile, " unique [%ld]", expr->data.nullcheck.precompid); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.nullcheck.nullcheckexpr, indent + 1); + expr = expr->data.nullcheck.condexpr; + indent++; + break; + + case EPRECOMP: + fprintf(outfile, " unique [%ld]", expr->data.precompid); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ELABEL: + fprintf(outfile, "[%s]", expr->data.label->uniquename->name); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ETEMP: + DumpType(expr->data.temp.type); + fprintf(outfile, "\r"); + return; + + case EINITTRYCATCH: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + if (expr->data.itc.initexpr) + DumpExpression(expr->data.itc.initexpr, indent + 1); + if (expr->data.itc.tryexpr) + DumpExpression(expr->data.itc.tryexpr, indent + 1); + if (expr->data.itc.catchexpr) + DumpExpression(expr->data.itc.catchexpr, indent + 1); + if (expr->data.itc.result) + DumpExpression(expr->data.itc.result, indent + 1); + return; + + case EDEFINE: + fprintf(outfile, "[%.8lX]", expr); + DumpType(expr->rtype); + fputs("\r", outfile); + expr = expr->data.monadic; + indent++; + break; + + case EREUSE: + fprintf(outfile, "[%.8lX]", expr->data.monadic); + DumpType(expr->rtype); + fputs("\r", outfile); + return; + + default: + return; + } + } +} + +void DumpSwitch(SwitchInfo *info) { + char buf[32]; + SwitchCase *cs; + + for (cs = info->cases; cs; cs = cs->next) { + CInt64_PrintDec(buf, cs->min); + CInt64_PrintDec(buf, cs->min); + fprintf(outfile, "\t\t%11s: %s\r", buf, cs->label->uniquename->name); + } + + fprintf(outfile, "\t\t default: %s\r", info->defaultlabel->uniquename->name); +} + +void DumpType(Type *type) { + char buf[256]; + + spell(type, buf); + fprintf(outfile, " (%s)", buf); +} + +static void spell(Type *type, char *buf) { + char mybuf[256]; + char mybuf2[256]; + + switch (type->type) { + case TYPEVOID: + strcpy(buf, "void"); + break; + case TYPEINT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + strcpy(buf, "bool"); + break; + case IT_CHAR: + strcpy(buf, "char"); + break; + case IT_WCHAR_T: + strcpy(buf, "wchar_t"); + break; + case IT_SCHAR: + strcpy(buf, "signed char"); + break; + case IT_UCHAR: + strcpy(buf, "unsigned char"); + break; + case IT_SHORT: + strcpy(buf, "short"); + break; + case IT_USHORT: + strcpy(buf, "unsigned short"); + break; + case IT_INT: + strcpy(buf, "int"); + break; + case IT_UINT: + strcpy(buf, "unsigned int"); + break; + case IT_LONG: + strcpy(buf, "long"); + break; + case IT_ULONG: + strcpy(buf, "unsigned long"); + break; + case IT_LONGLONG: + strcpy(buf, "long long"); + break; + case IT_ULONGLONG: + strcpy(buf, "unsigned long long"); + break; + } + break; + case TYPEFLOAT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_FLOAT: + strcpy(buf, "float"); + break; + case IT_SHORTDOUBLE: + strcpy(buf, "short double"); + break; + case IT_DOUBLE: + strcpy(buf, "double"); + break; + case IT_LONGDOUBLE: + strcpy(buf, "long double"); + break; + } + break; + case TYPEENUM: + strcpy(buf, "enum "); + if (TYPE_ENUM(type)->enumname) + strcat(buf, TYPE_ENUM(type)->enumname->name); + break; + case TYPESTRUCT: + if (IS_TYPESTRUCT_VECTOR(type)) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_4: + strcpy(buf, "vector unsigned char "); + break; + case STRUCT_TYPE_5: + strcpy(buf, "vector signed char "); + break; + case STRUCT_TYPE_6: + strcpy(buf, "vector bool char "); + break; + case STRUCT_TYPE_7: + strcpy(buf, "vector unsigned short "); + break; + case STRUCT_TYPE_8: + strcpy(buf, "vector signed short "); + break; + case STRUCT_TYPE_9: + strcpy(buf, "vector bool short "); + break; + case STRUCT_TYPE_A: + strcpy(buf, "vector unsigned int "); + break; + case STRUCT_TYPE_B: + strcpy(buf, "vector signed int "); + break; + case STRUCT_TYPE_C: + strcpy(buf, "vector bool int "); + break; + case STRUCT_TYPE_D: + strcpy(buf, "vector float "); + break; + case STRUCT_TYPE_E: + strcpy(buf, "vector pixel "); + break; + } + } else { + strcpy(buf, "struct "); + if (TYPE_STRUCT(type)->name) + strcat(buf, TYPE_STRUCT(type)->name->name); + } + break; + case TYPECLASS: + strcpy(buf, "class "); + if (TYPE_CLASS(type)->classname) + strcat(buf, TYPE_CLASS(type)->classname->name); + break; + case TYPEFUNC: + spell(TYPE_FUNC(type)->functype, mybuf); + strcpy(buf, "freturns("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEBITFIELD: + spell(TYPE_BITFIELD(type)->bitfieldtype, mybuf); + sprintf(buf, + "bitfield(%s){%d:%d}", + mybuf, + TYPE_BITFIELD(type)->unkA, + TYPE_BITFIELD(type)->unkB); + break; + case TYPELABEL: + strcpy(buf, "label"); + break; + case TYPEPOINTER: + spell(TPTR_TARGET(type), mybuf); + strcpy(buf, "pointer("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEARRAY: + spell(TPTR_TARGET(type), mybuf); + strcpy(buf, "array("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEMEMBERPOINTER: + spell(TYPE_MEMBER_POINTER(type)->ty2, mybuf); + spell(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); + strcpy(buf, "memberpointer("); + strcat(buf, mybuf); + strcat(buf, ","); + strcat(buf, mybuf2); + strcat(buf, ")"); + break; + } +} + +void DumpStack(ExceptionAction *act) { + while (act) { + fprintf(outfile, "\t\t:"); + switch (act->type) { + case EAT_DESTROYLOCAL: + fprintf(outfile, + "EAT_DESTROYLOCAL %s(&%s)%s", + CMangler_GetLinkName(act->data.destroy_local.dtor)->name, + act->data.destroy_local.local->name->name, + "\r"); + break; + case EAT_DESTROYLOCALCOND: + fprintf(outfile, + "EAT_DESTROYLOCALCOND%s", + "\r"); + break; + case EAT_DESTROYLOCALOFFSET: + fprintf(outfile, + "EAT_DESTROYLOCALOFFSET %s(&%s+%ld)%s", + CMangler_GetLinkName(act->data.destroy_local_offset.dtor)->name, + act->data.destroy_local_offset.local->name->name, + act->data.destroy_local_offset.offset, + "\r"); + break; + case EAT_DESTROYLOCALPOINTER: + fprintf(outfile, + "EAT_DESTROYLOCALPOINTER%s", + "\r"); + break; + case EAT_DESTROYLOCALARRAY: + fprintf(outfile, + "EAT_DESTROYLOCALARRAY%s", + "\r"); + break; + case EAT_DESTROYBASE: + fprintf(outfile, + "EAT_DESTROYBASE %s(this+%ld)%s", + CMangler_GetLinkName(act->data.destroy_base.dtor)->name, + act->data.destroy_base.offset, + "\r"); + break; + case EAT_DESTROYMEMBER: + fprintf(outfile, + "EAT_DESTROYMEMBER %s(%s+%ld)%s", + CMangler_GetLinkName(act->data.destroy_member.dtor)->name, + act->data.destroy_member.objectptr->name->name, + act->data.destroy_member.offset, + "\r"); + break; + case EAT_DESTROYMEMBERCOND: + fprintf(outfile, + "EAT_DESTROYMEMBERCOND if(%s) %s(this+%ld)%s", + act->data.destroy_member_cond.cond->name->name, + CMangler_GetLinkName(act->data.destroy_member_cond.dtor)->name, + act->data.destroy_member_cond.offset, + "\r"); + break; + case EAT_DESTROYMEMBERARRAY: + fprintf(outfile, + "EAT_DESTROYMEMBERARRAY %s(this+%ld)[%ld] size: %ld%s", + CMangler_GetLinkName(act->data.destroy_member_array.dtor)->name, + act->data.destroy_member_array.offset, + act->data.destroy_member_array.elements, + act->data.destroy_member_array.element_size, + "\r"); + break; + case EAT_DELETEPOINTER: + fprintf(outfile, + "EAT_DELETEPOINTER(%s)%s", + act->data.delete_pointer.pointerobject->name->name, + "\r"); + break; + case EAT_DELETELOCALPOINTER: + fprintf(outfile, + "EAT_DELETELOCALPOINTER(%s)%s", + act->data.delete_pointer.pointerobject->name->name, + "\r"); + break; + case EAT_DELETEPOINTERCOND: + fprintf(outfile, + "EAT_DELETEPOINTERCOND if (%s)(%s)%s", + act->data.delete_pointer_cond.cond->name->name, + act->data.delete_pointer_cond.pointerobject->name->name, + "\r"); + break; + case EAT_CATCHBLOCK: + fprintf(outfile, "EAT_CATCHBLOCK "); + if (act->data.catch_block.catch_type) { + if (act->data.catch_block.catch_object) + fprintf(outfile, "[%s]", act->data.catch_block.catch_object->name->name); + else + fprintf(outfile, "[]"); + DumpType(act->data.catch_block.catch_type); + } else { + fprintf(outfile, "[...] "); + } + fprintf(outfile, + " Label: %s%s", + act->data.catch_block.catch_label->uniquename->name, + "\r"); + break; + case EAT_SPECIFICATION: + fprintf(outfile, + "EAT_SPECIFICATION%s", + "\r"); + break; + case EAT_ACTIVECATCHBLOCK: + fprintf(outfile, + "EAT_ACTIVECATCHBLOCK%s", + "\r"); + break; + case EAT_TERMINATE: + fprintf(outfile, + "EAT_TERMINATE%s", + "\r"); + break; + } + act = act->prev; + } +} -- cgit v1.2.3