summaryrefslogtreecommitdiff
path: root/compiler_and_linker
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2022-12-29 12:32:55 +0000
committerAsh Wolf <ninji@wuffs.org>2022-12-29 12:32:55 +0000
commitfcfbafff31869ed808bff0639532db1828660e92 (patch)
tree7425b346b031c4cb47a06250b3f6f950374d44ae /compiler_and_linker
parentbc1321735c15104ffad195e1509cab5f3a044260 (diff)
downloadMWCC-fcfbafff31869ed808bff0639532db1828660e92.tar.gz
MWCC-fcfbafff31869ed808bff0639532db1828660e92.zip
dump lots more code
Diffstat (limited to 'compiler_and_linker')
-rw-r--r--compiler_and_linker/FrontEnd/Common/CompilerTools.c53
-rw-r--r--compiler_and_linker/unsorted/AddPropagation.c12
-rw-r--r--compiler_and_linker/unsorted/Alias.c30
-rw-r--r--compiler_and_linker/unsorted/CABI.c2
-rw-r--r--compiler_and_linker/unsorted/CBrowse.c737
-rw-r--r--compiler_and_linker/unsorted/CDecl.c8
-rw-r--r--compiler_and_linker/unsorted/CError.c39
-rw-r--r--compiler_and_linker/unsorted/CException.c2187
-rw-r--r--compiler_and_linker/unsorted/CExpr.c14
-rw-r--r--compiler_and_linker/unsorted/CExpr2.c6
-rw-r--r--compiler_and_linker/unsorted/CExprConvMatch.c1
-rw-r--r--compiler_and_linker/unsorted/CFunc.c2
-rw-r--r--compiler_and_linker/unsorted/CIRTransform.c534
-rw-r--r--compiler_and_linker/unsorted/CInit.c54
-rw-r--r--compiler_and_linker/unsorted/CInline.c4270
-rw-r--r--compiler_and_linker/unsorted/CMachine.c78
-rw-r--r--compiler_and_linker/unsorted/CMangler.c33
-rw-r--r--compiler_and_linker/unsorted/CObjC.c3102
-rw-r--r--compiler_and_linker/unsorted/CObjCModern.c181
-rw-r--r--compiler_and_linker/unsorted/COptimizer.c64
-rw-r--r--compiler_and_linker/unsorted/CPrec.c12
-rw-r--r--compiler_and_linker/unsorted/CPreprocess.c676
-rw-r--r--compiler_and_linker/unsorted/CRTTI.c940
-rw-r--r--compiler_and_linker/unsorted/CSOM.c2074
-rw-r--r--compiler_and_linker/unsorted/CTemplateClass.c1632
-rw-r--r--compiler_and_linker/unsorted/CTemplateFunc.c1383
-rw-r--r--compiler_and_linker/unsorted/CTemplateNew.c1881
-rw-r--r--compiler_and_linker/unsorted/CTemplateTools.c1962
-rw-r--r--compiler_and_linker/unsorted/CodeGen.c80
-rw-r--r--compiler_and_linker/unsorted/CodeMotion.c30
-rw-r--r--compiler_and_linker/unsorted/Exceptions.c857
-rw-r--r--compiler_and_linker/unsorted/FuncLevelAsmPPC.c385
-rw-r--r--compiler_and_linker/unsorted/FunctionCalls.c642
-rw-r--r--compiler_and_linker/unsorted/GenStabs.c1191
-rw-r--r--compiler_and_linker/unsorted/GlobalOptimizer.c224
-rw-r--r--compiler_and_linker/unsorted/IROUseDef.c54
-rw-r--r--compiler_and_linker/unsorted/InlineAsm.c3
-rw-r--r--compiler_and_linker/unsorted/InlineAsmPPC.c117
-rw-r--r--compiler_and_linker/unsorted/InterferenceGraph.c12
-rw-r--r--compiler_and_linker/unsorted/Intrinsics.c4894
-rw-r--r--compiler_and_linker/unsorted/IroBitVect.c8
-rw-r--r--compiler_and_linker/unsorted/IroCSE.c42
-rw-r--r--compiler_and_linker/unsorted/IroEmptyLoop.c21
-rw-r--r--compiler_and_linker/unsorted/IroFlowgraph.c3
-rw-r--r--compiler_and_linker/unsorted/IroLinearForm.c126
-rw-r--r--compiler_and_linker/unsorted/IroLoop.c33
-rw-r--r--compiler_and_linker/unsorted/IroPropagate.c10
-rw-r--r--compiler_and_linker/unsorted/IroRangePropagation.c6
-rw-r--r--compiler_and_linker/unsorted/IroUtil.c51
-rw-r--r--compiler_and_linker/unsorted/IroVars.c63
-rw-r--r--compiler_and_linker/unsorted/LoopDetection.c9
-rw-r--r--compiler_and_linker/unsorted/LoopOptimization.c39
-rw-r--r--compiler_and_linker/unsorted/MachO.c878
-rw-r--r--compiler_and_linker/unsorted/ObjGenMachO.c1810
-rw-r--r--compiler_and_linker/unsorted/Operands.c101
-rw-r--r--compiler_and_linker/unsorted/PCodeAssembly.c1603
-rw-r--r--compiler_and_linker/unsorted/PCodeInfo.c185
-rw-r--r--compiler_and_linker/unsorted/PCodeListing.c30
-rw-r--r--compiler_and_linker/unsorted/PCodeUtilities.c46
-rw-r--r--compiler_and_linker/unsorted/PPCError.c3
-rw-r--r--compiler_and_linker/unsorted/Peephole.c2753
-rw-r--r--compiler_and_linker/unsorted/RegisterInfo.c28
-rw-r--r--compiler_and_linker/unsorted/ScanFloat.c9
-rw-r--r--compiler_and_linker/unsorted/Scheduler.c3
-rw-r--r--compiler_and_linker/unsorted/SpillCode.c36
-rw-r--r--compiler_and_linker/unsorted/StackFrame.c91
-rw-r--r--compiler_and_linker/unsorted/StrengthReduction.c6
-rw-r--r--compiler_and_linker/unsorted/StructMoves.c792
-rw-r--r--compiler_and_linker/unsorted/Switch.c15
-rw-r--r--compiler_and_linker/unsorted/TOC.c48
-rw-r--r--compiler_and_linker/unsorted/Unmangle.c1022
-rw-r--r--compiler_and_linker/unsorted/ValueNumbering.c9
-rw-r--r--compiler_and_linker/unsorted/VectorArraysToRegs.c3
-rw-r--r--compiler_and_linker/unsorted/uDump.c639
74 files changed, 39819 insertions, 1158 deletions
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 = &copy->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(&param->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 = &params;
+
+ 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 = &param->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, &copy->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, &section->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(&section->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(&section->glist, 256);
+ return &section->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(&section->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;
+ }
+}