summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/unsorted')
-rw-r--r--compiler_and_linker/unsorted/AddPropagation.c271
-rw-r--r--compiler_and_linker/unsorted/Alias.c766
-rw-r--r--compiler_and_linker/unsorted/BitVectors.c122
-rw-r--r--compiler_and_linker/unsorted/COptimizer.c74
-rw-r--r--compiler_and_linker/unsorted/CodeMotion.c916
-rw-r--r--compiler_and_linker/unsorted/Coloring.c268
-rw-r--r--compiler_and_linker/unsorted/ConstantPropagation.c643
-rw-r--r--compiler_and_linker/unsorted/CopyPropagation.c474
-rw-r--r--compiler_and_linker/unsorted/IROUseDef.c1448
-rw-r--r--compiler_and_linker/unsorted/InlineAsmPPC.c4
-rw-r--r--compiler_and_linker/unsorted/InterferenceGraph.c404
-rw-r--r--compiler_and_linker/unsorted/IrOptimizer.c45
-rw-r--r--compiler_and_linker/unsorted/IroBitVect.c2
-rw-r--r--compiler_and_linker/unsorted/IroCSE.c1039
-rw-r--r--compiler_and_linker/unsorted/IroDump.c652
-rw-r--r--compiler_and_linker/unsorted/IroEmptyLoop.c567
-rw-r--r--compiler_and_linker/unsorted/IroExprRegeneration.c1531
-rw-r--r--compiler_and_linker/unsorted/IroFlowgraph.c336
-rw-r--r--compiler_and_linker/unsorted/IroJump.c267
-rw-r--r--compiler_and_linker/unsorted/IroLinearForm.c1831
-rw-r--r--compiler_and_linker/unsorted/IroLoop.c2335
-rw-r--r--compiler_and_linker/unsorted/IroMalloc.c564
-rw-r--r--compiler_and_linker/unsorted/IroPointerAnalysis.c5912
-rw-r--r--compiler_and_linker/unsorted/IroPointerAnalysisADTs.c2925
-rw-r--r--compiler_and_linker/unsorted/IroPropagate.c595
-rw-r--r--compiler_and_linker/unsorted/IroRangePropagation.c776
-rw-r--r--compiler_and_linker/unsorted/IroSubable.c160
-rw-r--r--compiler_and_linker/unsorted/IroTransform.c3
-rw-r--r--compiler_and_linker/unsorted/IroUnrollLoop.c95
-rw-r--r--compiler_and_linker/unsorted/IroUtil.c1250
-rw-r--r--compiler_and_linker/unsorted/IroVars.c1449
-rw-r--r--compiler_and_linker/unsorted/LiveInfo.c167
-rw-r--r--compiler_and_linker/unsorted/LoadDeletion.c46
-rw-r--r--compiler_and_linker/unsorted/LoopDetection.c889
-rw-r--r--compiler_and_linker/unsorted/LoopOptimization.c1565
-rw-r--r--compiler_and_linker/unsorted/PCode.c2
-rw-r--r--compiler_and_linker/unsorted/PCodeAssembly.c27
-rw-r--r--compiler_and_linker/unsorted/PCodeListing.c527
-rw-r--r--compiler_and_linker/unsorted/Scheduler.c548
-rw-r--r--compiler_and_linker/unsorted/SpillCode.c464
-rw-r--r--compiler_and_linker/unsorted/StrengthReduction.c752
-rw-r--r--compiler_and_linker/unsorted/Switch.c465
-rw-r--r--compiler_and_linker/unsorted/TOC.c1
-rw-r--r--compiler_and_linker/unsorted/UseDefChains.c563
-rw-r--r--compiler_and_linker/unsorted/ValueNumbering.c664
-rw-r--r--compiler_and_linker/unsorted/VectorArraysToRegs.c549
46 files changed, 34940 insertions, 13 deletions
diff --git a/compiler_and_linker/unsorted/AddPropagation.c b/compiler_and_linker/unsorted/AddPropagation.c
index e69de29..78b3393 100644
--- a/compiler_and_linker/unsorted/AddPropagation.c
+++ b/compiler_and_linker/unsorted/AddPropagation.c
@@ -0,0 +1,271 @@
+#include "compiler/AddPropagation.h"
+#include "compiler/Alias.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CopyPropagation.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/objects.h"
+
+int propagatedadds;
+
+static int is_add(PCode *instr) {
+ return
+ (
+ instr->op == PC_ADD ||
+ (
+ instr->op == PC_ADDI &&
+ (
+ instr->args[2].kind == PCOp_IMMEDIATE ||
+ (instr->args[2].kind == PCOp_MEMORY && (unsigned char) instr->args[2].arg == 1)
+ )
+ )
+ )
+ &&
+ instr->args[0].data.reg.reg >= n_real_registers[(char) instr->args[0].arg];
+}
+
+static int addpropagatestouse(int candidateID, int useID) {
+ int reg2;
+ PCode *candidateInstr;
+ PCode *useInstr;
+ int reg1;
+ int reg27;
+ Object *object;
+ SInt32 offset;
+ int i;
+ PCode *instr;
+ PCodeArg *op;
+
+ candidateInstr = Candidates[candidateID].pcode;
+ useInstr = Uses[useID].pcode;
+ reg1 = candidateInstr->args[0].data.reg.reg;
+ reg2 = candidateInstr->args[1].data.reg.reg;
+ reg27 = reg2;
+
+ if (!useInstr->block) {
+ recursive_propagation = 1;
+ return 0;
+ }
+
+ if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ if (PCODE_FLAG_SET_F(useInstr) & fPCodeFlag2000000)
+ return 0;
+ } else if (useInstr->op == PC_ADDI) {
+ if (useInstr->args[2].kind != PCOp_IMMEDIATE)
+ return 0;
+ } else if (useInstr->op != PC_MR) {
+ return 0;
+ }
+
+ if (candidateInstr->op == PC_ADD) {
+ if (useInstr->argCount < 3) {
+ if (useInstr->op != PC_MR)
+ return 0;
+ } else if (useInstr->args[2].kind == PCOp_IMMEDIATE) {
+ if (useInstr->args[2].data.imm.value != 0)
+ return 0;
+ } else if (useInstr->args[2].kind == PCOp_REGISTER) {
+ if (
+ useInstr->args[1].kind != PCOp_REGISTER ||
+ useInstr->args[2].data.reg.reg != reg1 ||
+ useInstr->args[1].data.reg.reg != 0
+ )
+ return 0;
+ } else {
+ return 0;
+ }
+
+ object = NULL;
+ offset = 0;
+ if (candidateInstr->alias && candidateInstr->alias->type == AliasType0) {
+ object = candidateInstr->alias->object;
+ offset = candidateInstr->alias->offset;
+ }
+ reg27 = candidateInstr->args[2].data.reg.reg;
+ } else if (candidateInstr->op == PC_ADDI) {
+ if (candidateInstr->alias && candidateInstr->alias->type == AliasType0) {
+ object = candidateInstr->alias->object;
+ offset = candidateInstr->alias->offset;
+ } else if (candidateInstr->args[2].kind == PCOp_MEMORY) {
+ object = candidateInstr->args[2].data.mem.obj;
+ offset = candidateInstr->args[2].data.mem.offset;
+ } else if (candidateInstr->args[2].kind == PCOp_IMMEDIATE) {
+ object = NULL;
+ offset = candidateInstr->args[2].data.imm.value;
+ } else {
+ return 0;
+ }
+
+ if (useInstr->argCount < 3) {
+ if (useInstr->op != PC_MR)
+ return 0;
+ } else if (useInstr->args[2].kind == PCOp_IMMEDIATE) {
+ offset += useInstr->args[2].data.imm.value;
+ if (object) {
+ if (object->datatype == DLOCAL) {
+ if (!can_add_displ_to_local(object, offset))
+ return 0;
+ } else {
+ return 0;
+ }
+ } else if (!FITS_IN_SHORT(offset)) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+#line 225
+ CError_FATAL();
+ return 0;
+ }
+
+ if (
+ (useInstr->flags & fPCodeFlag4) &&
+ useInstr->args[0].kind == PCOp_REGISTER &&
+ useInstr->args[0].arg == RegClass_GPR &&
+ useInstr->args[0].data.reg.reg == reg1
+ )
+ return 0;
+
+ if (useInstr->args[1].data.reg.reg != reg1)
+ return 0;
+
+ if (candidateInstr->block == useInstr->block && precedes(candidateInstr, useInstr)) {
+ for (instr = candidateInstr->nextPCode; instr && instr != useInstr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ (op->data.reg.reg == reg2 || op->data.reg.reg == reg27)
+ )
+ return 0;
+ op++;
+ }
+ }
+ } else {
+ if (!bitvectorgetbit(candidateID, propinfo[useInstr->block->blockIndex].vec8))
+ return 0;
+
+ for (instr = useInstr->block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr == useInstr)
+ break;
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ (op->data.reg.reg == reg2 || op->data.reg.reg == reg27)
+ )
+ return 0;
+ op++;
+ }
+ }
+ }
+
+ if ((useInstr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) && object)
+ useInstr->alias = make_alias(object, offset, nbytes_loaded_or_stored_by(useInstr));
+
+ return 1;
+}
+
+static void propagateandremoveadd(int id) {
+ PCode *instr;
+ RegUseOrDef *list;
+ Candidate *candidate;
+ PCode *useInstr;
+
+ candidate = Candidates + id;
+ instr = candidate->pcode;
+
+ if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_MEMORY)
+ instr->alias = make_alias(instr->args[2].data.mem.obj, instr->args[2].data.mem.offset, 1);
+
+ for (list = candidate->list; list; list = list->next) {
+ useInstr = Uses[list->id].pcode;
+
+ if (instr->op == PC_ADD) {
+ if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ if (useInstr->args[2].kind != PCOp_REGISTER) {
+ useInstr->op += 2;
+ useInstr->flags |= fPCodeFlag20;
+ }
+ useInstr->args[1] = instr->args[1];
+ 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);
+ change_opcode(useInstr, PC_ADD);
+ useInstr->args[1] = instr->args[1];
+ useInstr->args[2] = instr->args[2];
+ useInstr->alias = instr->alias;
+ } else if (useInstr->op == PC_MR) {
+ change_opcode(useInstr, PC_ADD);
+ useInstr->flags = instr->flags;
+ change_num_operands(useInstr, 3);
+ useInstr->args[1] = instr->args[1];
+ useInstr->args[2] = instr->args[2];
+ useInstr->alias = instr->alias;
+ } else {
+#line 352
+ CError_FATAL();
+ }
+ } else if (useInstr->op == PC_MR) {
+ change_opcode(useInstr, PC_ADDI);
+ useInstr->flags = instr->flags;
+ useInstr->alias = instr->alias;
+ change_num_operands(useInstr, 3);
+ useInstr->args[1] = instr->args[1];
+ useInstr->args[2] = instr->args[2];
+ } else {
+ useInstr->args[1] = instr->args[1];
+ if (instr->args[2].kind == PCOp_IMMEDIATE) {
+ SInt32 newValue = useInstr->args[2].data.imm.value + instr->args[2].data.imm.value;
+ useInstr->args[2] = instr->args[2];
+ useInstr->args[2].data.imm.value = newValue;
+ useInstr->flags |= fPCodeFlag20;
+ } else if (instr->args[2].kind == PCOp_MEMORY) {
+ SInt32 newValue = useInstr->args[2].data.imm.value + instr->args[2].data.mem.offset;
+ useInstr->args[2] = instr->args[2];
+ useInstr->args[2].data.mem.offset = newValue;
+ useInstr->flags &= ~fPCodeFlag20;
+ if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000))
+ useInstr->alias = make_alias(
+ useInstr->args[2].data.mem.obj,
+ useInstr->args[2].data.mem.offset,
+ nbytes_loaded_or_stored_by(useInstr));
+ } else {
+#line 382
+ CError_FATAL();
+ }
+ }
+ }
+
+ deletepcode(instr);
+ propagatedadds = 1;
+}
+
+static Propagation add_prop = {
+ &is_add,
+ &addpropagatestouse,
+ &propagateandremoveadd,
+ "ADD",
+ "ADDS",
+ "a%ld",
+ 0
+};
+
+void propagateaddinstructions(Object *proc) {
+ propagateinstructions(proc, &add_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1);
+ propagatedadds = propagated_instructions;
+}
diff --git a/compiler_and_linker/unsorted/Alias.c b/compiler_and_linker/unsorted/Alias.c
index e69de29..4c0f064 100644
--- a/compiler_and_linker/unsorted/Alias.c
+++ b/compiler_and_linker/unsorted/Alias.c
@@ -0,0 +1,766 @@
+#include "compiler/Alias.h"
+#include "compiler/CClass.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/CMachine.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CopyPropagation.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/ValueNumbering.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+static Alias *aliases;
+static int n_aliases;
+static int n_gathered_aliases;
+static Alias *alias_hash[997];
+Alias *worst_case;
+Object worst_case_obj;
+
+static TypePointer worst_case_memory_type = {
+ TYPEARRAY,
+ 0xFFFFFF,
+ TYPE(&stchar)
+};
+
+static Boolean is_safe_const(Object *obj) {
+ Type *type;
+
+ type = obj->type;
+ while (IS_TYPE_ARRAY(type))
+ type = TPTR_TARGET(type);
+
+ if (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_VECTOR(type) || IS_TYPE_FLOAT(type) || IS_TYPE_STRUCT(type))
+ return is_const_object(obj);
+
+ if (IS_TYPE_CLASS(type))
+ return is_const_object(obj) && CClass_IsPODClass(TYPE_CLASS(type));
+
+ return 0;
+}
+
+void initialize_aliases(void) {
+ int i;
+
+ memclrw(&worst_case_obj, sizeof(Object));
+ worst_case_obj.otype = OT_OBJECT;
+ worst_case_obj.type = TYPE(&worst_case_memory_type);
+ worst_case_obj.datatype = DDATA;
+ worst_case_obj.name = GetHashNameNodeExport("@worst_case@");
+
+ aliases = NULL;
+ n_aliases = 0;
+ n_gathered_aliases = 0;
+ for (i = 0; i < 997; i++)
+ alias_hash[i] = NULL;
+
+ worst_case = make_alias_set();
+ add_alias_member(worst_case, make_alias(&worst_case_obj, 0, 0));
+}
+
+static UInt32 hash_alias(Object *object, SInt32 offset, SInt32 size) {
+ return (UInt32) (object->name->hashval * offset * size) % 997;
+}
+
+static Alias *create_alias(AliasType type, Object *object, SInt32 offset, SInt32 size, Boolean addToHash) {
+ Alias *alias;
+ UInt32 hash;
+
+ alias = lalloc(sizeof(Alias));
+ memclrw(alias, sizeof(Alias));
+ alias->type = type;
+ alias->index = n_aliases++;
+ alias->next = aliases;
+ aliases = alias;
+ alias->object = object;
+ alias->offset = offset;
+ alias->size = size;
+
+ if (addToHash) {
+ hash = hash_alias(object, offset, size);
+ alias->hashNext = alias_hash[hash];
+ alias_hash[hash] = alias;
+ }
+
+ return alias;
+}
+
+static Alias *lookup_alias(Object *object, SInt32 offset, SInt32 size) {
+ Alias *scan;
+
+ for (scan = alias_hash[hash_alias(object, offset, size)]; scan; scan = scan->hashNext) {
+ if (scan->object == object && scan->offset == offset && scan->size == size)
+ return scan;
+ }
+
+ return NULL;
+}
+
+Alias *make_alias(Object *object, SInt32 offset, SInt32 size) {
+ Alias *alias;
+ Alias *alias2;
+
+ if (!offset && !size)
+ size = object->type->size;
+
+ alias = lookup_alias(object, offset, size);
+ if (!alias) {
+ if (offset > 0 || size != object->type->size) {
+ alias2 = make_alias(object, 0, object->type->size);
+ alias = create_alias(AliasType1, object, offset, size, 1);
+ add_alias_member(alias2, alias);
+ } else {
+ alias = create_alias(AliasType0, object, offset, size, 1);
+ }
+
+ switch (object->datatype) {
+ case DLOCAL:
+ case DNONLAZYPTR:
+ break;
+ default:
+ if (!is_safe_const(object))
+ add_alias_member(worst_case, make_alias(object, 0, 0));
+ }
+ }
+
+ if (offset > object->type->size)
+ return NULL;
+ else
+ return alias;
+}
+
+Alias *make_alias_set(void) {
+ return create_alias(AliasType2, NULL, 0, 0, 0);
+}
+
+void add_alias_member(Alias *parent, Alias *child) {
+ AliasMember *member;
+
+ if (child->type == AliasType2) {
+ for (member = child->parents; member; member = member->nextParent)
+ add_alias_member(parent, member->child);
+ } else {
+ if (parent == worst_case && child->type == AliasType1)
+ child = make_alias(child->object, 0, 0);
+
+ for (member = parent->parents; member; member = member->nextParent) {
+ if (member->child == child)
+ return;
+ }
+
+ member = lalloc(sizeof(AliasMember));
+ member->parent = parent;
+ member->child = child;
+ member->nextParent = parent->parents;
+ parent->parents = member;
+ member->nextChild = child->children;
+ child->children = member;
+ }
+}
+
+Alias *make_alias_set_from_IR(void) {
+#line 333
+ CError_FATAL();
+ return NULL;
+}
+
+static Boolean aliases_overlap(Alias *a, Alias *b) {
+ return (
+ a->offset == b->offset ||
+ (a->offset > b->offset && a->offset < (b->offset + b->size)) ||
+ (b->offset > a->offset && b->offset < (a->offset + a->size))
+ );
+}
+
+static int is_address_load(PCode *pcode) {
+ Object *obj;
+
+ switch (pcode->op) {
+ case PC_LWZ:
+ if (pcode->args[2].kind == PCOp_MEMORY && pcode->args[2].data.mem.obj->datatype == DNONLAZYPTR)
+ return 1;
+ break;
+ case PC_LBZU:
+ case PC_LBZUX:
+ case PC_LHZU:
+ case PC_LHZUX:
+ case PC_LHAU:
+ case PC_LHAUX:
+ case PC_LWZU:
+ case PC_LWZUX:
+ case PC_STBU:
+ case PC_STBUX:
+ case PC_STHU:
+ case PC_STHUX:
+ case PC_STWU:
+ case PC_STWUX:
+ return 1;
+ case PC_ADDI:
+ case PC_ADDIS:
+ if (pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) {
+ if (pcode->args[2].kind == PCOp_MEMORY) {
+ obj = pcode->args[2].data.mem.obj;
+ if (obj->datatype == DLOCAL && !is_safe_const(obj))
+ add_alias_member(worst_case, make_alias(obj, 0, 0));
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ break;
+ case PC_ADD:
+ return 1;
+ }
+
+ return 0;
+}
+
+static int addresspropagatestouse(int candidateID, int useID) {
+ PCode *candidate_pcode; // r30
+ PCode *use_pcode; // r29
+ int reg; // r28
+ short reg2;
+ Object *object; // r27
+ SInt32 offset; // r26
+ Alias *alias; // r25
+ Boolean flag24; // r24
+ SInt32 size; // r23
+ Alias *aliasSet; // r22
+ int i;
+ PCode *scan;
+ PCodeArg *op;
+
+ candidate_pcode = Candidates[candidateID].pcode;
+ use_pcode = Uses[useID].pcode;
+ flag24 = 0;
+ size = 1;
+ reg = candidate_pcode->args[0].data.reg.reg;
+
+ if (candidate_pcode->alias && (candidate_pcode->alias->type == AliasType0 || candidate_pcode->alias->type == AliasType1)) {
+ object = candidate_pcode->alias->object;
+ offset = candidate_pcode->alias->offset;
+ if (offset == 0 && candidate_pcode->alias->size == object->type->size)
+ flag24 = 1;
+ } else if (candidate_pcode->args[2].kind == PCOp_MEMORY) {
+ object = candidate_pcode->args[2].data.mem.obj;
+ if (candidate_pcode->op == PC_ADDIS)
+ offset = candidate_pcode->args[2].data.mem.offset << 16;
+ else
+ offset = candidate_pcode->args[2].data.mem.offset;
+ } else {
+ return 0;
+ }
+
+#line 478
+ CError_ASSERT(object->otype == OT_OBJECT);
+
+ if ((candidate_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (candidate_pcode->flags & fPCodeFlag2000000)) {
+ reg = candidate_pcode->args[1].data.reg.reg;
+ offset = 0;
+ flag24 = 1;
+ } else if (candidate_pcode->op == PC_LWZ) {
+ if (object->datatype != DNONLAZYPTR)
+ return 0;
+
+ object = object->u.var.realObj;
+#line 495
+ CError_ASSERT(object->otype == OT_OBJECT);
+ offset = 0;
+ } else if (candidate_pcode->op == PC_ADDI) {
+ if (!candidate_pcode->alias && object)
+ candidate_pcode->alias = make_alias(object, offset, 1);
+ } else if (candidate_pcode->op == PC_ADDIS) {
+ if (!candidate_pcode->alias && object)
+ candidate_pcode->alias = make_alias(object, offset, 1);
+ } else if (candidate_pcode->op == PC_ADD) {
+ offset = 0;
+ flag24 = 1;
+ } else {
+#line 509
+ CError_FATAL();
+ }
+
+ if (
+ !(use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) &&
+ use_pcode->op != PC_ADDI &&
+ use_pcode->op != PC_ADD &&
+ use_pcode->op != PC_ADDIS
+ ) {
+ if (object->datatype == DLOCAL && !is_safe_const(object))
+ add_alias_member(worst_case, make_alias(object, 0, 0));
+ return 1;
+ }
+
+ if (
+ (use_pcode->flags & (fPCodeFlag4 | fPCodeFlag40000)) &&
+ use_pcode->args[0].kind == PCOp_REGISTER &&
+ use_pcode->args[0].arg == RegClass_GPR &&
+ use_pcode->args[0].data.reg.reg == reg &&
+ object->datatype == DLOCAL &&
+ !is_safe_const(object)
+ )
+ add_alias_member(worst_case, make_alias(object, 0, 0));
+
+ if (use_pcode->argCount < 3)
+ return 1;
+
+#line 543
+ CError_ASSERT(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) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg)
+ return 1;
+ op++;
+ }
+ }
+ } else {
+ if (!bitvectorgetbit(candidateID, propinfo[use_pcode->block->blockIndex].vec8)) {
+ if (bitvectorgetbit(candidate_pcode->defID, usedefinfo[use_pcode->block->blockIndex].defvec8)) {
+ for (scan = use_pcode->block->firstPCode; scan && scan != use_pcode; scan = scan->nextPCode) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg)
+ return 1;
+ op++;
+ }
+ }
+ } else {
+ return 1;
+ }
+ }
+
+ for (scan = use_pcode->block->firstPCode; scan; scan = scan->nextPCode) {
+ if (scan == use_pcode)
+ break;
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg)
+ return 1;
+ op++;
+ }
+ }
+ }
+
+#line 598
+ CError_ASSERT(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))
+ add_alias_member(worst_case, make_alias(object, 0, 0));
+ }
+
+ if (use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4))
+ size = nbytes_loaded_or_stored_by(use_pcode);
+
+ if (use_pcode->args[2].kind == PCOp_REGISTER) {
+ if (use_pcode->args[1].data.reg.reg == 0) {
+ if (use_pcode->args[2].data.reg.reg == reg)
+ alias = make_alias(object, offset, size);
+ } else {
+ if (use_pcode->args[1].data.reg.reg == reg)
+ reg2 = use_pcode->args[2].data.reg.reg;
+ else if (use_pcode->args[2].data.reg.reg == reg)
+ reg2 = use_pcode->args[1].data.reg.reg;
+ else
+ return 1;
+
+ for (scan = use_pcode->prevPCode; scan; scan = scan->prevPCode) {
+ if (scan->op == PC_LI && scan->args[0].data.reg.reg == reg2)
+ break;
+
+ for (i = 0; i < scan->argCount; i++) {
+ if (scan->args[i].kind == PCOp_REGISTER &&
+ scan->args[i].arg == RegClass_GPR &&
+ scan->args[i].data.reg.reg == reg2 &&
+ (scan->args[i].data.reg.effect & EffectWrite)) {
+ scan = NULL;
+ break;
+ }
+ }
+
+ if (!scan)
+ break;
+ }
+
+ if (scan) {
+ offset += scan->args[1].data.mem.offset;
+ alias = make_alias(object, offset, size);
+ } else {
+ alias = make_alias(object, 0, 0);
+ }
+ }
+ } else {
+ if (use_pcode->args[1].kind != PCOp_REGISTER ||
+ use_pcode->args[1].arg != RegClass_GPR ||
+ use_pcode->args[1].data.reg.reg != reg)
+ return 1;
+
+ if (use_pcode->args[1].data.reg.effect & EffectWrite) {
+ alias = make_alias(object, 0, 0);
+ } else if (use_pcode->args[2].kind == PCOp_IMMEDIATE) {
+ if (use_pcode->op == PC_ADDIS) {
+ offset += use_pcode->args[2].data.imm.value << 16;
+ alias = make_alias(object, offset, 1);
+ } else {
+ offset += use_pcode->args[2].data.imm.value;
+ alias = make_alias(object, offset, size);
+ }
+ } else {
+ return 1;
+ }
+ }
+
+ if (flag24)
+ alias = make_alias(object, 0, 0);
+
+ if (!alias)
+ return 1;
+
+ if (!use_pcode->alias) {
+ if (
+ use_pcode->op == PC_ADDI ||
+ use_pcode->op == PC_ADD ||
+ use_pcode->op == PC_ADDIS ||
+ ((candidate_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (candidate_pcode->flags & fPCodeFlag2000000))
+ )
+ recursive_propagation = 1;
+ }
+
+ if (use_pcode->alias) {
+ if (use_pcode->alias == worst_case) {
+ add_alias_member(worst_case, make_alias(object, 0, 0));
+ } else if (use_pcode->alias == alias) {
+ return 1;
+ } else if (use_pcode->alias->type == AliasType0 || use_pcode->alias->type == AliasType1) {
+ if (object == use_pcode->alias->object) {
+ use_pcode->alias = make_alias(object, 0, 0);
+ } else {
+ aliasSet = make_alias_set();
+ if (
+ use_pcode->op == PC_ADDI ||
+ use_pcode->op == PC_ADD ||
+ use_pcode->op == PC_ADDIS ||
+ ((use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (use_pcode->flags & fPCodeFlag2000000))
+ ) {
+ if (alias->type == AliasType2)
+ add_alias_member(worst_case, alias);
+ else
+ add_alias_member(worst_case, make_alias(use_pcode->alias->object, 0, 0));
+ }
+ add_alias_member(aliasSet, use_pcode->alias);
+ add_alias_member(aliasSet, alias);
+ use_pcode->alias = aliasSet;
+ }
+ } else {
+ add_alias_member(use_pcode->alias, alias);
+ }
+ } else {
+ use_pcode->alias = alias;
+ }
+
+ propagated_instructions = 1;
+ return 1;
+}
+
+static void finishpropagatealiases(int id) {
+ propagated_instructions = 1;
+}
+
+static Propagation alias_prop = {
+ &is_address_load,
+ &addresspropagatestouse,
+ &finishpropagatealiases,
+ "ALIAS",
+ "ALIASES",
+ "A%ld",
+ 1
+};
+
+static void propagatealiasinfo(Object *proc) {
+ propagateinstructions(proc, &alias_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1);
+}
+
+void gather_alias_info(void) {
+ UInt32 *myvec; // r31
+ Alias *alias; // r22
+ AliasMember *member;
+ AliasMember *member2;
+ PCodeBlock *block; // r21
+ PCode *pcode; // r20
+ PCodeArg *op; // r19
+ RegUseOrDef *list; // r18
+ int i; // r17
+ Alias *alias_choice; // r16
+ int aliases_idx; // r15 (helper in r23)
+ PCode *defpcode; // r14
+ Alias *alias_array[3];
+ UseOrDef *def;
+ int defID;
+
+ if (coloring) {
+ propagatealiasinfo(gFunction);
+ myvec = oalloc(4 * ((number_of_Defs + 31) >> 5));
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs);
+
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) {
+ if (!pcode->alias) {
+ pcode->alias = worst_case;
+ } else {
+ if ((pcode->alias->type == AliasType0 || pcode->alias->type == AliasType1) &&
+ pcode->alias->size == nbytes_loaded_or_stored_by(pcode)) {
+ pcode->flags &= ~fPCodeFlag20;
+ } else {
+ pcode->flags |= fPCodeFlag20;
+ }
+
+ if (pcode->alias != worst_case) {
+ aliases_idx = 0;
+ alias_choice = NULL;
+ op = pcode->args;
+ for (i = 0; i < pcode->argCount; i++, op++) {
+ if (
+ (!(pcode->flags & (fPCodeFlag4 | fPCodeFlag40000)) || op != pcode->args) &&
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectRead)
+ ) {
+ alias_array[aliases_idx] = NULL;
+ if (aliases_idx >= 2) {
+ alias_choice = worst_case;
+ break;
+ }
+ alias_array[aliases_idx] = pcode->alias;
+
+ for (list = reg_Defs[RegClass_GPR][op->data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, myvec)) {
+ defpcode = Defs[list->id].pcode;
+ if (!defpcode->alias || !is_address_load(defpcode) || defpcode->alias == worst_case) {
+ alias_array[aliases_idx] = worst_case;
+ break;
+ }
+ }
+ }
+
+ aliases_idx++;
+ }
+ }
+
+ if (!alias_choice) {
+ if (aliases_idx > 0) {
+ alias_choice = alias_array[0];
+ if (aliases_idx == 2) {
+ if (alias_array[0] != worst_case) {
+ if (alias_array[1] != worst_case)
+ alias_choice = worst_case;
+ } else if (alias_array[1] != worst_case) {
+ alias_choice = alias_array[1];
+ }
+ }
+ }
+
+ if (alias_choice == worst_case) {
+ pcode->flags |= fPCodeFlag20;
+ if (pcode->alias->type == AliasType2)
+ add_alias_member(worst_case, pcode->alias);
+ else
+ add_alias_member(worst_case, make_alias(pcode->alias->object, 0, 0));
+ }
+
+ if (alias_choice)
+ pcode->alias = alias_choice;
+ }
+ }
+ }
+ } else {
+ if ((pcode->flags & fPCodeFlag8) && !pcode->alias)
+ pcode->alias = worst_case;
+ }
+
+ for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; defID++, def++) {
+ if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) {
+ for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next)
+ bitvectorclearbit(list->id, myvec);
+ }
+ bitvectorsetbit(defID, myvec);
+ }
+ }
+ }
+
+ freeoheap();
+ } else {
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if ((pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag8 | fPCodeFlag20000 | fPCodeFlag40000)) && !pcode->alias)
+ pcode->alias = worst_case;
+ }
+ }
+ }
+
+ if (n_gathered_aliases != n_aliases) {
+ for (alias = aliases; alias; alias = alias->next) {
+ if (alias->type == AliasType2) {
+ alias->vec24 = lalloc(4 * ((n_aliases + 31) >> 35));
+ bitvectorinitialize(alias->vec24, n_aliases, 0);
+ for (member = alias->parents; member; member = member->nextParent) {
+ bitvectorsetbit(member->child->index, alias->vec24);
+ for (member2 = member->child->parents; member2; member2 = member2->nextParent)
+ bitvectorsetbit(member2->child->index, alias->vec24);
+ }
+ }
+ }
+ n_gathered_aliases = n_aliases;
+ }
+}
+
+static Boolean may_alias_alias(Alias *a, Alias *b) {
+ switch ((a->type * 3) + b->type) {
+ case (AliasType0 * 3) + AliasType0:
+ return a == b;
+ case (AliasType0 * 3) + AliasType1:
+ case (AliasType1 * 3) + AliasType0:
+ return a->object == b->object;
+ case (AliasType1 * 3) + AliasType1:
+ return (a->object == b->object) && aliases_overlap(a, b);
+ case (AliasType0 * 3) + AliasType2:
+ case (AliasType1 * 3) + AliasType2:
+ return bitvectorgetbit(a->index, b->vec24) != 0;
+ case (AliasType2 * 3) + AliasType0:
+ case (AliasType2 * 3) + AliasType1:
+ return bitvectorgetbit(b->index, a->vec24) != 0;
+ case (AliasType2 * 3) + AliasType2:
+ return (a == b) || !bitvectorintersectionisempty(a->vec24, b->vec24, n_aliases);
+ default:
+#line 1054
+ CError_FATAL();
+ return 1;
+ }
+}
+
+Boolean may_alias(PCode *a, PCode *b) {
+ return may_alias_alias(a->alias, b->alias);
+}
+
+Boolean uniquely_aliases(PCode *a, PCode *b) {
+ if (may_alias_alias(a->alias, b->alias)) {
+ if (
+ a->alias->type != AliasType2 &&
+ b->alias->type != AliasType2 &&
+ a->alias &&
+ b->alias &&
+ a->alias->size == nbytes_loaded_or_stored_by(a) &&
+ b->alias->size == nbytes_loaded_or_stored_by(b)
+ )
+ return 1;
+ }
+
+ return 0;
+}
+
+Boolean may_alias_worst_case(PCode *pcode) {
+ return may_alias_alias(pcode->alias, worst_case);
+}
+
+Boolean may_alias_object(PCode *pcode, Object *object) {
+ return may_alias_alias(pcode->alias, make_alias(object, 0, 0));
+}
+
+void initialize_alias_values(void) {
+ Alias *alias;
+
+ for (alias = aliases; alias; alias = alias->next) {
+ alias->valuenumber = nextvaluenumber++;
+ alias->valuepcode = NULL;
+ }
+}
+
+void update_alias_value(Alias *alias, PCode *pcode) {
+ AliasMember *member;
+ AliasMember *member2;
+ AliasMember *member3;
+
+ switch (alias->type) {
+ case AliasType0:
+ killmemory(alias, pcode);
+ for (member = alias->children; member; member = member->nextChild) {
+#line 1152
+ CError_ASSERT(member->parent->type == AliasType2);
+ killmemory(member->parent, NULL);
+ }
+ for (member = alias->parents; member; member = member->nextParent) {
+#line 1157
+ CError_ASSERT(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);
+ killmemory(member2->parent, NULL);
+ }
+ }
+ }
+ break;
+
+ case AliasType1:
+ killmemory(alias, pcode);
+ for (member = alias->children; member; member = member->nextChild) {
+ killmemory(member->parent, NULL);
+ if (member->parent->type == AliasType0) {
+ for (member2 = member->parent->parents; member2; member2 = member2->nextParent) {
+ if (member2->child != alias && aliases_overlap(alias, member2->child)) {
+ killmemory(member2->child, NULL);
+ }
+ }
+ }
+ }
+ break;
+
+ case AliasType2:
+ killmemory(alias, NULL);
+ for (member = alias->parents; member; member = member->nextParent) {
+ killmemory(member->child, NULL);
+ for (member2 = member->child->children; member2; member2 = member2->nextChild) {
+ if (member2->parent != alias)
+ killmemory(member2->parent, NULL);
+ }
+ for (member3 = member->child->parents; member3; member3 = member3->nextParent) {
+ killmemory(member3->child, NULL);
+ for (member2 = member3->child->children; member2; member2 = member2->nextChild) {
+ if (member2->parent != member->child)
+ killmemory(member2->parent, NULL);
+ }
+ }
+ }
+ break;
+ }
+}
+
+void update_all_alias_values(void) {
+ Alias *alias;
+
+ for (alias = aliases; alias; alias = alias->next)
+ killmemory(alias, NULL);
+}
+
diff --git a/compiler_and_linker/unsorted/BitVectors.c b/compiler_and_linker/unsorted/BitVectors.c
index e69de29..3a928fd 100644
--- a/compiler_and_linker/unsorted/BitVectors.c
+++ b/compiler_and_linker/unsorted/BitVectors.c
@@ -0,0 +1,122 @@
+#include "compiler/BitVectors.h"
+
+void bitvectorcopy(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(dst++) = *(src++);
+}
+
+int bitvectorchanged(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+ int flag = 0;
+ UInt32 v;
+
+ while (i--) {
+ v = *src;
+ if (*dst != v)
+ flag = 1;
+ *dst = v;
+ dst++;
+ src++;
+ }
+
+ return flag;
+}
+
+void bitvectorinitialize(UInt32 *vec, int len, UInt32 initval) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(vec++) = initval;
+}
+
+void bitvectorintersect(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(dst++) &= *(src++);
+}
+
+void bitvectorunion(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(dst++) |= *(src++);
+}
+
+void bitvectordifference(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(dst++) &= ~*(src++);
+}
+
+void bitvectorcomplement(UInt32 *dst, UInt32 *src, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--)
+ *(dst++) = ~*(src++);
+}
+
+int bitvectorcount(UInt32 *vec, int len) {
+ static unsigned char nbits[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+ };
+
+ UInt32 v;
+ int i = (len + 31) >> 5;
+ int total = 0;
+
+ while (i--) {
+ if ((v = *vec)) {
+ total += nbits[v & 0xFF];
+ total += nbits[(v >> 8) & 0xFF];
+ total += nbits[(v >> 16) & 0xFF];
+ total += nbits[(v >> 24) & 0xFF];
+ }
+ vec++;
+ }
+
+ return total;
+}
+
+int bitvectorisempty(UInt32 *vec, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--) {
+ if (*vec)
+ return 0;
+ vec++;
+ }
+
+ return 1;
+}
+
+int bitvectorintersectionisempty(UInt32 *a, UInt32 *b, int len) {
+ int i = (len + 31) >> 5;
+
+ while (i--) {
+ if (*a & *b)
+ return 0;
+ a++;
+ b++;
+ }
+
+ return 1;
+}
diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c
index 38b203f..b7637c8 100644
--- a/compiler_and_linker/unsorted/COptimizer.c
+++ b/compiler_and_linker/unsorted/COptimizer.c
@@ -904,6 +904,8 @@ static COptBlock *newblock(void) {
block->set1[i] = 0;
block->set2[i] = 0;
}
+
+ return block;
}
static void MarkFollow(COptBlock *block) {
@@ -1369,6 +1371,8 @@ static CLabel *finallabel(CLabel *label, Statement *stmt) {
return label;
}
}
+
+ return label;
}
static void optimizegoto(Statement *stmt) {
@@ -1399,6 +1403,76 @@ static void removeif(Statement *stmt, Boolean flag) {
}
static void optimizeif(Statement *stmt) {
+ Statement *scan;
+ Statement *scan2;
+ Boolean flag;
+
+ if (iszero(stmt->expr)) {
+ removeif(stmt, 0);
+ return;
+ }
+ if (isnotzero(stmt->expr)) {
+ removeif(stmt, 1);
+ return;
+ }
+
+ for (scan = stmt->next, flag = 0; scan; scan = scan->next) {
+ if (scan->type > ST_LABEL) {
+ if (scan->type == ST_GOTO) {
+ if (scan->label == stmt->label) {
+ stmt->type = ST_EXPRESSION;
+ stmtchanged = 1;
+ return;
+ }
+
+ if (!flag) {
+ for (scan2 = scan->next; scan2; scan2 = scan2->next) {
+ if (scan2->type > ST_LABEL)
+ break;
+ if (stmt->label->stmt == scan2) {
+ stmt->label = scan->label;
+ scan->type = ST_NOP;
+ if (stmt->type == ST_IFGOTO)
+ stmt->type = ST_IFNGOTO;
+ else
+ stmt->type = ST_IFGOTO;
+ stmtchanged = 1;
+ stmt->label = finallabel(stmt->label, stmt);
+ return;
+ }
+ }
+ }
+ } else if (scan->type == ST_RETURN && !scan->expr && !static_for_inlines && !flag) {
+ for (scan2 = scan->next; scan2; scan2 = scan2->next) {
+ if (scan2->type > ST_LABEL)
+ break;
+ if (stmt->label->stmt == scan2) {
+ stmt->label = cleanreturnlabel;
+ needs_cleanup = 1;
+ scan->type = ST_NOP;
+ if (stmt->type == ST_IFGOTO)
+ stmt->type = ST_IFNGOTO;
+ else
+ stmt->type = ST_IFGOTO;
+ stmtchanged = 1;
+ return;
+ }
+ }
+ }
+ break;
+ }
+
+ if (scan->type == ST_LABEL)
+ flag = 1;
+
+ if (stmt->label->stmt == scan) {
+ stmt->type = ST_EXPRESSION;
+ stmtchanged = 1;
+ return;
+ }
+ }
+
+ stmt->label = finallabel(stmt->label, stmt);
}
static void optimizeswitch(Statement *stmt) {
diff --git a/compiler_and_linker/unsorted/CodeMotion.c b/compiler_and_linker/unsorted/CodeMotion.c
index e69de29..539748e 100644
--- a/compiler_and_linker/unsorted/CodeMotion.c
+++ b/compiler_and_linker/unsorted/CodeMotion.c
@@ -0,0 +1,916 @@
+#include "compiler/CodeMotion.h"
+#include "compiler/Alias.h"
+#include "compiler/BitVectors.h"
+#include "compiler/LoopDetection.h"
+#include "compiler/LoopOptimization.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/RegisterInfo.h"
+
+int movedloopinvariantcode;
+int unswitchedinvariantcode;
+
+static int isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec, int flag1, int flag2) {
+ PCodeArg *op;
+ RegUseOrDef *list;
+ int i;
+
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) {
+ if (pcode->alias) {
+ if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects)))
+ return 0;
+
+ if (pcode->flags & fPCodeFlag2) {
+ for (list = findobjectusedef(pcode->alias->object)->defs; list; list = list->next) {
+ if (
+ may_alias(pcode, Defs[list->id].pcode) &&
+ bitvectorgetbit(list->id, vec) &&
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 0;
+ }
+ }
+
+ if (pcode->flags & fPCodeFlag4) {
+ for (list = findobjectusedef(pcode->alias->object)->uses; list; list = list->next) {
+ if (
+ may_alias(pcode, Uses[list->id].pcode) &&
+ bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 0;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ if ((pcode->flags & fPCodeFlag4) && !bitvectorgetbit(pcode->block->blockIndex, loop->vec2C))
+ return 0;
+
+ op = pcode->args;
+ i = pcode->argCount;
+ while (i--) {
+ switch (op->kind) {
+ case PCOp_MEMORY:
+ if ((pcode->flags & fPCodeFlag2) && ((pcode->flags == 0) & 0x40)) {
+ for (list = findobjectusedef(op->data.mem.obj)->defs; list; list = list->next) {
+ if (
+ may_alias(pcode, Defs[list->id].pcode) &&
+ bitvectorgetbit(list->id, vec) &&
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 0;
+ }
+ }
+ if (pcode->flags & fPCodeFlag4) {
+ for (list = findobjectusedef(op->data.mem.obj)->uses; list; list = list->next) {
+ if (
+ may_alias(pcode, Uses[list->id].pcode) &&
+ bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 0;
+ }
+ }
+ break;
+ case PCOp_REGISTER:
+ if (op->data.reg.effect & (EffectRead | EffectWrite)) {
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) {
+ if (op->data.reg.reg == _FP_)
+ break;
+ if (op->data.reg.reg == _CALLER_SP_)
+ break;
+ if (op->data.reg.reg == 2)
+ break;
+ }
+ if (op->data.reg.reg < n_real_registers[op->arg]) {
+ if (op->arg == RegClass_CRFIELD) {
+ if (!flag2 || (op->data.reg.effect & EffectRead))
+ return 0;
+ } else if (op->arg == RegClass_SPR) {
+ if (!flag1)
+ return 0;
+ } else {
+ return 0;
+ }
+ } else if (op->data.reg.effect & EffectRead) {
+ if (flag1 && op->kind == PCOp_REGISTER && op->arg == RegClass_SPR)
+ break;
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) {
+ if (op->data.reg.reg == _FP_)
+ break;
+ if (op->data.reg.reg == _CALLER_SP_)
+ break;
+ if (op->data.reg.reg == 2)
+ break;
+ }
+
+ for (list = reg_Defs[op->arg][op->data.reg.reg]; list; list = list->next) {
+ if (
+ bitvectorgetbit(list->id, vec) &&
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 0;
+ }
+ }
+ }
+ break;
+ }
+ op++;
+ }
+
+ return 1;
+}
+
+static int isuniquedefinition(PCode *pcode, Loop *loop) {
+ RegUseOrDef *list;
+ int defID;
+ UseOrDef *def;
+
+ defID = pcode->defID;
+ def = &Defs[defID];
+ if (defID >= number_of_Defs)
+ return 0;
+ if (def->pcode != pcode)
+ return 0;
+ if ((defID + 1) < number_of_Defs && def[1].pcode == pcode)
+ return 0;
+
+ if (def->v.kind == PCOp_REGISTER) {
+ for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) {
+ if (
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) &&
+ list->id != defID
+ )
+ return 0;
+ }
+ } else if (def->v.kind == PCOp_MEMORY) {
+ for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) {
+ if (
+ may_alias(pcode, Defs[list->id].pcode) &&
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) &&
+ list->id != defID
+ )
+ return 0;
+ }
+ } else {
+#line 292
+ CError_FATAL();
+ }
+
+ return 1;
+}
+
+static int uniquelyreachesuse(int defID, int useID) {
+ UseOrDef *def;
+ UseOrDef *use;
+ RegUseOrDef *list;
+ PCode *pcode;
+
+ def = &Defs[defID];
+ use = &Uses[useID];
+ if (def->v.kind == PCOp_REGISTER) {
+ for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) {
+ if (
+ list->id != defID &&
+ bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8)
+ )
+ break;
+ }
+ } else if (def->v.kind == PCOp_MEMORY) {
+ for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) {
+ if (
+ may_alias(def->pcode, Defs[list->id].pcode) &&
+ list->id != defID &&
+ bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8)
+ )
+ break;
+ }
+ }
+
+ if (!list)
+ return 1;
+
+ if (def->pcode->block == use->pcode->block) {
+ for (pcode = use->pcode->prevPCode; pcode; pcode = pcode->prevPCode) {
+ if (pcode == def->pcode)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int uniquelyreachesalluses(int defID, Loop *loop) {
+ UseOrDef *def;
+ RegUseOrDef *list;
+
+ def = &Defs[defID];
+
+ if (def->v.kind == PCOp_REGISTER) {
+ for (list = reg_Uses[(char) def->v.arg][def->v.u.reg]; list; list = list->next) {
+ if (
+ bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) ||
+ (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id))
+ )
+ return 0;
+ }
+ } else if (def->v.kind == PCOp_MEMORY) {
+ for (list = findobjectusedef(def->v.u.object)->uses; list; list = list->next) {
+ if (may_alias(def->pcode, Uses[list->id].pcode)) {
+ if (
+ bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) ||
+ (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id))
+ )
+ return 0;
+ }
+ }
+ } else {
+#line 382
+ CError_FATAL();
+ }
+
+ return 1;
+}
+
+static int isliveonexit(TinyValue *v, Loop *loop) {
+ RegUseOrDef *list;
+ UInt32 *vec;
+
+ vec = usedefinfo[loop->preheader->blockIndex].usevec1C;
+
+ if (v->kind == PCOp_REGISTER) {
+ for (list = reg_Uses[(char) v->arg][v->u.reg]; list; list = list->next) {
+ if (
+ bitvectorgetbit(list->id, vec) &&
+ !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 1;
+ }
+ } else if (v->kind == PCOp_MEMORY) {
+ for (list = findobjectusedef(v->u.object)->uses; list; list = list->next) {
+ if (
+ bitvectorgetbit(list->id, vec) &&
+ !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)
+ )
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int dominatesallexits(PCode *pcode, Loop *loop) {
+ return bitvectorgetbit(pcode->block->blockIndex, loop->vec28) != 0;
+}
+
+static int maymove(PCode *pcode, Loop *loop) {
+ short reg;
+
+ if (!isuniquedefinition(pcode, loop))
+ return 0;
+ if (!uniquelyreachesalluses(pcode->defID, loop))
+ return 0;
+ if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop))
+ return 0;
+
+ if (loop->bodySize > 25) {
+ switch (pcode->op) {
+ case PC_LI:
+ if (
+ pcode->nextPCode &&
+ pcode->nextPCode->op == PC_LVX &&
+ (pcode->nextPCode->flags & fIsConst)
+ ) {
+ reg = pcode->args[0].data.reg.reg;
+ if (pcode->nextPCode->args[1].data.reg.reg == reg ||
+ pcode->nextPCode->args[2].data.reg.reg == reg)
+ return 1;
+ }
+ case PC_VSPLTISB:
+ case PC_VSPLTISH:
+ case PC_VSPLTISW:
+ return 0;
+ default:
+ if (!bitvectorgetbit(pcode->block->blockIndex, loop->vec2C))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void moveinvariantcomputation(PCode *pcode, Loop *loop) {
+ ObjectUseDef *oud;
+ BlockList *blocklist;
+ RegUseOrDef *list;
+ UseOrDef *def;
+ int defID;
+
+ defID = pcode->defID;
+ def = &Defs[defID];
+ deletepcode(pcode);
+ insertpcodebefore(loop->preheader->lastPCode, pcode);
+ loop->bodySize--;
+ movedloopinvariantcode = 1;
+
+ if (def->v.kind == PCOp_REGISTER) {
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next)
+ bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8);
+ bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8);
+ }
+ } else if (def->v.kind == PCOp_MEMORY) {
+ oud = findobjectusedef(def->v.u.object);
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ for (list = oud->defs; list; list = list->next) {
+ if (uniquely_aliases(pcode, Defs[list->id].pcode))
+ bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8);
+ }
+ bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8);
+ }
+ } else {
+#line 545
+ CError_FATAL();
+ }
+}
+
+static int srawi_addze_maymove(PCode *pcode, Loop *loop) {
+ RegUseOrDef *list;
+ UseOrDef *def;
+ int defID;
+ int nextDefID;
+
+ defID = pcode->defID;
+ nextDefID = pcode->nextPCode->defID;
+
+ def = &Defs[defID];
+ if (defID >= number_of_Defs)
+ return 0;
+ if (def->pcode != pcode)
+ return 0;
+ if ((defID + 1) < number_of_Defs && def[1].pcode == pcode)
+ return 0;
+
+ if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) {
+ for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) {
+ if (
+ bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) &&
+ list->id != defID &&
+ list->id != nextDefID
+ )
+ return 0;
+ }
+ } else {
+#line 582
+ CError_FATAL();
+ }
+
+ if (!uniquelyreachesalluses(pcode->defID, loop))
+ return 0;
+ if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop))
+ return 0;
+ if (!dominatesallexits(pcode->nextPCode, loop) && isliveonexit(&Defs[pcode->nextPCode->defID].v, loop))
+ return 0;
+
+ return 1;
+}
+
+static int srawi_addze_isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec) {
+ static PCode *oldNextInstr;
+ PCode *nextInstr;
+
+ nextInstr = pcode->nextPCode;
+ if (
+ pcode->op == PC_ADDZE &&
+ oldNextInstr == pcode
+ ) {
+ oldNextInstr = NULL;
+ return 1;
+ } else if (
+ pcode->op == PC_SRAWI &&
+ nextInstr &&
+ nextInstr->op == PC_ADDZE &&
+ pcode->args[0].data.reg.reg == nextInstr->args[0].data.reg.reg &&
+ nextInstr->args[0].data.reg.reg == nextInstr->args[1].data.reg.reg &&
+ !(pcode->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) &&
+ !(nextInstr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) &&
+ isloopinvariant(pcode, loop, vec, 1, 0) &&
+ srawi_addze_maymove(pcode, loop)
+ ) {
+ oldNextInstr = nextInstr;
+ return 1;
+ } else {
+ oldNextInstr = NULL;
+ return 0;
+ }
+}
+
+static void removeblockfromloop(Loop *loop, PCodeBlock *block) {
+ BlockList *list;
+ BlockList **ptr;
+
+ bitvectorclearbit(block->blockIndex, loop->memberblocks);
+ bitvectorclearbit(block->blockIndex, loop->vec24);
+ bitvectorclearbit(block->blockIndex, loop->vec28);
+ bitvectorclearbit(block->blockIndex, loop->vec2C);
+ loop->bodySize -= block->pcodeCount;
+
+ ptr = &loop->blocks;
+ while ((list = *ptr)) {
+ if (list->block == block)
+ *ptr = list->next;
+ else
+ ptr = &list->next;
+ }
+}
+
+static void changesuccessor(PCodeBlock *block, PCodeBlock *from, PCodeBlock *to) {
+ PCLink **ptr;
+ PCLink *link;
+
+ for (link = block->successors; link; link = link->nextLink) {
+ if (link->block == from)
+ link->block = to;
+ }
+
+ ptr = &from->predecessors;
+ while ((link = *ptr)) {
+ if (link->block == block) {
+ *ptr = link->nextLink;
+ link->nextLink = to->predecessors;
+ to->predecessors = link;
+ } else {
+ ptr = &link->nextLink;
+ }
+ }
+}
+
+static void movesuccessor(PCodeBlock *to, PCodeBlock *from, PCodeBlock *block) {
+ PCLink **ptr;
+ PCLink *link;
+
+ for (link = block->predecessors; link; link = link->nextLink) {
+ if (link->block == from)
+ link->block = to;
+ }
+
+ ptr = &from->successors;
+ while ((link = *ptr)) {
+ if (link->block == block) {
+ *ptr = link->nextLink;
+ link->nextLink = to->successors;
+ to->successors = link;
+ } else {
+ ptr = &link->nextLink;
+ }
+ }
+}
+
+static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode *pc2, PCodeArg *op) {
+ PCodeBlock *preheader;
+ PCode *pc3;
+
+ preheader = loop->preheader;
+ if (PCODE_FLAG_SET_F(pc1) & fPCodeFlag20000000) {
+ moveinvariantcomputation(pc1, loop);
+ } else {
+ deletepcode(pc1);
+ insertpcodebefore(loop->preheader->lastPCode, pc1);
+ loop->bodySize--;
+ movedloopinvariantcode = 1;
+ }
+ loop->preheader = NULL;
+
+ insertpreheaderblock(loop);
+
+ pc3 = preheader->lastPCode;
+#line 775
+ CError_ASSERT(pc3->op == PC_B);
+ deletepcode(pc3);
+ deletepcode(pc2);
+ appendpcode(preheader, pc2);
+ movesuccessor(preheader, block, op->data.label.label->block);
+}
+
+static PCodeBlock *appendheadercopy(Loop *loop, PCodeBlock *block1, PCodeBlock *block2, PCodeBlock *block3) {
+ PCodeBlock *newblock1;
+ PCodeBlock *newblock2;
+ PCLink *link;
+ PCode *scan;
+
+ newblock1 = lalloc(sizeof(PCodeBlock));
+ newblock2 = lalloc(sizeof(PCodeBlock));
+
+ newblock1->labels = NULL;
+ newblock1->predecessors = newblock1->successors = NULL;
+ newblock1->firstPCode = newblock1->lastPCode = NULL;
+ newblock1->pcodeCount = 0;
+ newblock1->loopWeight = loop->body->loopWeight;
+ newblock1->flags = 0;
+ newblock1->blockIndex = pcblockcount++;
+
+ newblock2->labels = NULL;
+ newblock2->predecessors = newblock2->successors = NULL;
+ newblock2->firstPCode = newblock2->lastPCode = NULL;
+ newblock2->pcodeCount = 0;
+ newblock2->loopWeight = loop->body->loopWeight;
+ newblock2->flags = 0;
+ newblock2->blockIndex = pcblockcount++;
+
+ newblock1->nextBlock = newblock2;
+ newblock2->prevBlock = newblock1;
+ newblock1->prevBlock = block1;
+ newblock2->nextBlock = block1->nextBlock;
+ block1->nextBlock = newblock1;
+ newblock2->nextBlock->prevBlock = newblock2;
+
+ pclabel(newblock1, makepclabel());
+ pclabel(newblock2, makepclabel());
+
+ changesuccessor(block1, block1->successors->block, newblock1);
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock2;
+ link->nextLink = newblock1->successors;
+ newblock1->successors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock1;
+ link->nextLink = newblock2->predecessors;
+ newblock2->predecessors = link;
+
+ appendpcode(newblock2, makepcode(PC_B, block2->nextBlock->labels));
+ pcbranch(newblock2, block2->nextBlock->labels);
+ pccomputepredecessors1(newblock2);
+
+ for (scan = block2->firstPCode; scan; scan = scan->nextPCode)
+ appendpcode(newblock1, copypcode(scan));
+
+ pcbranch(newblock1, block3->labels);
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock1;
+ link->nextLink = block3->predecessors;
+ block3->predecessors = link;
+
+ addblocktoloop(loop, newblock1);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec28))
+ bitvectorsetbit(newblock1->blockIndex, loop->vec28);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec2C))
+ bitvectorsetbit(newblock1->blockIndex, loop->vec2C);
+
+ for (loop = loop->parent; loop; loop = loop->parent) {
+ addblocktoloop(loop, newblock1);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec28))
+ bitvectorsetbit(newblock1->blockIndex, loop->vec28);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec2C))
+ bitvectorsetbit(newblock1->blockIndex, loop->vec2C);
+
+ addblocktoloop(loop, newblock2);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec28))
+ bitvectorsetbit(newblock2->blockIndex, loop->vec28);
+ if (bitvectorgetbit(block2->blockIndex, loop->vec2C))
+ bitvectorsetbit(newblock2->blockIndex, loop->vec2C);
+ }
+
+ return newblock1;
+}
+
+static BlockList *findswitchpath(Loop *loop, PCodeBlock *block) {
+ BlockList *head;
+ BlockList *tail;
+ BlockList *node;
+ PCodeBlock *scan;
+
+ head = NULL;
+ tail = NULL;
+
+ for (scan = block; scan && scan != loop->body; scan = scan->successors->block) {
+ if (!bitvectorgetbit(scan->blockIndex, loop->memberblocks))
+ return NULL;
+ if (scan->successors && scan->successors->nextLink)
+ return NULL;
+
+ node = oalloc(sizeof(BlockList));
+ node->block = scan;
+ node->next = NULL;
+ if (head) {
+ tail->next = node;
+ tail = node;
+ } else {
+ head = node;
+ tail = node;
+ }
+ }
+
+ return head;
+}
+
+static void simpleunswitchloop(Loop *loop) {
+ PCode *pc29;
+ PCodeArg *op27;
+ UInt32 *myvec;
+ PCodeBlock *block26;
+ PCode *pc25; // r25
+ BlockList *path2_24;
+ PCodeArg *op23;
+ PCode *pc23; // r23
+ BlockList *scanlist; // r23
+ BlockList *bestpath1; // r23
+ BlockList *bestpath2; // r22
+ PCodeBlock *headercopy; // r22
+ Loop *newloop; // r21
+ PCodeBlock *preheader21;
+ BlockList *path20;
+ PCode *scan20;
+ PCode *lastpcode;
+ int i;
+ BlockList *pathiter1;
+ BlockList *pathiter2;
+
+ if (!(lastpcode = loop->body->lastPCode))
+ return;
+ if (lastpcode->op != PC_BT && lastpcode->op != PC_BF)
+ return;
+ if (lastpcode->args[2].kind != PCOp_LABEL)
+ return;
+ if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks))
+ return;
+ if (loop->x57)
+ return;
+ if (loop->x4D)
+ return;
+ if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks))
+ return;
+
+ for (block26 = pcbasicblocks; block26; block26 = block26->nextBlock) {
+ if (bitvectorgetbit(block26->blockIndex, loop->memberblocks))
+ break;
+ }
+
+ if (!block26)
+ return;
+
+ myvec = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ bitvectorcopy(myvec, usedefinfo[block26->blockIndex].defvec8, number_of_Defs);
+ for (pc25 = loop->preheader->nextBlock->firstPCode; pc25; pc25 = pc25->nextPCode) {
+ if (!(PCODE_FLAG_SET_F(pc25) & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects | fPCodeFlag20000000))) {
+ if (isloopinvariant(pc25, loop, myvec, 0, 1))
+ break;
+ }
+ }
+
+ if (!pc25 || pc25->argCount < 1)
+ return;
+
+ if (
+ pc25->argCount < 1 ||
+ pc25->args[0].kind != PCOp_REGISTER ||
+ pc25->args[0].arg != RegClass_CRFIELD
+ )
+ return;
+
+ pc29 = pc25->block->lastPCode;
+ if (
+ !pc29 ||
+ !(pc29->flags & fPCodeFlag1) ||
+ pc29->args[0].kind != PCOp_REGISTER ||
+ pc29->args[0].arg != RegClass_CRFIELD
+ )
+ return;
+
+ if (pc29->args[0].data.reg.reg != pc25->args[0].data.reg.reg)
+ return;
+
+ op27 = NULL;
+ for (i = 0; i < pc29->argCount; i++) {
+ if (pc29->args[i].kind == PCOp_LABEL)
+ op27 = &pc29->args[i];
+ }
+
+ if (op27) {
+ preheader21 = loop->preheader;
+
+ path20 = findswitchpath(loop, block26->nextBlock);
+ if (!path20)
+ return;
+
+ path2_24 = findswitchpath(loop, op27->data.label.label->block);
+ if (!path2_24)
+ return;
+
+ bestpath1 = NULL;
+ bestpath2 = NULL;
+ for (pathiter1 = path20; pathiter1; pathiter1 = pathiter1->next) {
+ for (pathiter2 = path2_24; pathiter2; pathiter2 = pathiter2->next) {
+ if (pathiter1->block == pathiter2->block) {
+ bestpath1 = pathiter1;
+ break;
+ }
+ }
+ if (bestpath1)
+ break;
+ bestpath2 = pathiter1;
+ }
+
+#line 1192
+ CError_ASSERT(bestpath2->block);
+
+ if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B)
+ deletepcode(bestpath2->block->lastPCode);
+
+ while (bestpath1) {
+ for (scan20 = bestpath1->block->firstPCode; scan20; scan20 = scan20->nextPCode) {
+ if (scan20->op != PC_B)
+ appendpcode(bestpath2->block, copypcode(scan20));
+ }
+ bestpath1 = bestpath1->next;
+ }
+
+ headercopy = appendheadercopy(loop, bestpath2->block, loop->body, block26);
+ movecmptopreheader(loop, block26, pc25, pc29, op27);
+
+ if (block26->pcodeCount) {
+ if (path2_24->block->firstPCode) {
+ pc23 = path2_24->block->firstPCode;
+ for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) {
+ if (scan20->op != PC_B)
+ insertpcodebefore(pc23, copypcode(scan20));
+ }
+ } else {
+ for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) {
+ if (scan20->op != PC_B)
+ appendpcode(path2_24->block, copypcode(scan20));
+ }
+ }
+ }
+
+ op23 = NULL;
+ for (i = 0; i < loop->body->lastPCode->argCount; i++) {
+ if (loop->body->lastPCode->args[i].kind == PCOp_LABEL)
+ op23 = &loop->body->lastPCode->args[i];
+ }
+
+#line 1250
+ CError_ASSERT(op23 != NULL);
+
+ changesuccessor(loop->body, op23->data.label.label->block, path2_24->block);
+ op23->data.label.label = path2_24->block->labels;
+
+ op23 = NULL;
+ for (i = 0; i < preheader21->lastPCode->argCount; i++) {
+ if (preheader21->lastPCode->args[i].kind == PCOp_LABEL)
+ op23 = &preheader21->lastPCode->args[i];
+ }
+
+#line 1267
+ CError_ASSERT(op23 != NULL);
+
+ changesuccessor(preheader21, op23->data.label.label->block, loop->body);
+ op23->data.label.label = loop->body->labels;
+
+ op23 = NULL;
+ for (i = 0; i < loop->preheader->lastPCode->argCount; i++) {
+ if (loop->preheader->lastPCode->args[i].kind == PCOp_LABEL)
+ op23 = &loop->preheader->lastPCode->args[i];
+ }
+
+#line 1284
+ CError_ASSERT(op23 != NULL);
+
+ changesuccessor(loop->preheader, op23->data.label.label->block, headercopy);
+ op23->data.label.label = headercopy->labels;
+
+ newloop = lalloc(sizeof(Loop));
+ newloop->parent = loop->parent;
+ newloop->children = NULL;
+ newloop->nextSibling = loop->nextSibling;
+ loop->nextSibling = newloop;
+ newloop->body = loop->body;
+ newloop->preheader = NULL;
+ newloop->blocks = NULL;
+ newloop->basicInductionVars = NULL;
+ newloop->footer = NULL;
+ newloop->pc18 = NULL;
+ newloop->loopWeight = loop->loopWeight;
+
+ bitvectorinitialize(newloop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(newloop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(newloop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(newloop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+
+ removeblockfromloop(loop, newloop->body);
+ addblocktoloop(newloop, newloop->body);
+
+ bitvectorsetbit(newloop->body->blockIndex, newloop->vec24);
+ bitvectorsetbit(newloop->body->blockIndex, newloop->vec2C);
+ bitvectorsetbit(newloop->body->blockIndex, newloop->vec28);
+
+ for (scanlist = path2_24; scanlist; scanlist = scanlist->next) {
+ removeblockfromloop(loop, scanlist->block);
+ addblocktoloop(newloop, scanlist->block);
+ bitvectorsetbit(scanlist->block->blockIndex, newloop->vec2C);
+ }
+
+ newloop->preheader = NULL;
+ insertpreheaderblock(newloop);
+ analyzeloop(newloop);
+
+ loop->body = headercopy;
+
+ for (scanlist = loop->blocks; scanlist; scanlist = scanlist->next)
+ bitvectorsetbit(scanlist->block->blockIndex, loop->vec2C);
+
+ bitvectorsetbit(headercopy->blockIndex, loop->vec24);
+ analyzeloop(loop);
+
+ unswitchedinvariantcode = 1;
+ }
+}
+
+static void simpleunswitchloops(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ simpleunswitchloops(loop->children);
+ else if (!loop->x4F)
+ simpleunswitchloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+static void moveinvariantsfromloop(Loop *loop) {
+ RegUseOrDef *list;
+ BlockList *blocklist;
+ PCode *instr;
+ PCode *nextInstr;
+ UInt32 *myvec;
+ UseOrDef *def;
+ int defID;
+ int flag;
+ PCodeBlock *block;
+
+ myvec = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ do {
+ flag = 0;
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ block = blocklist->block;
+ bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs);
+ for (instr = block->firstPCode; instr; instr = nextInstr) {
+ nextInstr = instr->nextPCode;
+ if (!(instr->flags & fPCodeFlag1) && instr->argCount) {
+ if (
+ !(instr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) &&
+ isloopinvariant(instr, loop, myvec, 0, 0) &&
+ maymove(instr, loop)
+ ) {
+ moveinvariantcomputation(instr, loop);
+ flag = 1;
+ } else if (srawi_addze_isloopinvariant(instr, loop, myvec)) {
+ moveinvariantcomputation(instr, loop);
+ flag = 1;
+ }
+
+ for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) {
+ if (def->v.kind == PCOp_REGISTER) {
+ for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next)
+ bitvectorclearbit(list->id, myvec);
+ } else if (def->v.kind == PCOp_MEMORY) {
+ if ((char) def->v.arg == 0) {
+ for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) {
+ if (uniquely_aliases(instr, Defs[list->id].pcode))
+ bitvectorclearbit(list->id, myvec);
+ }
+ }
+ } else {
+#line 1434
+ CError_FATAL();
+ }
+
+ bitvectorsetbit(defID, myvec);
+ }
+ }
+ }
+ }
+ } while (flag);
+}
+
+static void moveinvariantsfromloops(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ moveinvariantsfromloops(loop->children);
+ moveinvariantsfromloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void moveloopinvariantcode(void) {
+ unswitchedinvariantcode = 0;
+ movedloopinvariantcode = 0;
+ if (loopsinflowgraph) {
+ moveinvariantsfromloops(loopsinflowgraph);
+ simpleunswitchloops(loopsinflowgraph);
+ }
+ freeoheap();
+}
diff --git a/compiler_and_linker/unsorted/Coloring.c b/compiler_and_linker/unsorted/Coloring.c
index e69de29..9ba3c28 100644
--- a/compiler_and_linker/unsorted/Coloring.c
+++ b/compiler_and_linker/unsorted/Coloring.c
@@ -0,0 +1,268 @@
+#include "compiler/Coloring.h"
+#include "compiler/CFunc.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/InterferenceGraph.h"
+#include "compiler/PCode.h"
+#include "compiler/PPCError.h"
+#include "compiler/Registers.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/SpillCode.h"
+#include "compiler/StackFrame.h"
+#include "compiler/objects.h"
+
+char coloring_class;
+static short used_regs_before_coloring;
+
+static void markspecialregisters(RegClass rclass) {
+ ObjectList *list;
+ Object *object;
+ VarInfo *vi;
+ UInt32 i;
+
+ for (i = 0; i < n_real_registers[rclass]; i++)
+ interferencegraph[i]->x14 = i;
+
+ for (list = arguments; list; list = list->next) {
+ object = list->object;
+ vi = Registers_GetVarInfo(object);
+ if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) {
+ interferencegraph[vi->reg]->spillTemporary = object;
+ if (vi->flags & VarInfoFlag4) {
+ interferencegraph[vi->reg]->flags |= fPairLow;
+ interferencegraph[vi->regHi]->flags |= fPairHigh;
+ interferencegraph[vi->regHi]->spillTemporary = object;
+ }
+ }
+ }
+
+ for (list = locals; list; list = list->next) {
+ object = list->object;
+ vi = Registers_GetVarInfo(object);
+ if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) {
+ interferencegraph[vi->reg]->spillTemporary = object;
+ if (vi->flags & VarInfoFlag4) {
+ interferencegraph[vi->reg]->flags |= fPairLow;
+ interferencegraph[vi->regHi]->flags |= fPairHigh;
+ interferencegraph[vi->regHi]->spillTemporary = object;
+ }
+ }
+ }
+}
+
+static IGNode *simplifygraph(void) {
+ int availableRegs;
+ IGNode *spilledNodes;
+ IGNode *pushedNodes;
+ IGNode *best;
+ IGNode *node;
+ UInt32 i;
+ UInt32 j;
+ int flag;
+ float bestScore;
+ float score;
+
+ availableRegs = available_registers(coloring_class);
+ pushedNodes = NULL;
+
+ do {
+ spilledNodes = NULL;
+ flag = 0;
+ for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) {
+ node = interferencegraph[i];
+ if (!(node->flags & (fPushed | fCoalesced))) {
+ if (node->x12 < availableRegs) {
+ for (j = 0; j < node->arraySize; j++)
+ interferencegraph[node->array[j]]->x12--;
+ node->flags |= fPushed;
+ node->next = pushedNodes;
+ pushedNodes = node;
+ flag = 1;
+ } else {
+ node->next = spilledNodes;
+ spilledNodes = node;
+ }
+ }
+ }
+ } while (flag);
+
+ if (spilledNodes)
+ estimatespillcosts();
+
+ while (spilledNodes) {
+ best = spilledNodes;
+ bestScore = (spilledNodes->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) spilledNodes->spillCost / (float) spilledNodes->x12);
+
+ for (node = spilledNodes->next; node; node = node->next) {
+ score = (node->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) node->spillCost / (float) node->x12);
+ if (score < bestScore) {
+ best = node;
+ bestScore = score;
+ }
+ }
+
+ for (i = 0; i < best->arraySize; i++)
+ interferencegraph[best->array[i]]->x12--;
+
+ best->flags |= fPushed;
+ best->next = pushedNodes;
+ pushedNodes = best;
+
+ do {
+ spilledNodes = NULL;
+ flag = 0;
+ for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) {
+ node = interferencegraph[i];
+ if (!(node->flags & (fPushed | fCoalesced))) {
+ if (node->x12 < availableRegs) {
+ for (j = 0; j < node->arraySize; j++)
+ interferencegraph[node->array[j]]->x12--;
+ node->flags |= fPushed;
+ node->next = pushedNodes;
+ pushedNodes = node;
+ flag = 1;
+ } else {
+ node->next = spilledNodes;
+ spilledNodes = node;
+ }
+ }
+ }
+ } while (flag);
+ }
+
+ return pushedNodes;
+}
+
+static int colorgraph(IGNode *node) {
+ UInt32 volatileRegs;
+ int result;
+ IGNode *otherNode;
+ int reg;
+ UInt32 workingMask;
+ int i;
+ short *array;
+
+ result = 1;
+
+ reset_nonvolatile_registers(coloring_class);
+ volatileRegs = volatile_registers(coloring_class);
+
+ while (node) {
+ workingMask = volatileRegs;
+ for (array = node->array, i = 0; i < node->arraySize; i++) {
+ otherNode = interferencegraph[*(array++)];
+ reg = otherNode->x14;
+ if (reg != -1 && reg < n_real_registers[coloring_class])
+ workingMask &= ~(1 << reg);
+ }
+
+ if (workingMask) {
+ for (i = 0; i < n_real_registers[coloring_class]; i++) {
+ if (workingMask & (1 << i)) {
+ node->x14 = i;
+ break;
+ }
+ }
+ } else {
+ reg = obtain_nonvolatile_register(coloring_class);
+ if (reg != -1) {
+ volatileRegs |= 1 << (node->x14 = reg);
+ } else {
+ node->flags |= fSpilled;
+ result = 0;
+ }
+ }
+
+ node = node->next;
+ }
+
+ return result;
+}
+
+static void rewritepcode(void) {
+ PCodeBlock *block;
+ PCode *instr;
+ PCodeArg *op;
+ UInt32 i;
+ IGNode *node;
+ int reg;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (PC_OP_IS_ANY_REGISTER(op, coloring_class))
+ op->data.reg.reg = interferencegraph[op->data.reg.reg]->x14;
+ op++;
+ }
+
+ if (
+ (instr->flags & fPCodeFlag10) &&
+ ((char) instr->args[1].arg == coloring_class) &&
+ instr->args[1].data.reg.reg == instr->args[0].data.reg.reg
+ )
+ deletepcode(instr);
+ }
+ }
+
+ for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) {
+ node = interferencegraph[i];
+ if (node->spillTemporary && !(node->flags & fSpilled)) {
+ if (node->flags & fCoalesced) {
+ reg = node->x14;
+ while (reg >= n_real_registers[coloring_class]) {
+ reg = interferencegraph[reg]->x14;
+ if (reg < 0)
+ break;
+ }
+ node->x14 = reg;
+ }
+
+ if (node->flags & fPairHigh) {
+ reg = node->x14;
+ Registers_GetVarInfo(node->spillTemporary)->regHi = reg;
+ } else {
+ reg = node->x14;
+ Registers_GetVarInfo(node->spillTemporary)->reg = reg;
+ }
+ }
+ }
+}
+
+void colorinstructions(Object *proc) {
+ RegClass rclass;
+ int flag;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ coloring_class = rclass;
+
+ if (rclass == RegClass_GPR)
+ check_dynamic_aligned_frame();
+
+ if (used_virtual_registers[rclass] > n_real_registers[rclass]) {
+ save_before_coloring_nonvolatile_registers(rclass);
+ used_regs_before_coloring = used_virtual_registers[rclass];
+ if (!available_registers(rclass)) {
+ PPCError_Error(102, register_class_name[rclass]);
+ return;
+ }
+
+ flag = 1;
+ while (flag && used_virtual_registers[rclass] > n_real_registers[rclass]) {
+ buildinterferencegraph(proc);
+ markspecialregisters(rclass);
+ flag = colorgraph(simplifygraph()) ? 0 : 1;
+
+ if (flag)
+ insertspillcode();
+ else
+ rewritepcode();
+ freeoheap();
+ }
+ }
+
+ used_virtual_registers[rclass] = n_real_registers[rclass];
+ }
+
+ coloring = 0;
+}
diff --git a/compiler_and_linker/unsorted/ConstantPropagation.c b/compiler_and_linker/unsorted/ConstantPropagation.c
index e69de29..4fe1d06 100644
--- a/compiler_and_linker/unsorted/ConstantPropagation.c
+++ b/compiler_and_linker/unsorted/ConstantPropagation.c
@@ -0,0 +1,643 @@
+#include "compiler/ConstantPropagation.h"
+#include "compiler/Alias.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/objects.h"
+
+int propagatedconstants;
+static int changed;
+static PCode **defininginstruction;
+static PCode **vrdefininginstruction;
+
+static void computedefininginstructions(PCodeBlock *block) {
+ RegUseOrDef *list;
+ PCode *instr;
+ int i;
+
+ for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) {
+ instr = NULL;
+ for (list = reg_Defs[RegClass_GPR][i]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) {
+ if (instr == NULL) {
+ instr = Defs[list->id].pcode;
+ } else {
+ instr = NULL;
+ break;
+ }
+ }
+ }
+ defininginstruction[i] = instr;
+ }
+
+ for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) {
+ instr = NULL;
+ for (list = reg_Defs[RegClass_VR][i]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) {
+ if (instr == NULL) {
+ instr = Defs[list->id].pcode;
+ } else {
+ instr = NULL;
+ break;
+ }
+ }
+ }
+ vrdefininginstruction[i] = instr;
+ }
+}
+
+static PCode *isstackoperand(PCodeArg *op, SInt16 *resultValue, SInt16 addend) {
+ PCode *instr;
+
+ if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_ADDI) {
+ if (
+ instr->args[2].kind == PCOp_MEMORY &&
+ (instr->args[1].data.reg.reg == _FP_ || instr->args[1].data.reg.reg == _CALLER_SP_) &&
+ instr->args[2].data.mem.obj->datatype == DLOCAL
+ )
+ {
+ if (can_add_displ_to_local(instr->args[2].data.mem.obj, addend)) {
+ *resultValue = instr->args[2].data.mem.offset;
+ return instr;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+static int isconstantoperand(PCodeArg *op, SInt16 *resultValue) {
+ PCode *instr;
+
+ if (
+ (instr = defininginstruction[op->data.reg.reg]) &&
+ instr->op == PC_LI &&
+ instr->args[1].kind == PCOp_IMMEDIATE
+ )
+ {
+ *resultValue = instr->args[1].data.imm.value;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int isuint16constantoperand(PCodeArg *op, SInt16 *resultValue) {
+ PCode *instr;
+
+ if (
+ (instr = defininginstruction[op->data.reg.reg]) &&
+ instr->op == PC_LI &&
+ instr->args[1].kind == PCOp_IMMEDIATE &&
+ FITS_IN_USHORT(instr->args[1].data.imm.value)
+ )
+ {
+ *resultValue = instr->args[1].data.imm.value;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int isvectorconstantoperand(PCodeArg *op, SInt16 *resultValue, Opcode *resultNewOp) {
+ PCode *instr;
+
+ if (
+ (instr = vrdefininginstruction[op->data.reg.reg]) &&
+ (instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW) &&
+ instr->args[1].kind == PCOp_IMMEDIATE
+ )
+ {
+ *resultValue = instr->args[1].data.imm.value;
+ *resultNewOp = instr->op;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int isunsignedloadoperand(PCodeArg *op) {
+ PCode *instr;
+
+ if ((instr = defininginstruction[op->data.reg.reg])) {
+ if (instr->flags & fPCodeFlag2) {
+ if (instr->op >= PC_LHZ && instr->op <= PC_LHZUX)
+ return 2;
+ if (instr->op >= PC_LBZ && instr->op <= PC_LBZUX)
+ return 1;
+ } else if (instr->op == PC_RLWINM) {
+ int var3 = instr->args[3].data.imm.value;
+ int var4 = instr->args[4].data.imm.value;
+ if (var4 == 31) {
+ if (var3 == 24)
+ return 1;
+ if (var3 == 16)
+ return 2;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int ismaskedoperand(PCodeArg *op, UInt32 *resultMask) {
+ PCode *instr;
+ UInt32 mask;
+
+ if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_RLWINM) {
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) {
+ mask =
+ ((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 {
+ mask =
+ ((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)));
+ }
+ *resultMask = mask;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int issignedloadoperand(PCodeArg *op) {
+ PCode *instr;
+
+ if ((instr = defininginstruction[op->data.reg.reg])) {
+ if (instr->flags & fPCodeFlag2) {
+ if (instr->op >= PC_LHA && instr->op <= PC_LHAUX)
+ return 2;
+ } else if (instr->op == PC_EXTSB) {
+ return 1;
+ } else if (instr->op == PC_EXTSH) {
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+static void propagateconstantstoblock(PCodeBlock *block) {
+ PCode *instr;
+ SInt16 immAddend;
+ SInt16 value1;
+ SInt16 valueU16;
+ Opcode newOpcode;
+ SInt16 value2;
+ UInt32 mask;
+ UInt32 mask2;
+ int loadSize;
+ PCodeArg *op;
+ int i;
+
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ switch (instr->op) {
+ case PC_MR:
+ if (isconstantoperand(&instr->args[1], &value1)) {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value1;
+ instr->args[1].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ break;
+ case PC_VMR:
+ if (isvectorconstantoperand(&instr->args[1], &value1, &newOpcode)) {
+ change_opcode(instr, newOpcode);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value1;
+ instr->args[1].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ break;
+ case PC_RLWINM:
+ if (
+ !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) &&
+ instr->args[2].data.imm.value == 0 &&
+ instr->args[4].data.imm.value == 31
+ )
+ {
+ if (isconstantoperand(&instr->args[1], &value1)) {
+ if (
+ (instr->args[3].data.imm.value == 16 && value1 == (value1 & 0x7FFF)) ||
+ (instr->args[3].data.imm.value == 24 && value1 == (value1 & 0xFF))
+ )
+ {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ break;
+ }
+ }
+
+ loadSize = isunsignedloadoperand(&instr->args[1]);
+ if (
+ (loadSize == 2 && instr->args[3].data.imm.value <= 16) ||
+ (loadSize == 1 && instr->args[3].data.imm.value <= 24)
+ )
+ {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ break;
+ }
+
+ if (ismaskedoperand(&instr->args[1], &mask)) {
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) {
+ mask2 =
+ ((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 {
+ mask2 =
+ ((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 (mask == (mask & mask2)) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ }
+ }
+ break;
+
+ case PC_EXTSH:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ if (isconstantoperand(&instr->args[1], &value1)) {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ break;
+ }
+
+ loadSize = issignedloadoperand(&instr->args[1]);
+ if (loadSize == 1 || loadSize == 2) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ break;
+
+ case PC_EXTSB:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ if (
+ isconstantoperand(&instr->args[1], &value1) &&
+ value1 >= -128 &&
+ value1 <= 127
+ )
+ {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ break;
+ }
+
+ loadSize = issignedloadoperand(&instr->args[1]);
+ if (loadSize == 1) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ break;
+
+ case PC_ADDI:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ immAddend = instr->args[2].data.imm.value;
+ if (
+ isconstantoperand(&instr->args[1], &value1) &&
+ FITS_IN_SHORT(immAddend + value1)
+ )
+ {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = immAddend + value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ break;
+
+ case PC_ADD:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ if (isconstantoperand(&instr->args[2], &value1)) {
+ if (value1 == 0) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ } else {
+ change_opcode(instr, PC_ADDI);
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = value1;
+ instr->args[2].data.imm.obj = NULL;
+ }
+ propagatedconstants = 1;
+ changed = 1;
+ immAddend = value1;
+ }
+
+ if (isconstantoperand(&instr->args[1], &value1)) {
+ if (instr->op == PC_ADDI || instr->op == PC_MR) {
+ if (FITS_IN_SHORT(immAddend + value1)) {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = immAddend + value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ } else {
+ instr->args[1] = instr->args[2];
+ if (value1 == 0) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ } else {
+ change_opcode(instr, PC_ADDI);
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = value1;
+ instr->args[2].data.imm.obj = NULL;
+ }
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ }
+
+ if (changed) {
+ if (instr->op == PC_MR) {
+ PCode *stackInstr;
+ if ((stackInstr = isstackoperand(&instr->args[1], &value1, 0))) {
+ change_opcode(instr, PC_ADDI);
+ instr->flags = stackInstr->flags;
+ instr->args[1] = stackInstr->args[1];
+ instr->args[2] = stackInstr->args[2];
+ change_num_operands(instr, 3);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ } else if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) {
+ PCode *stackInstr;
+ SInt16 addend = instr->args[2].data.imm.value;
+ if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) {
+ change_opcode(instr, PC_ADDI);
+ instr->flags = stackInstr->flags;
+ instr->args[1] = stackInstr->args[1];
+ instr->args[2] = stackInstr->args[2];
+ instr->args[2].data.imm.value = value1 + addend;
+ if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000))
+ instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, 1);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ }
+ }
+ break;
+
+ case PC_OR:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ value1 = 0;
+ immAddend = 0;
+ if (isconstantoperand(&instr->args[2], &value1)) {
+ if (isuint16constantoperand(&instr->args[2], &valueU16)) {
+ if (valueU16 != 0) {
+ change_opcode(instr, PC_ORI);
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = valueU16;
+ instr->args[2].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ } else {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ value1 = valueU16;
+ } else if (value1 == 0) {
+ change_opcode(instr, PC_MR);
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ immAddend = value1;
+ }
+
+ if (isconstantoperand(&instr->args[1], &value1)) {
+ if (instr->op == PC_ORI || instr->op == PC_MR) {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = immAddend | value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ } else if (isuint16constantoperand(&instr->args[1], &valueU16)) {
+ if (valueU16 != 0) {
+ change_opcode(instr, PC_ORI);
+ instr->args[1] = instr->args[2];
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = valueU16;
+ instr->args[2].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ } else {
+ change_opcode(instr, PC_MR);
+ instr->args[1] = instr->args[2];
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ } else if (value1 == 0) {
+ change_opcode(instr, PC_MR);
+ instr->args[1] = instr->args[2];
+ change_num_operands(instr, 2);
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ }
+ break;
+
+ case PC_SUBF:
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ break;
+
+ if (isconstantoperand(&instr->args[1], &value1) && FITS_IN_SHORT(-value1)) {
+ if (isconstantoperand(&instr->args[2], &value2) && FITS_IN_SHORT(value2 - value1)) {
+ change_opcode(instr, PC_LI);
+ instr->args[1].kind = PCOp_IMMEDIATE;
+ instr->args[1].data.imm.value = value2 - value1;
+ instr->args[1].data.imm.obj = NULL;
+ change_num_operands(instr, 2);
+ } else if (value1 == 0) {
+ change_opcode(instr, PC_MR);
+ instr->args[1] = instr->args[2];
+ change_num_operands(instr, 2);
+ } else {
+ change_opcode(instr, PC_ADDI);
+ instr->args[1] = instr->args[2];
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = -value1;
+ instr->args[2].data.imm.obj = NULL;
+ }
+ propagatedconstants = 1;
+ changed = 1;
+ value2 = value1;
+ } else if (isconstantoperand(&instr->args[2], &value1) && FITS_IN_SHORT(-value1)) {
+ if (value1 == 0) {
+ change_opcode(instr, PC_NEG);
+ change_num_operands(instr, 2);
+ } else {
+ instr->flags = opcodeinfo[PC_SUBFIC].flags | (instr->flags & ~opcodeinfo[PC_SUBF].flags);
+ change_opcode(instr, PC_SUBFIC);
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = value1;
+ instr->args[2].data.imm.obj = NULL;
+ instr->args[3].kind = PCOp_REGISTER;
+ instr->args[3].arg = RegClass_SPR;
+ instr->args[3].data.reg.reg = 0;
+ instr->args[3].data.reg.effect = EffectWrite;
+ change_num_operands(instr, 4);
+ }
+ propagatedconstants = 1;
+ changed = 1;
+ }
+
+ break;
+
+ case PC_LBZ:
+ case PC_LHZ:
+ case PC_LHA:
+ case PC_LWZ:
+ case PC_STB:
+ case PC_STH:
+ case PC_STW:
+ case PC_LFS:
+ case PC_LFD:
+ case PC_STFS:
+ case PC_STFD:
+ if (instr->args[2].kind == PCOp_IMMEDIATE) {
+ PCode *stackInstr;
+ SInt16 addend = instr->args[2].data.imm.value;
+
+ if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) {
+ instr->args[1] = stackInstr->args[1];
+ instr->args[2] = stackInstr->args[2];
+ instr->args[2].data.imm.value = value1 + addend;
+ if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000))
+ instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value,
+ nbytes_loaded_or_stored_by(instr));
+ propagatedconstants = 1;
+ changed = 1;
+ }
+ }
+ break;
+
+ case PC_LBZX:
+ case PC_LHZX:
+ case PC_LHAX:
+ case PC_LWZX:
+ case PC_STBX:
+ case PC_STHX:
+ case PC_STWX:
+ case PC_LFSX:
+ case PC_LFDX:
+ case PC_STFSX:
+ case PC_STFDX:
+ if (isconstantoperand(&instr->args[2], &value1)) {
+ instr->op -= 2;
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = value1;
+ instr->args[2].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ } else if (isconstantoperand(&instr->args[1], &value1)) {
+ instr->op -= 2;
+ instr->args[1] = instr->args[2];
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = value1;
+ instr->args[2].data.imm.obj = NULL;
+ propagatedconstants = 1;
+ changed = 1;
+ }
+
+ break;
+ }
+
+ for (i = 0, op = instr->args; i < instr->argCount; i++, op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ {
+ defininginstruction[op->data.reg.reg] = instr;
+ }
+ else if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_VR &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ {
+ vrdefininginstruction[op->data.reg.reg] = instr;
+ }
+ }
+ }
+}
+
+void propagateconstants(void) {
+ PCodeBlock *block;
+ int i;
+
+ propagatedconstants = 0;
+ computeusedefchains(0);
+ defininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_GPR]);
+ vrdefininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_VR]);
+
+ do {
+ changed = 0;
+ for (i = 0; i < pcblockcount; i++) {
+ if ((block = depthfirstordering[i])) {
+ computedefininginstructions(block);
+ propagateconstantstoblock(block);
+ }
+ }
+ } while (changed);
+
+ freeoheap();
+}
diff --git a/compiler_and_linker/unsorted/CopyPropagation.c b/compiler_and_linker/unsorted/CopyPropagation.c
index e69de29..23583b1 100644
--- a/compiler_and_linker/unsorted/CopyPropagation.c
+++ b/compiler_and_linker/unsorted/CopyPropagation.c
@@ -0,0 +1,474 @@
+#include "compiler/CopyPropagation.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/PCode.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/BitVectors.h"
+
+// TODO move me
+extern void pclistblocks(char *, char *);
+
+int propagatedcopies;
+int propagated_instructions;
+int recursive_propagation;
+int number_of_candidates;
+Candidate *Candidates;
+PropInfo *propinfo;
+int *ncandidatesinblock;
+int *firstcandidateinblock;
+static int moreaggressiveoptimization;
+static PropagateAndFinishFunc propagateandfinish;
+static PropagatesToUseFunc propagatestouse;
+static IsCandidateFunc is_candidate;
+
+static void precomputecanidatecounts(void) {
+ PCodeBlock *block;
+ PCode *pcode;
+ int count;
+
+ ncandidatesinblock = oalloc(sizeof(int) * pcblockcount);
+ firstcandidateinblock = oalloc(sizeof(int) * pcblockcount);
+ number_of_candidates = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ firstcandidateinblock[block->blockIndex] = number_of_candidates;
+
+ count = 0;
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (is_candidate(pcode)) {
+ number_of_candidates++;
+ count++;
+ }
+ }
+ ncandidatesinblock[block->blockIndex] = count;
+ }
+}
+
+static void computecandidatelist(void) {
+ RegUseOrDef *list; // r23
+ PCodeBlock *block; // r22
+ PCode *pcode; // r21
+ Candidate *candidate; // r20
+ UInt32 *vec; // r19
+ int reg;
+ RegUseOrDef *newlist;
+ UseOrDef *def;
+ UseOrDef *use;
+ int defID;
+ int useID;
+
+ Candidates = oalloc(sizeof(Candidate) * number_of_candidates);
+ vec = oalloc(4 * ((number_of_Uses + 31) >> 5));
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (ncandidatesinblock[block->blockIndex]) {
+ bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses);
+ candidate = &Candidates[firstcandidateinblock[block->blockIndex] + ncandidatesinblock[block->blockIndex] - 1];
+ for (pcode = block->lastPCode; pcode; pcode = pcode->prevPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ if (is_candidate(pcode)) {
+ reg = pcode->args[0].data.reg.reg;
+ candidate->pcode = pcode;
+ candidate->list = NULL;
+
+ for (list = reg_Uses[pcode->args[0].arg][reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, vec)) {
+ newlist = oalloc(sizeof(RegUseOrDef));
+ newlist->id = list->id;
+ newlist->next = candidate->list;
+ candidate->list = newlist;
+ }
+ }
+
+ if ((pcode->flags & fPCodeFlag2 | fPCodeFlag4) && (pcode->flags & fPCodeFlag2000000)) {
+ for (list = reg_Uses[pcode->args[1].arg][pcode->args[1].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, vec)) {
+ newlist = oalloc(sizeof(RegUseOrDef));
+ newlist->id = list->id;
+ newlist->next = candidate->list;
+ candidate->list = newlist;
+ }
+ }
+ }
+
+ candidate--;
+ }
+
+ for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; def++, defID++) {
+ if (def->kind == PCOp_REGISTER) {
+ for (list = reg_Uses[def->arg][def->u.reg]; list; list = list->next)
+ bitvectorclearbit(list->id, vec);
+ }
+ }
+ for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) {
+ if (use->kind == PCOp_REGISTER)
+ bitvectorsetbit(useID, vec);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void allocatepropinfo(void) {
+ PropInfo *info;
+ int i;
+
+ propinfo = oalloc(sizeof(PropInfo) * pcblockcount);
+ for (i = 0, info = propinfo; i < pcblockcount; i++, info++) {
+ info->vec0 = oalloc(4 * ((number_of_candidates + 31) >> 5));
+ info->vec4 = oalloc(4 * ((number_of_candidates + 31) >> 5));
+ info->vec8 = oalloc(4 * ((number_of_candidates + 31) >> 5));
+ info->vecC = oalloc(4 * ((number_of_candidates + 31) >> 5));
+ }
+}
+
+static void computelocalpropinfo(Boolean flag) {
+ PropInfo *info;
+ PCode *pcode;
+ PCodeBlock *block;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ int index;
+ PCodeArg *op;
+ PCodeArg *candOp;
+ int i;
+ int j;
+ int cndi;
+ Candidate *candidate;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ info = &propinfo[block->blockIndex];
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+ bitvectorinitialize(vec0, number_of_candidates, 0);
+ bitvectorinitialize(vec4, number_of_candidates, 0);
+ index = firstcandidateinblock[block->blockIndex];
+
+ if (flag) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ i = pcode->argCount;
+ op = pcode->args;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) {
+ for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) {
+ for (j = 0; j < candidate->pcode->argCount; j++) {
+ candOp = candidate->pcode->args + j;
+ if (candOp->kind == PCOp_REGISTER && candOp->arg == RegClass_GPR && candOp->data.reg.reg == op->data.reg.reg) {
+ if (candidate->pcode->block == block)
+ bitvectorclearbit(cndi, vec0);
+ else
+ bitvectorsetbit(cndi, vec4);
+ break;
+ }
+ }
+ }
+ }
+ op++;
+ }
+
+ if (is_candidate(pcode)) {
+ bitvectorsetbit(index, vec0);
+ index++;
+ }
+ }
+ }
+ } else {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ i = pcode->argCount;
+ op = pcode->args;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) {
+ for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) {
+ for (j = 0; j < candidate->pcode->argCount; j++) {
+ candOp = candidate->pcode->args + j;
+ if (candOp->kind == PCOp_REGISTER && candOp->arg == op->arg) {
+ if (candOp->data.reg.reg == op->data.reg.reg) {
+ if (candidate->pcode->block == block)
+ bitvectorclearbit(cndi, vec0);
+ else
+ bitvectorsetbit(cndi, vec4);
+ break;
+ }
+ } else {
+ if (j == 0)
+ break;
+ }
+ }
+ }
+ }
+ op++;
+ }
+
+ if (is_candidate(pcode)) {
+ bitvectorsetbit(index, vec0);
+ index++;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void computeglobalpropinfo(void) {
+ PropInfo *info;
+ PCodeBlock *block;
+ int bitvecsize;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ UInt32 *vec8;
+ UInt32 *vecC;
+ int i;
+ int j;
+ int flag;
+ PCLink *preds;
+ UInt32 val;
+
+ bitvecsize = (number_of_candidates + 31) >> 5;
+ flag = 1;
+ info = &propinfo[pcbasicblocks->blockIndex];
+ bitvectorinitialize(info->vec8, number_of_candidates, 0);
+ bitvectorcopy(info->vecC, info->vec0, number_of_candidates);
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
+ info = &propinfo[block->blockIndex];
+ vecC = info->vecC;
+ vec4 = info->vec4;
+ for (i = 0; i < bitvecsize; vecC++, vec4++, i++)
+ *vecC = ~*vec4;
+ }
+
+ while (flag) {
+ flag = 0;
+ for (i = 0; i < pcblockcount; i++) {
+ if (depthfirstordering[i]) {
+ info = &propinfo[depthfirstordering[i]->blockIndex];
+ if ((preds = depthfirstordering[i]->predecessors)) {
+ vec8 = info->vec8;
+ bitvectorcopy(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates);
+ for (preds = preds->nextLink; preds; preds = preds->nextLink)
+ bitvectorintersect(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates);
+ }
+
+ vecC = info->vecC;
+ vec8 = info->vec8;
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+ for (j = 0; j < bitvecsize; j++) {
+ val = *vec0 | (*vec8 & ~*vec4);
+ if (val != *vecC) {
+ *vecC = val;
+ flag = 1;
+ }
+ vec8++;
+ vecC++;
+ vec4++;
+ vec0++;
+ }
+ }
+ }
+ }
+}
+
+int precedes(PCode *a, PCode *b) {
+ PCode *scan;
+
+ for (scan = a->nextPCode; scan; scan = scan->nextPCode) {
+ if (scan == b)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int canidatepropagatestoalluses(int id) {
+ RegUseOrDef *list;
+
+ if (PCODE_FLAG_SET_F(Candidates[id].pcode) & (fPCodeFlag20000000 | fSideEffects))
+ return 0;
+
+ for (list = Candidates[id].list; list; list = list->next) {
+ if (!propagatestouse(id, list->id))
+ return 0;
+ }
+
+ return 1;
+}
+
+static void propagatecandidates(void) {
+ int i;
+
+ for (i = 0; i < number_of_candidates; i++) {
+ if (canidatepropagatestoalluses(i))
+ propagateandfinish(i);
+ }
+}
+
+void propagateinstructions(Object *proc, Propagation *config, int passCount, Boolean localflag) {
+ char buf[64];
+
+ is_candidate = config->is_candidate;
+ propagatestouse = config->propagatestouse;
+ propagateandfinish = config->propagateandfinish;
+ propagated_instructions = 0;
+
+ while (1) {
+ recursive_propagation = 0;
+ precomputecanidatecounts();
+ if (number_of_candidates <= 0) {
+ freeoheap();
+ if (config->computesUseDefChains)
+ computeusedefchains(0);
+ return;
+ }
+
+ computeusedefchains(0);
+ computecandidatelist();
+ allocatepropinfo();
+ computelocalpropinfo(localflag);
+ computedepthfirstordering();
+ computeglobalpropinfo();
+ propagatecandidates();
+ passCount--;
+
+ if (propagated_instructions && copts.debuglisting) {
+ sprintf(buf, "AFTER %s PROPAGATION", config->name);
+ pclistblocks(CMangler_GetLinkName(proc)->name, buf);
+ }
+
+ if (!passCount || !recursive_propagation) {
+ if (!config->computesUseDefChains)
+ freeoheap();
+ return;
+ }
+
+ freeoheap();
+ }
+}
+
+static int is_copy(PCode *pcode) {
+ return (pcode->flags & fPCodeFlag10) && (pcode->args[0].data.reg.reg >= n_real_registers[pcode->args[0].arg]);
+}
+
+static int copypropagatestouse(int candidateID, int useID) {
+ UseOrDef *use;
+ short reg1;
+ short reg2;
+ char rclass;
+ PCode *pcode;
+ int i;
+ PCode *scan;
+ PCodeArg *op;
+
+ pcode = Candidates[candidateID].pcode;
+ use = Uses + useID;
+ rclass = pcode->args[0].arg;
+ reg1 = pcode->args[0].data.reg.reg;
+ reg2 = pcode->args[1].data.reg.reg;
+
+ if (use->pcode->flags & fPCodeFlag10)
+ return 0;
+
+ if (rclass == RegClass_GPR && use->pcode->op == PC_RLWIMI && use->pcode->args[0].data.reg.reg == reg1)
+ return 0;
+
+ if (pcode->block == use->pcode->block && precedes(pcode, use->pcode)) {
+ for (scan = pcode->nextPCode; scan && scan != use->pcode; scan = scan->nextPCode) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == rclass &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg2
+ )
+ return 0;
+ op++;
+ }
+ }
+ } else {
+ if (!bitvectorgetbit(candidateID, propinfo[use->pcode->block->blockIndex].vec8))
+ return 0;
+
+ for (scan = use->pcode->block->firstPCode; scan; scan = scan->nextPCode) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == rclass &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg2
+ )
+ return 0;
+ op++;
+ }
+ if (scan == use->pcode)
+ break;
+ }
+ }
+
+ return 1;
+}
+
+static void propagateandremovecopy(int id) {
+ Candidate *candidate;
+ unsigned char rclass;
+ short reg1;
+ short reg2;
+ RegUseOrDef *list;
+ int i;
+ PCodeArg *op;
+
+ candidate = &Candidates[id];
+ rclass = candidate->pcode->args[0].arg;
+ reg1 = candidate->pcode->args[0].data.reg.reg;
+ reg2 = candidate->pcode->args[1].data.reg.reg;
+
+ if (rclass == RegClass_GPR && reg1 >= 32 && reg1 <= last_exception_register[RegClass_GPR])
+ return;
+
+ if (!moreaggressiveoptimization && reg2 < n_real_registers[(char) rclass])
+ return;
+
+ for (list = candidate->list; list; list = list->next) {
+ op = Uses[list->id].pcode->args;
+ i = Uses[list->id].pcode->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == (char) rclass &&
+ op->data.reg.reg == reg1 &&
+ (op->data.reg.effect & EffectRead)
+ )
+ op->data.reg.reg = reg2;
+ op++;
+ }
+ }
+
+ deletepcode(candidate->pcode);
+ propagated_instructions = 1;
+}
+
+static Propagation copy_prop = {
+ &is_copy,
+ &copypropagatestouse,
+ &propagateandremovecopy,
+ "COPY",
+ "COPIES",
+ "c%ld",
+ 0
+};
+
+void propagatecopyinstructions(Object *proc, int flag) {
+ moreaggressiveoptimization = flag;
+ propagateinstructions(proc, &copy_prop, 1, 0);
+ propagatedcopies = propagated_instructions;
+}
+
diff --git a/compiler_and_linker/unsorted/IROUseDef.c b/compiler_and_linker/unsorted/IROUseDef.c
index e69de29..943e557 100644
--- a/compiler_and_linker/unsorted/IROUseDef.c
+++ b/compiler_and_linker/unsorted/IROUseDef.c
@@ -0,0 +1,1448 @@
+#include "compiler/IROUseDef.h"
+#include "compiler/IRODump.h"
+#include "compiler/IROVars.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroTransform.h"
+#include "compiler/IroUtil.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+
+ENodeType IRO_NonAssignmentOp[MAXEXPR];
+typedef CInt64 (*AssignmentFoldingFunc)(CInt64, CInt64);
+static AssignmentFoldingFunc AssignmentFoldingFunction[MAXEXPR];
+static SInt32 NumDefs;
+static IRODef *FirstDef;
+static IRODef *LastDef;
+static SInt32 NumUses;
+static BitVector *Reaches;
+static BitVector *MightReachAnyUse;
+static BitVector *alldefs;
+static BitVector *alluses;
+static BitVector *defset;
+static BitVector *useset;
+IROUse *IRO_FirstVarUse;
+IROUse *IRO_LastVarUse;
+
+// forward decls
+static void AddDefToRange(IRODef *def);
+
+static void MakeDef(VarRecord *var, IROLinear *linear, IRONode *node, Boolean flag) {
+ IRODef *def = oalloc(sizeof(IRODef));
+
+ def->index = NumDefs++;
+ def->node = node;
+ def->linear = linear;
+ def->var = var;
+ def->globalnext = NULL;
+ def->x18 = 0;
+ def->x1A = Inline_IsObjectData(var->object);
+ def->x1B = var->xB;
+ def->x1C = flag;
+ def->x1D = 0;
+
+ if (FirstDef)
+ LastDef->globalnext = def;
+ else
+ FirstDef = def;
+ LastDef = def;
+
+ def->varnext = var->defs;
+ var->defs = def;
+}
+
+static void MakeUse(VarRecord *var, IROLinear *linear, IRONode *node) {
+ IROUse *use = oalloc(sizeof(IROUse));
+
+ use->index = NumUses++;
+ use->node = node;
+ use->linear = linear;
+ use->var = var;
+ use->globalnext = NULL;
+ use->x1C = 0;
+
+ if (IRO_FirstVarUse)
+ IRO_LastVarUse->globalnext = use;
+ else
+ IRO_FirstVarUse = use;
+ IRO_LastVarUse = use;
+
+ use->varnext = var->uses;
+ var->uses = use;
+}
+
+static void FindDefsAndUses(void) {
+ VarRecord *var;
+ IROLinear *linear;
+ IRONode *node;
+
+ NumDefs = 0;
+ NumUses = 0;
+ IRO_FirstVarUse = NULL;
+ FirstDef = NULL;
+
+ for (var = IRO_FirstVar; var; var = var->next) {
+ var->defs = NULL;
+ var->uses = NULL;
+ var->xC = 0;
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ for (linear = node->first; linear; linear = linear->next) {
+ if (IS_LINEAR_ENODE(linear, EOBJREF)) {
+ Object *obj = linear->u.node->data.objref;
+ if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) {
+ if ((var = IRO_FindVar(obj, 0, 1)))
+ MakeUse(var, linear, node);
+ }
+ }
+
+ if (IRO_IsAssignment(linear) && (var = IRO_FindAssigned(linear))) {
+ MakeDef(
+ var,
+ linear,
+ node,
+ (linear->rtype->size == var->object->type->size) && !IRO_IsBitField
+ );
+ }
+
+ if (linear->type == IROLinearAsm) {
+ IAEffects effects;
+ int i;
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+
+ for (i = 0; i < effects.numoperands; i++) {
+ var = IRO_FindVar(effects.operands[i].object, 0, 1);
+ switch (effects.operands[i].type) {
+ case IAEffect_0:
+ MakeUse(var, linear, node);
+ break;
+ case IAEffect_1:
+ MakeDef(
+ var,
+ linear,
+ node,
+ (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size)
+ );
+ break;
+ case IAEffect_2:
+ MakeDef(var, linear, node, 0);
+ break;
+ case IAEffect_4:
+ MakeUse(var, linear, node);
+ MakeDef(
+ var,
+ linear,
+ node,
+ (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size)
+ );
+ break;
+ }
+ }
+ }
+
+ if (linear == node->last)
+ break;
+ }
+ }
+
+ for (var = IRO_FirstVar; var; var = var->next)
+ MakeDef(var, NULL, NULL, 1);
+}
+
+static void MarkUses(Object *obj) {
+ VarRecord *var;
+ IRODef *def;
+
+ if ((var = IRO_FindVar(obj, 0, 1))) {
+ for (def = var->defs; def; def = def->varnext) {
+ if (Bv_IsBitSet(def->index, Reaches)) {
+ Bv_SetBit(def->index, MightReachAnyUse);
+ def->x18++;
+ }
+ }
+
+ var->xC = 1;
+ }
+}
+
+static Boolean IsIncOrDec(IROLinear *linear) {
+ switch (linear->type) {
+ case IROLinearOp1Arg:
+ if (linear->nodetype == EPOSTINC || linear->nodetype == EPOSTDEC || linear->nodetype == EPREINC || linear->nodetype == EPREDEC) {
+ if (!(linear->u.monadic->flags & IROLF_BitfieldIndirect))
+ return 1;
+ }
+ break;
+ case IROLinearOp2Arg:
+ if (linear->nodetype == EADDASS || linear->nodetype == ESUBASS) {
+ if (IRO_IsIntConstant(linear->u.diadic.right) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect))
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static Boolean IsOtherSelfAssignment(IROLinear *linear) {
+ switch (linear->type) {
+ case IROLinearOp2Arg:
+ switch (linear->nodetype) {
+ case EMULASS:
+ case EDIVASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ if (IRO_IsIntConstant(linear->u.diadic.right))
+ return 1;
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) {
+ CInt64 result;
+
+ if (linear->type == IROLinearOp1Arg) {
+ switch (linear->nodetype) {
+ case EPOSTINC:
+ case EPREINC:
+ CInt64_SetLong(&result, 1);
+ break;
+ case EPOSTDEC:
+ case EPREDEC:
+ CInt64_SetLong(&result, -1);
+ break;
+ default:
+#line 445
+ CError_FATAL();
+ }
+
+ if (IS_TYPE_POINTER_ONLY(linear->rtype)) {
+ CInt64 mul;
+ CInt64_SetLong(&mul, TPTR_TARGET(linear->rtype)->size);
+ result = CInt64_Mul(result, mul);
+ }
+ } else if (linear->type == IROLinearOp2Arg) {
+ switch (linear->nodetype) {
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ result = linear->u.diadic.right->u.node->data.intval;
+ break;
+ case ESUBASS:
+ result = linear->u.diadic.right->u.node->data.intval;
+ result = CInt64_Neg(result);
+ break;
+ default:
+#line 491
+ CError_FATAL();
+ }
+ } else {
+#line 496
+ CError_FATAL();
+ }
+
+ return result;
+}
+
+static void UpdateUse(IROLinear *linear, CInt64 val, Type *type) {
+ IROLinear *father;
+ IROLinear *repl;
+ IROLinear *newdiadic;
+
+ if ((father = IRO_LocateFather(linear))) {
+ switch (father->type) {
+ case IROLinearOp1Arg:
+ switch (father->nodetype) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ val = CInt64_Add(val, IRO_GetSelfAssignmentVal(father));
+ father->nodetype = EADDASS;
+ father->type = IROLinearOp2Arg;
+ repl = IRO_NewIntConst(val, type);
+ father->u.diadic.right = repl;
+ IRO_PasteAfter(repl, repl, linear);
+ return;
+ }
+ break;
+ case IROLinearOp2Arg:
+ if (IRO_IsIntConstant(father->u.diadic.right)) {
+ switch (father->nodetype) {
+ case EADD:
+ case EADDASS:
+ father->u.diadic.right->u.node->data.intval = CInt64_Add(
+ father->u.diadic.right->u.node->data.intval, val);
+ return;
+ case ESUB:
+ case ESUBASS:
+ father->u.diadic.right->u.node->data.intval = CInt64_Sub(
+ father->u.diadic.right->u.node->data.intval, val);
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ repl = IRO_NewIntConst(val, type);
+ newdiadic = IRO_NewLinear(IROLinearOp2Arg);
+ newdiadic->index = ++IRO_NumLinear;
+ newdiadic->nodetype = EADD;
+ newdiadic->u.diadic.left = linear;
+ newdiadic->u.diadic.right = repl;
+ newdiadic->rtype = linear->rtype;
+ repl->next = newdiadic;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, newdiadic);
+ IRO_PasteAfter(repl, newdiadic, linear);
+}
+
+void IRO_InitializeNonAssignmentOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ IRO_NonAssignmentOp[i] = MAXEXPR;
+
+ IRO_NonAssignmentOp[EPOSTINC] = MAXEXPR;
+ IRO_NonAssignmentOp[EPOSTDEC] = MAXEXPR;
+ IRO_NonAssignmentOp[EPREINC] = MAXEXPR;
+ IRO_NonAssignmentOp[EPREDEC] = MAXEXPR;
+ IRO_NonAssignmentOp[EINDIRECT] = MAXEXPR;
+ IRO_NonAssignmentOp[EMONMIN] = MAXEXPR;
+ IRO_NonAssignmentOp[EBINNOT] = MAXEXPR;
+ IRO_NonAssignmentOp[ELOGNOT] = MAXEXPR;
+ IRO_NonAssignmentOp[EFORCELOAD] = MAXEXPR;
+ IRO_NonAssignmentOp[EMUL] = MAXEXPR;
+ IRO_NonAssignmentOp[EMULV] = MAXEXPR;
+ IRO_NonAssignmentOp[EDIV] = MAXEXPR;
+ IRO_NonAssignmentOp[EMODULO] = MAXEXPR;
+ IRO_NonAssignmentOp[EADDV] = MAXEXPR;
+ IRO_NonAssignmentOp[ESUBV] = MAXEXPR;
+ IRO_NonAssignmentOp[EADD] = MAXEXPR;
+ IRO_NonAssignmentOp[ESUB] = MAXEXPR;
+ IRO_NonAssignmentOp[ESHL] = MAXEXPR;
+ IRO_NonAssignmentOp[ESHR] = MAXEXPR;
+ IRO_NonAssignmentOp[ELESS] = MAXEXPR;
+ IRO_NonAssignmentOp[EGREATER] = MAXEXPR;
+ IRO_NonAssignmentOp[ELESSEQU] = MAXEXPR;
+ IRO_NonAssignmentOp[EGREATEREQU] = MAXEXPR;
+ IRO_NonAssignmentOp[EEQU] = MAXEXPR;
+ IRO_NonAssignmentOp[ENOTEQU] = MAXEXPR;
+ IRO_NonAssignmentOp[EAND] = MAXEXPR;
+ IRO_NonAssignmentOp[EXOR] = MAXEXPR;
+ IRO_NonAssignmentOp[EOR] = MAXEXPR;
+ IRO_NonAssignmentOp[ELAND] = MAXEXPR;
+ IRO_NonAssignmentOp[ELOR] = MAXEXPR;
+ IRO_NonAssignmentOp[EASS] = MAXEXPR;
+ IRO_NonAssignmentOp[EMULASS] = EMUL;
+ IRO_NonAssignmentOp[EDIVASS] = EDIV;
+ IRO_NonAssignmentOp[EMODASS] = EMODULO;
+ IRO_NonAssignmentOp[EADDASS] = EADD;
+ IRO_NonAssignmentOp[ESUBASS] = ESUB;
+ IRO_NonAssignmentOp[ESHLASS] = ESHL;
+ IRO_NonAssignmentOp[ESHRASS] = ESHR;
+ IRO_NonAssignmentOp[EANDASS] = EAND;
+ IRO_NonAssignmentOp[EXORASS] = EXOR;
+ IRO_NonAssignmentOp[EORASS] = EOR;
+ IRO_NonAssignmentOp[ECOMMA] = MAXEXPR;
+ IRO_NonAssignmentOp[EPMODULO] = MAXEXPR;
+ IRO_NonAssignmentOp[EROTL] = MAXEXPR;
+ IRO_NonAssignmentOp[EROTR] = MAXEXPR;
+ IRO_NonAssignmentOp[EBCLR] = MAXEXPR;
+ IRO_NonAssignmentOp[EBTST] = MAXEXPR;
+ IRO_NonAssignmentOp[EBSET] = MAXEXPR;
+ IRO_NonAssignmentOp[ETYPCON] = MAXEXPR;
+ IRO_NonAssignmentOp[EBITFIELD] = MAXEXPR;
+ IRO_NonAssignmentOp[EINTCONST] = MAXEXPR;
+ IRO_NonAssignmentOp[EFLOATCONST] = MAXEXPR;
+ IRO_NonAssignmentOp[ESTRINGCONST] = MAXEXPR;
+ IRO_NonAssignmentOp[ECOND] = MAXEXPR;
+ IRO_NonAssignmentOp[EFUNCCALL] = MAXEXPR;
+ IRO_NonAssignmentOp[EFUNCCALLP] = MAXEXPR;
+ IRO_NonAssignmentOp[EOBJREF] = MAXEXPR;
+ IRO_NonAssignmentOp[EMFPOINTER] = MAXEXPR;
+ IRO_NonAssignmentOp[ENULLCHECK] = MAXEXPR;
+ IRO_NonAssignmentOp[EPRECOMP] = MAXEXPR;
+ IRO_NonAssignmentOp[ETEMP] = MAXEXPR;
+ IRO_NonAssignmentOp[EARGOBJ] = MAXEXPR;
+ IRO_NonAssignmentOp[ELOCOBJ] = MAXEXPR;
+ IRO_NonAssignmentOp[ELABEL] = MAXEXPR;
+ IRO_NonAssignmentOp[ESETCONST] = MAXEXPR;
+ IRO_NonAssignmentOp[ENEWEXCEPTION] = MAXEXPR;
+ IRO_NonAssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR;
+ IRO_NonAssignmentOp[EOBJLIST] = MAXEXPR;
+ IRO_NonAssignmentOp[EMEMBER] = MAXEXPR;
+ IRO_NonAssignmentOp[ETEMPLDEP] = MAXEXPR;
+ IRO_NonAssignmentOp[EINSTRUCTION] = MAXEXPR;
+ IRO_NonAssignmentOp[EDEFINE] = MAXEXPR;
+ IRO_NonAssignmentOp[EREUSE] = MAXEXPR;
+ IRO_NonAssignmentOp[EASSBLK] = MAXEXPR;
+ IRO_NonAssignmentOp[EVECTOR128CONST] = MAXEXPR;
+ IRO_NonAssignmentOp[ECONDASS] = MAXEXPR;
+}
+
+void IRO_InitializeAssignmentFoldingFunctionArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ AssignmentFoldingFunction[i] = NULL;
+
+ AssignmentFoldingFunction[EPOSTINC] = NULL;
+ AssignmentFoldingFunction[EPOSTDEC] = NULL;
+ AssignmentFoldingFunction[EPREINC] = NULL;
+ AssignmentFoldingFunction[EPREDEC] = NULL;
+ AssignmentFoldingFunction[EINDIRECT] = NULL;
+ AssignmentFoldingFunction[EMONMIN] = NULL;
+ AssignmentFoldingFunction[EBINNOT] = NULL;
+ AssignmentFoldingFunction[ELOGNOT] = NULL;
+ AssignmentFoldingFunction[EFORCELOAD] = NULL;
+ AssignmentFoldingFunction[EMUL] = NULL;
+ AssignmentFoldingFunction[EMULV] = NULL;
+ AssignmentFoldingFunction[EDIV] = NULL;
+ AssignmentFoldingFunction[EMODULO] = NULL;
+ AssignmentFoldingFunction[EADDV] = NULL;
+ AssignmentFoldingFunction[ESUBV] = NULL;
+ AssignmentFoldingFunction[EADD] = NULL;
+ AssignmentFoldingFunction[ESUB] = NULL;
+ AssignmentFoldingFunction[ESHL] = NULL;
+ AssignmentFoldingFunction[ESHR] = NULL;
+ AssignmentFoldingFunction[ELESS] = NULL;
+ AssignmentFoldingFunction[EGREATER] = NULL;
+ AssignmentFoldingFunction[ELESSEQU] = NULL;
+ AssignmentFoldingFunction[EGREATEREQU] = NULL;
+ AssignmentFoldingFunction[EEQU] = NULL;
+ AssignmentFoldingFunction[ENOTEQU] = NULL;
+ AssignmentFoldingFunction[EAND] = NULL;
+ AssignmentFoldingFunction[EXOR] = NULL;
+ AssignmentFoldingFunction[EOR] = NULL;
+ AssignmentFoldingFunction[ELAND] = NULL;
+ AssignmentFoldingFunction[ELOR] = NULL;
+ AssignmentFoldingFunction[EASS] = NULL;
+ AssignmentFoldingFunction[EMULASS] = CInt64_Mul;
+ AssignmentFoldingFunction[EDIVASS] = CInt64_Mul;
+ AssignmentFoldingFunction[EMODASS] = NULL;
+ AssignmentFoldingFunction[EADDASS] = CInt64_Add;
+ AssignmentFoldingFunction[ESUBASS] = CInt64_Add;
+ AssignmentFoldingFunction[ESHLASS] = CInt64_Add;
+ AssignmentFoldingFunction[ESHRASS] = CInt64_Add;
+ AssignmentFoldingFunction[EANDASS] = CInt64_And;
+ AssignmentFoldingFunction[EXORASS] = CInt64_Xor;
+ AssignmentFoldingFunction[EORASS] = CInt64_Or;
+ AssignmentFoldingFunction[ECOMMA] = NULL;
+ AssignmentFoldingFunction[EPMODULO] = NULL;
+ AssignmentFoldingFunction[EROTL] = NULL;
+ AssignmentFoldingFunction[EROTR] = NULL;
+ AssignmentFoldingFunction[EBCLR] = NULL;
+ AssignmentFoldingFunction[EBTST] = NULL;
+ AssignmentFoldingFunction[EBSET] = NULL;
+ AssignmentFoldingFunction[ETYPCON] = NULL;
+ AssignmentFoldingFunction[EBITFIELD] = NULL;
+ AssignmentFoldingFunction[EINTCONST] = NULL;
+ AssignmentFoldingFunction[EFLOATCONST] = NULL;
+ AssignmentFoldingFunction[ESTRINGCONST] = NULL;
+ AssignmentFoldingFunction[ECOND] = NULL;
+ AssignmentFoldingFunction[EFUNCCALL] = NULL;
+ AssignmentFoldingFunction[EFUNCCALLP] = NULL;
+ AssignmentFoldingFunction[EOBJREF] = NULL;
+ AssignmentFoldingFunction[EMFPOINTER] = NULL;
+ AssignmentFoldingFunction[ENULLCHECK] = NULL;
+ AssignmentFoldingFunction[EPRECOMP] = NULL;
+ AssignmentFoldingFunction[ETEMP] = NULL;
+ AssignmentFoldingFunction[EARGOBJ] = NULL;
+ AssignmentFoldingFunction[ELOCOBJ] = NULL;
+ AssignmentFoldingFunction[ELABEL] = NULL;
+ AssignmentFoldingFunction[ESETCONST] = NULL;
+ AssignmentFoldingFunction[ENEWEXCEPTION] = NULL;
+ AssignmentFoldingFunction[ENEWEXCEPTIONARRAY] = NULL;
+ AssignmentFoldingFunction[EOBJLIST] = NULL;
+ AssignmentFoldingFunction[EMEMBER] = NULL;
+ AssignmentFoldingFunction[ETEMPLDEP] = NULL;
+ AssignmentFoldingFunction[EINSTRUCTION] = NULL;
+ AssignmentFoldingFunction[EDEFINE] = NULL;
+ AssignmentFoldingFunction[EREUSE] = NULL;
+ AssignmentFoldingFunction[EASSBLK] = NULL;
+ AssignmentFoldingFunction[EVECTOR128CONST] = NULL;
+ AssignmentFoldingFunction[ECONDASS] = NULL;
+}
+
+static void UpdateUseForOtherSelfAssignment(IROLinear *a, IROLinear *b, Type *type) {
+ CInt64 val;
+ IROLinear *father;
+ IROLinear *repl;
+ IROLinear *newdiadic;
+
+ val = IRO_GetSelfAssignmentVal(b);
+ if ((father = IRO_LocateFather(a)) && father->type == IROLinearOp2Arg && IRO_IsIntConstant(father->u.diadic.right)) {
+ CInt64 var_30 = father->u.diadic.right->u.node->data.intval;
+ if (AssignmentFoldingFunction[b->nodetype] && ((father->nodetype == b->nodetype) || (father->nodetype == IRO_NonAssignmentOp[b->nodetype]))) {
+ CInt64 v;
+ CInt64 folded;
+ CInt64_SetLong(&v, b->rtype->size * 8);
+ folded = AssignmentFoldingFunction[b->nodetype](var_30, val);
+ if (b->nodetype == ESHRASS && !is_unsigned(b->rtype)) {
+ if (CInt64_LessU(var_30, v) && CInt64_LessU(val, v)) {
+ if (CInt64_GreaterEqualU(folded, v))
+ folded = CInt64_Sub(v, cint64_one);
+ father->u.diadic.right->u.node->data.intval = folded;
+ return;
+ }
+ } else {
+ father->u.diadic.right->u.node->data.intval = folded;
+ return;
+ }
+ } else {
+ switch (b->nodetype) {
+ case EMULASS:
+ if (father->nodetype == ESHL || father->nodetype == ESHLASS) {
+ SInt32 powvalue;
+ if (IRO_IsPow2(b->u.diadic.right, &powvalue)) {
+ if (powvalue > 0) {
+ CInt64 v;
+ CInt64_SetLong(&v, powvalue);
+ father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30);
+ }
+ } else {
+ father->nodetype = (father->nodetype == ESHL) ? EMUL : EMULASS;
+ var_30 = CInt64_Shl(cint64_one, var_30);
+ father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
+ }
+ return;
+ }
+ break;
+ case EDIVASS:
+ if ((father->nodetype == ESHR || father->nodetype == ESHRASS) && is_unsigned(father->rtype)) {
+ SInt32 powvalue;
+ if (IRO_IsPow2(b->u.diadic.right, &powvalue)) {
+ if (powvalue > 0) {
+ CInt64 v;
+ CInt64_SetLong(&v, powvalue);
+ father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30);
+ }
+ } else {
+ father->nodetype = (father->nodetype == ESHR) ? EDIV : EDIVASS;
+ var_30 = CInt64_Shl(cint64_one, var_30);
+ father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
+ }
+ return;
+ }
+ break;
+ case ESHLASS:
+ if (father->nodetype == EMUL || father->nodetype == EMULASS) {
+ SInt32 powvalue;
+ if (IRO_IsPow2(father->u.diadic.right, &powvalue)) {
+ if (powvalue > 0) {
+ CInt64 v;
+ father->nodetype = (father->nodetype == EMUL) ? ESHL : ESHLASS;
+ CInt64_SetLong(&v, powvalue);
+ father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val);
+ }
+ } else {
+ val = CInt64_Shl(cint64_one, val);
+ father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
+ }
+ return;
+ } else if (father->nodetype == ESHR || father->nodetype == ESHRASS) {
+ if (CInt64_Equal(var_30, val) && is_unsigned(father->rtype)) {
+ father->nodetype = (father->nodetype == ESHR) ? EAND : EANDASS;
+ if (father->rtype->size < 8) {
+ CInt64 v;
+ CInt64_SetLong(&v, 64 - (father->rtype->size * 8));
+ val = CInt64_Add(val, v);
+ }
+ father->u.diadic.right->u.node->data.intval = CInt64_ShrU(cint64_negone, val);
+ return;
+ }
+ }
+ break;
+ case ESHRASS:
+ if ((father->nodetype == EDIV || father->nodetype == EDIVASS) && is_unsigned(father->rtype)) {
+ SInt32 powvalue;
+ if (IRO_IsPow2(father->u.diadic.right, &powvalue)) {
+ if (powvalue > 0) {
+ CInt64 v;
+ father->nodetype = (father->nodetype == EDIV) ? ESHR : ESHRASS;
+ CInt64_SetLong(&v, powvalue);
+ father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val);
+ }
+ } else {
+ val = CInt64_Shl(cint64_one, val);
+ father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val);
+ }
+ return;
+ } else if (father->nodetype == ESHL || father->nodetype == ESHLASS) {
+ if (CInt64_Equal(var_30, val)) {
+ father->nodetype = (father->nodetype == ESHL) ? EAND : EANDASS;
+ father->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_negone, val);
+ return;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ repl = IRO_NewIntConst(val, type);
+ newdiadic = IRO_NewLinear(IROLinearOp2Arg);
+ newdiadic->index = ++IRO_NumLinear;
+ newdiadic->nodetype = IRO_NonAssignmentOp[b->nodetype];
+ newdiadic->u.diadic.left = a;
+ newdiadic->u.diadic.right = repl;
+ newdiadic->rtype = a->rtype;
+ repl->next = newdiadic;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(a, newdiadic);
+ IRO_PasteAfter(repl, newdiadic, a);
+}
+
+static Boolean PropagateIncsAndDecs(void) {
+ IRODef *def;
+ Boolean result;
+
+ result = 0;
+ def = FirstDef;
+ while (def) {
+ if (
+ def->linear &&
+ def->x1C &&
+ IsIncOrDec(def->linear) &&
+ !(def->linear->flags & IROLF_Reffed) &&
+ (IS_TYPE_INT_OR_ENUM(def->linear->rtype) || IS_TYPE_POINTER_ONLY(def->linear->rtype)) &&
+ IRO_TypesEqual(def->linear->rtype, def->var->object->type) &&
+ !is_volatile_object(def->var->object)
+ ) {
+ IROUse *use;
+ IROUse *use2;
+ IROLinear *father;
+ CInt64 val;
+ SInt32 i;
+ Type *type;
+
+ for (use = def->var->uses, i = 0; use; use = use->varnext) {
+ if (Bv_IsBitSet(def->index, use->x18)) {
+ if (
+ use->x1C == 1 &&
+ use->linear->type == IROLinearOperand &&
+ (father = IRO_LocateFather(use->linear)) &&
+ IRO_IsVariable(father) &&
+ IRO_TypesEqual(def->linear->rtype, father->rtype)
+ ) {
+ if (use->linear->flags & IROLF_Assigned) {
+ if (!((father = IRO_LocateFather(father)) && IsIncOrDec(father) && !(father->flags & IROLF_Reffed)))
+ goto nextDef;
+ }
+ i++;
+ } else {
+ goto nextDef;
+ }
+ }
+ }
+
+ if (i == def->x18) {
+ for (use = def->var->uses; use; use = use->varnext) {
+ if (Bv_IsBitSet(def->index, use->x18)) {
+ IRO_Dump("Propagating inc/dec from %d to %d\n", def->linear->index, use->linear->index);
+ father = IRO_LocateFather(use->linear);
+ val = IRO_GetSelfAssignmentVal(def->linear);
+ type = def->linear->rtype;
+ if (IS_TYPE_POINTER_ONLY(def->linear->rtype))
+ type = TYPE(&stunsignedlong);
+ UpdateUse(father, val, type);
+
+ result = 1;
+ for (use2 = def->var->uses; use2; use2 = use2->varnext) {
+ if (use2->linear == def->linear->u.monadic->u.diadic.left) {
+ use->x1C = use2->x1C;
+ Bv_Copy(use2->x18, use->x18);
+ break;
+ }
+ }
+ }
+ }
+ def->x18 = 0;
+ IRO_NopNonSideEffects(def->linear, -1);
+ def->linear->type = IROLinearNop;
+ IRO_Dump("Removing deadddd assignment %d\n", def->linear->index);
+ }
+ }
+ nextDef:
+ def = def->globalnext;
+ }
+
+ return result;
+}
+
+static Boolean PropagateOtherSelfAssignments(void) {
+ IRODef *def;
+ Boolean result;
+
+ result = 0;
+
+ def = FirstDef;
+ while (def) {
+ if (
+ def->linear &&
+ def->x1C &&
+ IsOtherSelfAssignment(def->linear) &&
+ !(def->linear->flags & IROLF_Reffed) &&
+ IS_TYPE_INT_OR_ENUM(def->linear->rtype) &&
+ IRO_TypesEqual(def->linear->rtype, def->var->object->type) &&
+ !is_volatile_object(def->var->object)
+ )
+ {
+ IROUse *use;
+ IROUse *use2;
+ IROLinear *father;
+ SInt32 i;
+ Type *type;
+
+ for (use = def->var->uses, i = 0; use; use = use->varnext) {
+ if (Bv_IsBitSet(def->index, use->x18)) {
+ if (
+ use->x1C == 1 &&
+ use->linear->type == IROLinearOperand &&
+ (father = IRO_LocateFather(use->linear)) &&
+ IRO_IsVariable(father) &&
+ IRO_TypesEqual(def->linear->rtype, father->rtype)
+ ) {
+ if (use->linear->flags & IROLF_Assigned) {
+ if (!((father = IRO_LocateFather(father)) && IsOtherSelfAssignment(father) && (father->nodetype == def->linear->nodetype) && !(father->flags & IROLF_Reffed)))
+ goto nextDef;
+ }
+ i++;
+ } else {
+ goto nextDef;
+ }
+ }
+ }
+
+ if (i == def->x18) {
+ for (use = def->var->uses; use; use = use->varnext) {
+ if (Bv_IsBitSet(def->index, use->x18)) {
+ IRO_Dump("Propagating self assignment from %d to %d\n", def->linear->index, use->linear->index);
+ father = IRO_LocateFather(use->linear);
+ UpdateUseForOtherSelfAssignment(father, def->linear, def->linear->rtype);
+
+ result = 1;
+ for (use2 = def->var->uses; use2; use2 = use2->varnext) {
+ if (use2->linear == def->linear->u.monadic->u.diadic.left) {
+ use->x1C = use2->x1C;
+ Bv_Copy(use2->x18, use->x18);
+ break;
+ }
+ }
+ }
+ }
+ def->x18 = 0;
+ IRO_NopNonSideEffects(def->linear, -1);
+ def->linear->type = IROLinearNop;
+ IRO_Dump("Removing deadddd assignment %d\n", def->linear->index);
+ }
+ }
+ nextDef:
+ def = def->globalnext;
+ }
+
+ return result;
+}
+
+static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) {
+ IROListNode *list;
+ IROLinear *nd;
+ Object *obj;
+ VarRecord *var;
+ Boolean foundObjRef;
+ IROListNode *scan;
+ IRODef *def;
+ Boolean found;
+
+ found = 0;
+
+ if (linear && copts.opt_pointer_analysis && linear->pointsToFunction && FunctionName) {
+ IROListNode *resultList;
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, linear, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ found = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ break;
+ }
+ }
+
+ if (!foundObjRef) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ while (list) {
+ 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);
+ var = IRO_FindVar(obj, 1, 1);
+#line 1424
+ CError_ASSERT(var != NULL);
+
+ for (def = var->defs; def; def = def->varnext) {
+ if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) {
+ def->x18++;
+ Bv_SetBit(def->index, MightReachAnyUse);
+ }
+ }
+ }
+ }
+ list = list->nextList;
+ }
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ found = 1;
+ }
+ } else {
+ found = 1;
+ }
+
+ if (found) {
+ Bv_Copy(Reaches, a);
+ Bv_And(b, a);
+ Bv_Or(a, MightReachAnyUse);
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
+ def->x18++;
+ }
+ }
+}
+
+static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b) {
+ ObjectList *olist;
+ IROLinear *funcnd;
+ IROListNode *list;
+ IROLinear *nd;
+ Object *obj;
+ VarRecord *var;
+ Boolean foundObjRef;
+ IROListNode *scan;
+ IRODef *def;
+ Boolean found;
+
+ found = 0;
+
+ if ((funcnd = linear->u.funccall.linear8) && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) {
+ IROListNode *resultList;
+ ObjectList *depsList;
+
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList);
+ if (resultList) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ found = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = nd->u.node->data.objref;
+#line 1522
+ CError_ASSERT(obj != NULL);
+
+ depsList = NULL;
+ PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList);
+ for (olist = depsList; olist; olist = olist->next) {
+ if (!olist->object) {
+ found = 1;
+ break;
+ }
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+
+ if (found)
+ break;
+ }
+ }
+
+ if (!foundObjRef)
+ found = 1;
+ if (found)
+ break;
+ }
+
+ if (!found) {
+ for (list = resultList; list; list = list->nextList) {
+ 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;
+ depsList = NULL;
+ PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList);
+
+ for (olist = depsList; olist; olist = olist->next) {
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 1573
+ CError_ASSERT(var != NULL);
+
+ for (def = var->defs; def; def = def->varnext) {
+ if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) {
+ def->x18++;
+ Bv_SetBit(def->index, MightReachAnyUse);
+ }
+ }
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ found = 1;
+ }
+ } else {
+ found = 1;
+ }
+
+ if (found) {
+ Bv_Copy(Reaches, a);
+ Bv_And(b, a);
+ Bv_Or(a, MightReachAnyUse);
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
+ def->x18++;
+ }
+ }
+
+ if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
+ IRO_WalkExcActions(linear->stmt->dobjstack, MarkUses);
+}
+
+static Boolean UseOfVarIsInsideASimpleDefOfVar(IROUse *use) {
+ VarRecord *var;
+ VarRecord *varAss;
+ IROLinear *nd;
+ IROLinear *nd2;
+
+ if ((var = use->var)) {
+ if ((nd = use->linear) && (nd->flags & IROLF_4000))
+ return 0;
+
+ while (nd && (nd->flags & IROLF_Reffed))
+ nd = nd->next;
+
+ if (
+ nd &&
+ IRO_IsAssignment(nd) &&
+ (varAss = IRO_FindAssigned(nd)) &&
+ varAss == var &&
+ !IRO_HasSideEffect((nd->type == IROLinearOp1Arg) ? nd->u.monadic : nd->u.diadic.left) &&
+ (!(nd2 = (nd->type == IROLinearOp1Arg) ? NULL : nd->u.diadic.right) || !IRO_HasSideEffect(nd2))
+ ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static Boolean AllLoopDefUsesAreInSimpleLoopDefs(IRODef *def) {
+ VarRecord *var;
+ IRODef *scan;
+ IROUse *use;
+
+ if ((var = def->var)) {
+ for (scan = var->defs; scan; scan = scan->varnext) {
+ if (scan->node && scan->node->loopdepth) {
+ for (use = var->uses; use; use = use->varnext) {
+ if (Bv_IsBitSet(scan->index, use->x18)) {
+ if (!use->node || !use->node->loopdepth || !UseOfVarIsInsideASimpleDefOfVar(use))
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void MarkRemovableLoopDefs(void) {
+ IRODef *def;
+ IRODef *scan;
+
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (!def->x1A && !def->x1B && def->node && def->node->loopdepth && !def->x1D &&
+ AllLoopDefUsesAreInSimpleLoopDefs(def) && def->var) {
+ for (scan = def->var->defs; scan; scan = scan->varnext) {
+ if (scan->node && scan->node->loopdepth)
+ scan->x1D = 1;
+ }
+ }
+ }
+}
+
+static Boolean EliminateReffedDeadStore(IRODef *def) {
+ Boolean isPostIncOrDec;
+ IROLinear *nd;
+ Boolean result;
+
+ nd = def->linear;
+ isPostIncOrDec = (nd->type == IROLinearOp1Arg) && (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC);
+
+ result = IRO_LocateFather(nd) != NULL;
+ if (result && IRO_IsAssignment(nd) && IRO_IsModifyOp[nd->nodetype])
+ result = IRO_TransformSelfAssignmentToAssignment(nd);
+ result = result && (nd->type == IROLinearOp2Arg) && (nd->nodetype == EASS);
+
+ if (result) {
+ def->x18 = 0;
+ IRO_Dump("Removing referenced dead assignment %d\n", nd->index);
+
+ if (isPostIncOrDec) {
+ IRO_NopNonSideEffects(nd->u.diadic.right, 0);
+ nd->type = IROLinearNop;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.left);
+ } else {
+ IRO_NopNonSideEffects(nd->u.diadic.left, 0);
+ nd->type = IROLinearNop;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.right);
+ }
+ }
+
+ return result;
+}
+
+Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation) {
+ Boolean result;
+ IRODef *gdef;
+ IROUse *guse;
+ IRODef *def;
+ IROUse *use;
+ IRONode *node;
+ IROLinear *nd;
+ VarRecord *var;
+ Boolean flag;
+ BitVector *bv3;
+ BitVector *bv2;
+ BitVector *bv;
+ int i;
+
+ FindDefsAndUses();
+
+ IRO_CheckForUserBreak();
+
+ for (use = IRO_FirstVarUse; use; use = use->globalnext)
+ Bv_AllocVector(&use->x18, NumDefs);
+ Bv_AllocVector(&MightReachAnyUse, NumDefs);
+ Bv_AllocVector(&bv, NumDefs);
+
+ IRO_CheckForUserBreak();
+
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->x1A || def->x1B)
+ Bv_SetBit(def->index, bv);
+ }
+
+ Bv_AllocVector(&bv2, NumDefs);
+ gdef = FirstDef;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ Bv_AllocVector(&node->x16, NumDefs);
+ Bv_AllocVector(&node->x1E, NumDefs);
+ Bv_AllocVector(&node->x22, NumDefs);
+ Bv_AllocVector(&node->x1A, NumDefs);
+
+ for (nd = node->first; nd; nd = nd->next) {
+ while (gdef && gdef->linear == nd) {
+ Bv_SetBit(gdef->index, node->x1E);
+ if (gdef->x1C) {
+ for (def = gdef->var->defs; def; def = def->varnext) {
+ if (def != gdef) {
+ Bv_SetBit(def->index, node->x22);
+ Bv_ClearBit(def->index, node->x1E);
+ }
+ }
+ }
+ gdef = gdef->globalnext;
+ }
+ if (nd == node->last)
+ break;
+ }
+
+ if (node->numpred)
+ Bv_Set(node->x16);
+ Bv_Copy(node->x1E, node->x1A);
+ IRO_CheckForUserBreak();
+ }
+
+ Bv_AllocVector(&bv3, NumDefs);
+
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ Bv_Clear(node->x16);
+ if (node->numpred) {
+ for (i = 0; i < node->numpred; i++)
+ Bv_Or(IRO_NodeTable[node->pred[i]]->x1A, node->x16);
+ } else if (node == IRO_FirstNode) {
+ for (var = IRO_FirstVar; var; var = var->next)
+ Bv_SetBit(var->defs->index, node->x16);
+ }
+ Bv_Copy(node->x16, bv3);
+ Bv_Minus(node->x22, bv3);
+ Bv_Or(node->x1E, bv3);
+ if (!Bv_Compare(bv3, node->x1A)) {
+ Bv_Copy(bv3, node->x1A);
+ flag = 1;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+ } while (flag);
+
+ gdef = FirstDef;
+ guse = IRO_FirstVarUse;
+ Bv_AllocVector(&Reaches, NumDefs);
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ Bv_Copy(node->x16, Reaches);
+ nd = node->first;
+ while (1) {
+ while (guse && guse->linear == nd) {
+ for (def = guse->var->defs; def; def = def->varnext) {
+ if (Bv_IsBitSet(def->index, Reaches)) {
+ Bv_SetBit(def->index, guse->x18);
+ Bv_SetBit(def->index, MightReachAnyUse);
+ def->x18++;
+ guse->x1C++;
+ }
+ }
+ guse = guse->globalnext;
+ }
+
+ if (nd->type == IROLinearFunccall) {
+ MarkUsesByFunctionCall(nd, bv2, bv);
+ } else if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd)) {
+ MarkUsesByIndirect(nd, bv2, bv);
+ } else if ((nd->type == IROLinearFunccall) ||
+ (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd))) {
+ Bv_Copy(Reaches, bv2);
+ Bv_And(bv, bv2);
+ Bv_Or(bv2, MightReachAnyUse);
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches)))
+ def->x18++;
+ }
+ if (nd->type == IROLinearFunccall && nd->stmt && IRO_FunctionCallMightThrowException(nd))
+ IRO_WalkExcActions(nd->stmt->dobjstack, MarkUses);
+ }
+
+ if (nd->type == IROLinearAsm) {
+ IAEffects effects;
+ CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects);
+ if (effects.x2) {
+ Bv_Copy(Reaches, bv2);
+ Bv_And(bv, bv2);
+ Bv_Or(bv2, MightReachAnyUse);
+ }
+ }
+
+ if (nd->type == IROLinearReturn || nd->type == IROLinearEnd) {
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->x1A && Bv_IsBitSet(def->index, Reaches)) {
+ Bv_SetBit(def->index, MightReachAnyUse);
+ def->x18++;
+ }
+ }
+ }
+
+ while (gdef && gdef->linear == nd) {
+ if (gdef->x1C) {
+ for (def = gdef->var->defs; def; def = def->varnext)
+ Bv_ClearBit(def->index, Reaches);
+ }
+ Bv_SetBit(gdef->index, Reaches);
+ gdef = gdef->globalnext;
+ }
+
+ if (nd == node->last)
+ break;
+ nd = nd->next;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+
+ result = 0;
+
+ if (optDeadAssignments) {
+ MarkRemovableLoopDefs();
+ for (def = FirstDef; def; def = def->globalnext) {
+ if (def->linear &&
+ (!Bv_IsBitSet(def->index, MightReachAnyUse) || def->x1D) &&
+ (copts.opt_pointer_analysis || !def->x1B) &&
+ def->linear->type != IROLinearAsm &&
+ (!def->linear->rtype || !CParser_IsVolatile(def->linear->rtype, def->linear->nodeflags & ENODE_FLAG_QUALS)) &&
+ !is_volatile_object(def->var->object)
+ ) {
+ if (!(def->linear->flags & IROLF_Reffed)) {
+ def->x18 = 0;
+ IRO_NopNonSideEffects(def->linear, -1);
+ def->linear->type = IROLinearNop;
+ IRO_Dump("Removing dead assignment %d\n", def->linear->index);
+ result = 1;
+ } else {
+ result = EliminateReffedDeadStore(def);
+ }
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+
+ if (optPropagation) {
+ while (1) {
+ if (PropagateIncsAndDecs() || PropagateOtherSelfAssignments())
+ result = 1;
+ else
+ break;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+
+ return result;
+}
+
+static IROLinear *GetOperand(IROLinear *nd) {
+ IROLinear *inner;
+
+ if (nd->type == IROLinearOperand)
+ return nd;
+
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) {
+ inner = GetOperand(nd->u.diadic.left);
+ if (!inner)
+ inner = GetOperand(nd->u.diadic.right);
+ return inner;
+ }
+
+ return NULL;
+}
+
+static IROLinear *GetAssigned(IROLinear *nd) {
+ if (!nd)
+ return NULL;
+
+ if (nd->type == IROLinearOp2Arg) {
+ nd = nd->u.diadic.left;
+ } else if (nd->type == IROLinearOp1Arg) {
+ nd = nd->u.monadic;
+ } else {
+#line 2338
+ CError_FATAL();
+ }
+
+ if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) {
+#line 2351
+ CError_FATAL();
+ }
+
+ nd = nd->u.monadic;
+
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD)
+ nd = GetOperand(nd);
+
+ return nd;
+}
+
+static void AddUseToRange(IROUse *use) {
+ IRODef *def;
+
+ Bv_SetBit(use->index, useset);
+ Bv_ClearBit(use->index, alluses);
+
+ for (def = use->var->defs; def; def = def->varnext) {
+ if (Bv_IsBitSet(def->index, alldefs) && (Bv_IsBitSet(def->index, use->x18) || GetAssigned(def->linear) == use->linear))
+ AddDefToRange(def);
+ }
+}
+
+static void AddDefToRange(IRODef *def) {
+ IROUse *use;
+ IROLinear *assigned;
+
+ Bv_SetBit(def->index, defset);
+ Bv_ClearBit(def->index, alldefs);
+
+ for (use = def->var->uses, assigned = GetAssigned(def->linear); use; use = use->varnext) {
+ if (Bv_IsBitSet(use->index, alluses) && (Bv_IsBitSet(def->index, use->x18) || assigned == use->linear))
+ AddUseToRange(use);
+ }
+}
+
+static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) {
+ IROLinear *assigned;
+
+ if (
+ !(assigned = GetAssigned(nd)) ||
+ assigned->type != IROLinearOperand ||
+ assigned->u.node->type != EOBJREF ||
+ assigned->u.node->data.objref != from
+ ) {
+#line 2459
+ CError_FATAL();
+ }
+
+ 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);
+
+ 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();
+ }
+}
+
+static void SplitOffRange(VarRecord *var) {
+ Object *newObj;
+ IRODef *def;
+ IROUse *use;
+
+ IRO_Dump("Splitting range for variable: %d\n", var->index);
+ IRO_DumpBits("Def set: ", defset);
+ IRO_DumpBits("Use set: ", useset);
+ IRO_DumpBits("All defs: ", alldefs);
+ IRO_DumpBits("All uses: ", alluses);
+
+ newObj = create_temp_object(var->object->type);
+ IRO_FindVar(newObj, 1, 1);
+
+ for (def = var->defs; def; def = def->varnext) {
+ if (Bv_IsBitSet(def->index, defset) && def->linear)
+ ReplaceAssigned(def->linear, var->object, newObj);
+ }
+
+ for (use = var->uses; use; use = use->varnext) {
+ if (Bv_IsBitSet(use->index, useset))
+ ReplaceUsed(use->linear, var->object, newObj);
+ }
+}
+
+void IRO_SplitLifetimes(void) {
+ VarRecord *var;
+ SInt32 numVars;
+ IRODef *def;
+ IROUse *use;
+ Boolean flag;
+
+ Bv_AllocVector(&alldefs, NumDefs);
+ Bv_AllocVector(&alluses, NumUses);
+ Bv_AllocVector(&defset, NumDefs);
+ Bv_AllocVector(&useset, NumUses);
+
+ var = IRO_FirstVar;
+ numVars = IRO_NumVars;
+
+ while (var && var->index <= numVars) {
+ if (var->object->datatype == DLOCAL && !is_volatile_object(var->object) && !var->xC && !var->xB && !var->x1E) {
+ Bv_Clear(alldefs);
+ Bv_Clear(alluses);
+
+ for (def = var->defs; def; def = def->varnext) {
+ if (def->linear && def->linear->type == IROLinearAsm)
+ goto skipThisVar;
+ Bv_SetBit(def->index, alldefs);
+ }
+
+ for (use = var->uses; use; use = use->varnext) {
+ if (use->linear && use->linear->type == IROLinearAsm)
+ goto skipThisVar;
+ Bv_SetBit(use->index, alluses);
+ }
+
+ flag = 1;
+ while (1) {
+ Bv_Clear(defset);
+ Bv_Clear(useset);
+
+ def = var->defs;
+ while (def && !Bv_IsBitSet(def->index, alldefs))
+ def = def->varnext;
+
+ if (!def)
+ break;
+
+ AddDefToRange(def);
+ if (Bv_IsEmpty(alldefs))
+ break;
+
+ if (!flag)
+ SplitOffRange(var);
+ flag = 0;
+ }
+ }
+
+ skipThisVar:
+ var = var->next;
+ }
+
+ IRO_CheckForUserBreak();
+}
diff --git a/compiler_and_linker/unsorted/InlineAsmPPC.c b/compiler_and_linker/unsorted/InlineAsmPPC.c
index ead84d7..e6e857b 100644
--- a/compiler_and_linker/unsorted/InlineAsmPPC.c
+++ b/compiler_and_linker/unsorted/InlineAsmPPC.c
@@ -22,11 +22,11 @@
#include "compiler/PCodeUtilities.h"
#include "compiler/StackFrame.h"
#include "compiler/CompilerTools.h"
+#include "compiler/Alias.h"
// TODO: move me
extern int countexceptionactionregisters(ExceptionAction *);
extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *);
-extern void *make_alias(Object *obj, SInt32 offset, SInt32 size);
char asm_alloc_flags[10];
unsigned char sm_section;
@@ -2090,7 +2090,7 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8
dest->data.mem.obj = src->u.obj.obj;
dest->data.mem.offset = src->u.obj.offset;
if (pc->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) {
- pc->_18 = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc));
+ pc->alias = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc));
if (is_volatile_object(dest->data.mem.obj))
pc->flags |= fIsVolatile;
if (OBJ_GET_TARGET_CONST(dest->data.mem.obj))
diff --git a/compiler_and_linker/unsorted/InterferenceGraph.c b/compiler_and_linker/unsorted/InterferenceGraph.c
index e69de29..942a5a0 100644
--- a/compiler_and_linker/unsorted/InterferenceGraph.c
+++ b/compiler_and_linker/unsorted/InterferenceGraph.c
@@ -0,0 +1,404 @@
+#include "compiler/InterferenceGraph.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/BitVectors.h"
+#include "compiler/Coloring.h"
+#include "compiler/LiveInfo.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeListing.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Registers.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/CompilerTools.h"
+
+IGNode **interferencegraph;
+static UInt32 *interferencematrix;
+Boolean coalesced_nregisters;
+static SInt16 *coalesced;
+
+static void makeinterfere(UInt32 a, UInt32 b) {
+ if (a < b)
+ bitvectorsetbit(((b * b) / 2) + a, interferencematrix);
+ else if (a > b)
+ bitvectorsetbit(((a * a) / 2) + b, interferencematrix);
+}
+
+int interferes(UInt32 a, UInt32 b) {
+ if (a < b)
+ return bitvectorgetbit(((b * b) / 2) + a, interferencematrix) > 0;
+ else if (a > b)
+ return bitvectorgetbit(((a * a) / 2) + b, interferencematrix) > 0;
+ else
+ return 0;
+}
+
+static void buildinterferencematrix(void) {
+ UInt32 regs; // r31
+ PCodeBlock *block; // r30
+ PCode *instr; // r29
+ UInt32 *vec; // r28
+ PCodeArg *op;
+ long reg;
+ UInt32 i;
+ UInt32 j;
+
+ regs = used_virtual_registers[coloring_class];
+ interferencematrix = oalloc(4 * ((((regs * regs) / 2) + 31) >> 5));
+ bitvectorinitialize(interferencematrix, (regs * regs) / 2, 0);
+
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; j++)
+ if (i != j)
+ makeinterfere(i, j);
+
+ vec = oalloc(4 * ((regs + 31) >> 5));
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ bitvectorcopy(vec, liveinfo[block->blockIndex].vecC, regs);
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ {
+ reg = op->data.reg.reg;
+ bitvectorclearbit(reg, vec);
+ for (j = 0; j < regs; j++) {
+ if (bitvectorgetbit(j, vec)) {
+ if (
+ (instr->flags & fPCodeFlag10) &&
+ instr->args[0].kind == PCOp_REGISTER &&
+ (char) instr->args[0].arg == coloring_class &&
+ instr->args[1].data.reg.reg == j
+ )
+ continue;
+ makeinterfere(reg, j);
+ }
+ }
+ }
+ op++;
+ }
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectRead)
+ )
+ {
+ reg = op->data.reg.reg;
+ if (bitvectorgetbit(reg, vec) == 0)
+ op->data.reg.effect |= Effect4;
+ bitvectorsetbit(reg, vec);
+ }
+ op++;
+ }
+
+ if (coloring_class == RegClass_GPR) {
+ if (PCODE_FLAG_SET_F(instr) & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag40000)) {
+ if (instr->args[1].data.reg.reg >= n_real_registers[coloring_class])
+ makeinterfere(0, instr->args[1].data.reg.reg);
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag2000000)
+ makeinterfere(instr->args[0].data.reg.reg, instr->args[1].data.reg.reg);
+ } else {
+ switch (instr->op) {
+ 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:
+ case PC_DST:
+ case PC_DSTT:
+ case PC_DSTST:
+ case PC_DSTSTT:
+ if (instr->args[0].data.reg.reg >= n_real_registers[coloring_class])
+ makeinterfere(0, instr->args[0].data.reg.reg);
+ break;
+ }
+ }
+ }
+
+ if (coloring_class == RegClass_GPR && (instr->flags & fPCodeFlag8)) {
+ i = branch_count_volatiles();
+ op = instr->args;
+#line 219
+ CError_ASSERT(instr->argCount != 0);
+
+ while (op->kind != PCOp_REGISTER && !(op->data.reg.effect & EffectWrite)) {
+ i++;
+ op++;
+#line 226
+ CError_ASSERT(i <= instr->argCount);
+ }
+
+ op = instr->args + i;
+ while (i < instr->argCount) {
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) {
+ for (j = 0; j < n_scratch_registers[coloring_class]; j++)
+ makeinterfere(op->data.reg.reg, scratch_registers[coloring_class][j]);
+ }
+ op++;
+ }
+ }
+ }
+ }
+}
+
+static short coalesced_path(short id) {
+ while (id != coalesced[id])
+ id = coalesced[id];
+ return id;
+}
+
+static void coalescenodes(void) {
+ PCodeArg *op;
+ UInt32 regs;
+ PCodeBlock *block;
+ PCode *instr;
+ UInt32 i;
+ short path1;
+ short path2;
+ short node1;
+ short node2;
+
+ regs = used_virtual_registers[coloring_class];
+ coalesced = oalloc(sizeof(SInt16) * regs);
+
+ for (i = 0; i < regs; i++)
+ coalesced[i] = i;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ 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();
+ continue;
+ }
+
+ if (instr->argCount > 2) {
+ if (instr->argCount != 3 || instr->args[2].kind != PCOp_PLACEHOLDEROPERAND) {
+#line 316
+ CError_FATAL();
+ continue;
+ }
+ }
+
+ if (instr->args[0].kind == PCOp_REGISTER && (char) instr->args[0].arg == coloring_class) {
+ path1 = coalesced_path(instr->args[0].data.reg.reg);
+ path2 = coalesced_path(instr->args[1].data.reg.reg);
+ if (path1 == path2) {
+ deletepcode(instr);
+ continue;
+ }
+
+ if (!interferes(path1, path2)) {
+ if (path1 >= n_real_registers[coloring_class] && path2 >= n_real_registers[coloring_class]) {
+ if (path1 < first_fe_temporary_register[coloring_class])
+ continue;
+ if (path1 > last_temporary_register[coloring_class])
+ continue;
+ if (path2 < first_fe_temporary_register[coloring_class])
+ continue;
+ if (path2 > last_temporary_register[coloring_class])
+ continue;
+ }
+
+ node1 = (path2 < path1) ? path2 : path1;
+ node2 = (path2 > path1) ? path2 : path1;
+
+ if (coloring_class == RegClass_GPR && node2 == _CALLER_SP_)
+ continue;
+
+ coalesced[node2] = node1;
+ for (i = 0; i < regs; i++) {
+ if (interferes(node2, i))
+ makeinterfere(node1, i);
+ }
+
+ deletepcode(instr);
+ }
+ }
+ }
+ }
+ }
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ op->data.reg.reg != coalesced[op->data.reg.reg]
+ )
+ op->data.reg.reg = coalesced_path(op->data.reg.reg);
+ op++;
+ }
+ }
+ }
+}
+
+static void buildadjacencyvectors(void) {
+ IGNode *node;
+ UInt32 regs;
+ UInt32 i;
+ UInt32 counter;
+ short *array;
+ short *dest;
+ short *src;
+ UInt32 j;
+
+ regs = used_virtual_registers[coloring_class];
+ interferencegraph = oalloc(sizeof(IGNode *) * regs);
+ array = oalloc(sizeof(short) * regs);
+
+ for (i = 0; i < regs; i++) {
+ counter = 0;
+ for (j = 0; j < regs; j++) {
+ if (interferes(i, j))
+ array[counter++] = j;
+ }
+
+ node = interferencegraph[i] = oalloc(sizeof(IGNode) + sizeof(short) * (counter - 1));
+ memclrw(node, sizeof(IGNode) + sizeof(short) * (counter - 1));
+
+ node->x10 = i;
+ node->x14 = -1;
+ node->arraySize = counter;
+ node->x12 = counter;
+
+ dest = node->array;
+ src = array;
+ for (j = 0; j < counter; j++)
+ *(dest++) = *(src++);
+
+ if (i != coalesced[i]) {
+ node->flags |= fCoalesced;
+ j = coalesced_path(i);
+ interferencegraph[j]->flags |= fCoalescedInto;
+ node->x14 = j;
+ }
+ }
+}
+
+static void eliminatedeadcode(void) {
+ UInt32 regs;
+ PCodeBlock *block;
+ PCode *instr;
+ UInt32 *vec;
+ UInt32 i;
+ PCodeArg *op;
+
+ regs = used_virtual_registers[coloring_class];
+ vec = oalloc(4 * ((regs + 31) >> 5));
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ bitvectorcopy(vec, liveinfo[block->blockIndex].vecC, regs);
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ if (dead(instr, coloring_class, vec)) {
+ deletepcode(instr);
+ continue;
+ }
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ bitvectorclearbit(op->data.reg.reg, vec);
+ op++;
+ }
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectRead)
+ )
+ {
+ int reg = op->data.reg.reg;
+ if (!bitvectorgetbit(reg, vec))
+ op->data.reg.effect |= Effect4;
+ bitvectorsetbit(reg, vec);
+ }
+ op++;
+ }
+ }
+ }
+}
+
+static void findrematerializations(void) {
+ UInt32 regs;
+ UInt32 i;
+ PCodeBlock *block;
+ PCode *instr;
+ PCodeArg *op;
+ IGNode *node;
+
+ regs = used_virtual_registers[coloring_class];
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg >= n_real_registers[coloring_class] &&
+ !(interferencegraph[op->data.reg.reg]->flags & (fPairLow | fPairHigh)) &&
+ !(interferencegraph[op->data.reg.reg]->flags & fIGNode40)
+ )
+ {
+ node = interferencegraph[op->data.reg.reg];
+ if (!node->instr8) {
+ node->instr8 = instr;
+ } else {
+ node->instr8 = NULL;
+ node->flags |= fIGNode40;
+ }
+ }
+ op++;
+ }
+ }
+ }
+
+ for (i = 0; i < regs; i++) {
+ node = interferencegraph[i];
+ if (node->instr8 && !is_location_independent(node->instr8))
+ node->instr8 = NULL;
+ }
+}
+
+void buildinterferencegraph(Object *proc) {
+ int regs = used_virtual_registers[coloring_class];
+
+ computelivevariables(proc);
+ eliminatedeadcode();
+ buildinterferencematrix();
+ if (copts.debuglisting)
+ pclistinterferences(register_class_format[coloring_class], regs);
+ coalescenodes();
+ buildadjacencyvectors();
+ findrematerializations();
+}
diff --git a/compiler_and_linker/unsorted/IrOptimizer.c b/compiler_and_linker/unsorted/IrOptimizer.c
index e69de29..462adf3 100644
--- a/compiler_and_linker/unsorted/IrOptimizer.c
+++ b/compiler_and_linker/unsorted/IrOptimizer.c
@@ -0,0 +1,45 @@
+#include "compiler/IrOptimizer.h"
+#include "compiler/CParser.h"
+
+Boolean DoScalarize;
+Boolean DoLinearize;
+Boolean EarlyReturn;
+Boolean IRO_CPFirstTime;
+Boolean VectorPhaseCalledFromUnroll;
+Boolean IRO_Log;
+static Boolean stIsSetup;
+
+static void CountRefToObject() {
+}
+
+static void CountARef() {
+}
+
+static void CountDoubleInd() {
+}
+
+static void CountUsage() {
+}
+
+Statement *IRO_Optimizer(Object *obj, Statement *stmt) {
+}
+
+void IRO_Setup(void) {
+ static Boolean ENodeArraysHaveBeenInitialized;
+}
+
+void IRO_Cleanup(void) {
+}
+
+void CodeGen_UpdateOptimizerOptions(void) {
+ copts.opt_dead_code = copts.optimizationlevel > 0;
+ copts.opt_propagation = copts.optimizationlevel > 1;
+ copts.opt_common_subs = copts.optimizationlevel > 1;
+ copts.opt_vectorize_loops = copts.optimizationlevel > 2;
+ copts.opt_unroll_loops = copts.optimizationlevel > 2;
+ copts.opt_dead_assignments = copts.optimizationlevel > 2;
+ copts.opt_lifetimes = copts.optimizationlevel > 2;
+ copts.opt_strength_reduction = copts.optimizationlevel > 2;
+ copts.opt_loop_invariants = copts.optimizationlevel > 2;
+ copts._B4 = copts.optimizationlevel > 3;
+}
diff --git a/compiler_and_linker/unsorted/IroBitVect.c b/compiler_and_linker/unsorted/IroBitVect.c
index ecaea04..f243238 100644
--- a/compiler_and_linker/unsorted/IroBitVect.c
+++ b/compiler_and_linker/unsorted/IroBitVect.c
@@ -1,4 +1,4 @@
-#include "compiler/IroBitVect.h"
+#include "compiler/BitVector.h"
#include "compiler/CompilerTools.h"
void Bv_AllocVector(BitVector **bv, UInt32 size) {
diff --git a/compiler_and_linker/unsorted/IroCSE.c b/compiler_and_linker/unsorted/IroCSE.c
index e69de29..e7ad16f 100644
--- a/compiler_and_linker/unsorted/IroCSE.c
+++ b/compiler_and_linker/unsorted/IroCSE.c
@@ -0,0 +1,1039 @@
+#include "compiler/IroCSE.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroSubable.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CInt64.h"
+#include "compiler/CParser.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+
+BitVector *IRO_Depends;
+Boolean IRO_NotSubable;
+Boolean IRO_IsVolatile;
+Boolean IRO_CouldError;
+IROExpr *IRO_FirstExpr;
+IROExpr *IRO_LastExpr;
+SInt32 IRO_NumExprs;
+static Boolean HasVectorOperand;
+
+// forward decls
+static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag);
+
+static void GetDependsOfIndirect(IROLinear *nd) {
+ IROListNode *resultList;
+ IROListNode *next;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *scannd;
+ Object *obj;
+ VarRecord *var;
+ int index;
+ Boolean result;
+ Boolean foundObjRef;
+
+ result = 0;
+
+ if (nd && copts.opt_pointer_analysis && nd->pointsToFunction && FunctionName) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, nd, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ break;
+ }
+ }
+
+ if (!foundObjRef) {
+ result = 1;
+ break;
+ }
+ }
+
+ if (!result) {
+ while (list) {
+ 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);
+ var = IRO_FindVar(obj, 1, 1);
+#line 121
+ CError_ASSERT(var != NULL);
+ index = var->index;
+#line 123
+ CError_ASSERT(index != 0);
+
+ if (is_volatile_object(obj)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+ Bv_SetBit(index, IRO_Depends);
+ }
+ }
+ list = list->nextList;
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result) {
+ nd = nd->u.monadic;
+ if (nd->type == IROLinearOp1Arg && nd->nodetype == EBITFIELD)
+ nd = nd->u.monadic;
+
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) {
+ IRO_BaseTerms = 0;
+ IRO_VarTerms = 0;
+ IRO_DecomposeAddressExpression_Cheap(nd);
+ if (IRO_BaseTerms != 1) {
+ IRO_CouldError = 1;
+ Bv_SetBit(0, IRO_Depends);
+ Bv_Or(IRO_FuncKills, IRO_Depends);
+ }
+ if (IRO_VarTerms)
+ IRO_CouldError = 1;
+ } else {
+ IRO_CouldError = 1;
+ Bv_SetBit(0, IRO_Depends);
+ Bv_Or(IRO_FuncKills, IRO_Depends);
+ }
+ }
+}
+
+static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) {
+ IROLinear *innernd;
+ IROListNode *resultList;
+ IROListNode *next;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *scannd;
+ Object *obj;
+ VarRecord *var;
+ int index;
+ Boolean result;
+ Boolean foundObjRef;
+ ObjectList *olist;
+ ObjectList *depsList;
+
+ result = 0;
+ innernd = nd->u.funccall.linear8;
+
+ if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = scannd->u.node->data.objref;
+#line 234
+ CError_ASSERT(obj != NULL);
+
+ depsList = NULL;
+ PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList);
+
+ for (olist = depsList; olist; olist = olist->next) {
+ if (!olist->object) {
+ result = 1;
+ break;
+ }
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+
+ if (result)
+ break;
+ }
+ }
+
+ if (!foundObjRef)
+ result = 1;
+ if (result)
+ break;
+ }
+
+ if (!result) {
+ for (list = resultList; list; list = list->nextList) {
+ 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;
+
+ depsList = NULL;
+ PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList);
+
+ for (olist = depsList; olist; olist = olist->next) {
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 285
+ CError_ASSERT(var != NULL);
+ index = var->index;
+#line 287
+ CError_ASSERT(index != 0);
+
+ if (is_volatile_object(olist->object)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+ Bv_SetBit(index, IRO_Depends);
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result) {
+ IRO_DependsOnForDataFlow(nd->u.funccall.linear8, 0);
+ Bv_Or(IRO_FuncKills, IRO_Depends);
+
+ for (index = nd->u.funccall.argCount - 1; index >= 0; index--)
+ IRO_DependsOnForDataFlow(nd->u.funccall.args[index], 0);
+ }
+}
+
+static void IRO_DependsOn(IROLinear *linear, Boolean flag) {
+ VarRecord *var;
+ IROLinear *inner;
+
+ if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+
+ if (!IRO_NotSubable) {
+ switch (linear->type) {
+ case IROLinearOperand:
+ if (flag && linear->u.node->type == EOBJREF) {
+ if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) {
+ if (is_volatile_object(var->object)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+ Bv_SetBit(var->index, IRO_Depends);
+ } else {
+ IRO_NotSubable = 1;
+ }
+ }
+ break;
+ case IROLinearOp1Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ IRO_NotSubable = 1;
+ } else {
+ inner = linear->u.monadic;
+ if (linear->nodetype == EINDIRECT) {
+ if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD)
+ inner = inner->u.monadic;
+ if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF)
+ GetDependsOfIndirect(linear);
+ }
+
+ IRO_DependsOn(inner, linear->nodetype == EINDIRECT);
+ }
+ break;
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ IRO_NotSubable = 1;
+ } else {
+ if (linear->nodetype == EDIV || linear->nodetype == EMODULO) {
+ if (IRO_IsIntConstant(linear->u.diadic.right)) {
+ if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero))
+ IRO_CouldError = 1;
+ } else {
+ IRO_CouldError = 1;
+ }
+ }
+
+ IRO_DependsOn(linear->u.diadic.left, flag);
+ IRO_DependsOn(linear->u.diadic.right, flag);
+ }
+ break;
+ case IROLinearOp3Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ IRO_NotSubable = 1;
+ } else {
+ IRO_DependsOn(linear->u.args3.a, flag);
+ IRO_DependsOn(linear->u.args3.b, flag);
+ IRO_DependsOn(linear->u.args3.c, flag);
+ }
+ break;
+ case IROLinearFunccall:
+ IRO_NotSubable = 1;
+ break;
+ default:
+#line 479
+ CError_FATAL();
+ }
+ }
+}
+
+static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag) {
+ VarRecord *var;
+ IROLinear *inner;
+
+ if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+
+ switch (linear->type) {
+ case IROLinearOperand:
+ if (flag && linear->u.node->type == EOBJREF) {
+ if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) {
+ if (is_volatile_object(var->object)) {
+ IRO_IsVolatile = 1;
+ IRO_NotSubable = 1;
+ }
+ Bv_SetBit(var->index, IRO_Depends);
+ } else {
+ IRO_NotSubable = 1;
+ }
+ }
+ break;
+ case IROLinearOp1Arg:
+ if (IRO_IsAssignOp[linear->nodetype])
+ IRO_NotSubable = 1;
+
+ inner = linear->u.monadic;
+ if (linear->nodetype == EINDIRECT) {
+ if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD)
+ inner = inner->u.monadic;
+ if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF)
+ GetDependsOfIndirect(linear);
+ }
+
+ IRO_DependsOnForDataFlow(inner, linear->nodetype == EINDIRECT);
+ break;
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype])
+ IRO_NotSubable = 1;
+
+ if (linear->nodetype == EDIV || linear->nodetype == EMODULO) {
+ if (IRO_IsIntConstant(linear->u.diadic.right)) {
+ if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero))
+ IRO_CouldError = 1;
+ } else {
+ IRO_CouldError = 1;
+ }
+ }
+
+ IRO_DependsOnForDataFlow(linear->u.diadic.left, flag);
+ IRO_DependsOnForDataFlow(linear->u.diadic.right, flag);
+ break;
+ case IROLinearOp3Arg:
+ if (IRO_IsAssignOp[linear->nodetype])
+ IRO_NotSubable = 1;
+
+ IRO_DependsOnForDataFlow(linear->u.args3.a, flag);
+ IRO_DependsOnForDataFlow(linear->u.args3.b, flag);
+ IRO_DependsOnForDataFlow(linear->u.args3.c, flag);
+ break;
+ case IROLinearFunccall:
+ IRO_NotSubable = 1;
+ GetDependsOfFunctionCallForDataFlow(linear);
+ break;
+ default:
+#line 650
+ CError_FATAL();
+ }
+}
+
+void IRO_FindDepends_NoAlloc(IROLinear *linear) {
+ Bv_Clear(IRO_Depends);
+ IRO_CouldError = 0;
+ IRO_NotSubable = 0;
+ IRO_IsVolatile = 0;
+ IRO_DependsOnForDataFlow(linear, 0);
+}
+
+void IRO_FindDepends(IROLinear *linear) {
+ Bv_AllocVector(&IRO_Depends, IRO_NumVars + 1);
+ IRO_CouldError = 0;
+ IRO_NotSubable = 0;
+ IRO_DependsOn(linear, 0);
+}
+
+static void VecAct(IROLinear *linear, Boolean isFirst) {
+ if (!isFirst && (linear->flags & IROLF_VecOpBase))
+ HasVectorOperand = 1;
+}
+
+static Boolean IRO_DoesNotHaveVectorOperand(IROLinear *linear) {
+ HasVectorOperand = 0;
+ IRO_WalkTree(linear, VecAct);
+ return HasVectorOperand == 0;
+}
+
+static void IRO_AddExpression(IROLinear *linear, IRONode *node, Boolean flag) {
+ IROExpr *expr;
+
+ if ((linear->flags & IROLF_Reffed) && IRO_IsSubableExpression(linear) && IRO_DoesNotHaveVectorOperand(linear)) {
+ expr = oalloc(sizeof(IROExpr));
+ expr->x0 = 0;
+ expr->index = ++IRO_NumExprs;
+ expr->linear = linear;
+ expr->x8 = NULL;
+ expr->node = node;
+ IRO_FindDepends(linear);
+ expr->depends = IRO_Depends;
+ expr->notSubable = IRO_NotSubable;
+ expr->couldError = IRO_CouldError;
+ expr->next = NULL;
+ expr->x14 = NULL;
+ if (IRO_FirstExpr)
+ IRO_LastExpr->next = expr;
+ else
+ IRO_FirstExpr = expr;
+ IRO_LastExpr = expr;
+ linear->expr = expr;
+ }
+}
+
+void IRO_FindExpressions(BitVector *bv, Boolean flag) {
+ IROLinear *nd;
+ IRONode *fnode;
+
+ IRO_FirstExpr = IRO_LastExpr = NULL;
+ IRO_NumExprs = 0;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (!bv || Bv_IsBitSet(fnode->index, bv)) {
+ for (nd = fnode->first; nd; nd = nd->next) {
+ nd->expr = NULL;
+ IRO_AddExpression(nd, fnode, flag);
+ if (nd == fnode->last)
+ break;
+ }
+ } else {
+ for (nd = fnode->first; nd; nd = nd->next) {
+ nd->expr = NULL;
+ if (nd == fnode->last)
+ break;
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+void IRO_RemoveExpr(IROExpr *expr) {
+ IROExpr *prev;
+ IROExpr *scan;
+
+ scan = IRO_FirstExpr;
+ prev = NULL;
+ while (scan != expr) {
+ prev = scan;
+ scan = scan->next;
+#line 809
+ CError_ASSERT(scan);
+ }
+
+ expr->linear->expr = NULL;
+ if (prev)
+ prev->next = expr->next;
+ else
+ IRO_FirstExpr = expr->next;
+}
+
+static void GetExprKillsByIndirectAssignment(IROLinear *linear) {
+ IROLinear *inner;
+ IROListNode *resultList;
+ IROListNode *next;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *scannd;
+ Object *obj;
+ VarRecord *var;
+ int index;
+ Boolean result;
+ Boolean foundObjRef;
+ IROExpr *expr;
+
+ result = 0;
+ if (linear->type == IROLinearOp2Arg)
+ linear = linear->u.diadic.left;
+ else
+ linear = linear->u.monadic;
+
+ if (
+ linear &&
+ linear->type == IROLinearOp1Arg &&
+ linear->nodetype == EINDIRECT &&
+ (inner = linear->u.monadic) &&
+ copts.opt_pointer_analysis &&
+ inner->pointsToFunction &&
+ FunctionName
+ ) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ break;
+ }
+ }
+
+ if (!foundObjRef) {
+ result = 1;
+ break;
+ }
+ }
+
+ if (!result) {
+ while (list) {
+ 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);
+ var = IRO_FindVar(obj, 1, 1);
+#line 895
+ CError_ASSERT(var != NULL);
+ index = var->index;
+
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_IsBitSet(index, expr->depends))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ }
+ }
+ list = list->nextList;
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result) {
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_BitsInCommon(expr->depends, IRO_FuncKills))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ }
+}
+
+static void GetExprKillsByFunctionCall(IROLinear *funccall) {
+ IROLinear *innernd;
+ IROListNode *resultList;
+ IROListNode *next;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *scannd;
+ Object *obj;
+ VarRecord *var;
+ int index;
+ Boolean result;
+ Boolean foundObjRef;
+ ObjectList *olist;
+ ObjectList *depsList;
+ IROExpr *expr;
+
+ result = 0;
+ innernd = funccall->u.funccall.linear8;
+
+ if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = scannd->u.node->data.objref;
+#line 991
+ CError_ASSERT(obj != NULL);
+
+ depsList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, funccall, &depsList);
+
+ for (olist = depsList; olist; olist = olist->next) {
+ if (!olist->object) {
+ result = 1;
+ break;
+ }
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+
+ if (result)
+ break;
+ }
+ }
+
+ if (!foundObjRef)
+ result = 1;
+ if (result)
+ break;
+ }
+
+ if (!result) {
+ for (list = resultList; list; list = list->nextList) {
+ 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;
+
+ depsList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, funccall, &depsList);
+
+ for (olist = depsList; olist; olist = olist->next) {
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 1042
+ CError_ASSERT(var != NULL);
+ index = var->index;
+#line 1044
+ CError_ASSERT(index != 0);
+
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_IsBitSet(index, expr->depends))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ }
+
+ while (depsList) {
+ olist = depsList->next;
+ IRO_free(depsList);
+ depsList = olist;
+ }
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result) {
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_BitsInCommon(expr->depends, IRO_FuncKills))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ }
+}
+
+static void IRO_GetExprKills(IROLinear *linear) {
+ Bv_Clear(IRO_ExprKills);
+ switch (linear->type) {
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ VarRecord *var;
+ int index;
+
+ var = IRO_FindAssigned(linear);
+ index = 0;
+ if (var)
+ index = var->index;
+ if (!index) {
+ GetExprKillsByIndirectAssignment(linear);
+ } else {
+ IROExpr *expr;
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_IsBitSet(index, expr->depends))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ }
+ }
+ break;
+ case IROLinearAsm: {
+ IROExpr *expr;
+ IRO_GetKills(linear);
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (Bv_BitsInCommon(expr->depends, IRO_VarKills))
+ Bv_SetBit(expr->index, IRO_ExprKills);
+ }
+ break;
+ }
+ case IROLinearFunccall:
+ GetExprKillsByFunctionCall(linear);
+ break;
+ }
+}
+
+void IRO_ComputeAvail(void) {
+ IRONode *node;
+ IROLinear *linear;
+ SInt32 counter;
+ BitVector *bv;
+ Boolean flag;
+
+ counter = 0;
+ node = IRO_FirstNode;
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ Bv_AllocVector(&IRO_ExprKills, IRO_NumExprs + 1);
+
+ while (node) {
+ Bv_AllocVector(&node->x16, IRO_NumExprs);
+ if (node->numpred)
+ Bv_Set(node->x16);
+ Bv_AllocVector(&node->x22, IRO_NumExprs);
+ Bv_AllocVector(&node->x1E, IRO_NumExprs);
+ Bv_AllocVector(&node->x1A, IRO_NumExprs);
+
+ for (linear = node->first; linear; linear = linear->next) {
+ if (linear->expr)
+ Bv_SetBit(linear->expr->index, node->x1E);
+ IRO_GetExprKills(linear);
+ Bv_Or(IRO_ExprKills, node->x22);
+ Bv_Minus(IRO_ExprKills, node->x1E);
+ if (linear == node->last)
+ break;
+
+ if (counter > 250) {
+ IRO_CheckForUserBreak();
+ counter = 0;
+ } else {
+ counter++;
+ }
+ }
+
+ Bv_Copy(node->x16, node->x1A);
+ Bv_Minus(node->x22, node->x1A);
+ Bv_Or(node->x1E, node->x1A);
+ node = node->nextnode;
+ }
+
+ IRO_CheckForUserBreak();
+
+ Bv_AllocVector(&bv, IRO_NumExprs);
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (!node->numpred) {
+ Bv_Clear(bv);
+ } else {
+ UInt16 i;
+ Bv_Set(bv);
+ for (i = 0; i < node->numpred; i++)
+ Bv_And(IRO_NodeTable[node->pred[i]]->x1A, bv);
+ }
+
+ if (!Bv_Compare(bv, node->x16)) {
+ flag = 1;
+ Bv_Copy(bv, node->x16);
+ }
+
+ Bv_Copy(node->x16, node->x1A);
+ Bv_Minus(node->x22, node->x1A);
+ Bv_Or(node->x1E, node->x1A);
+ }
+ IRO_CheckForUserBreak();
+ } while (flag);
+}
+
+static void IRO_MakeReplacementEmbedded(IROExpr *expr) {
+ IROLinear *opnd;
+ IROLinear *ind;
+ IROLinear *ass;
+
+ IRO_GetTemp(expr);
+
+ opnd = IRO_NewLinear(IROLinearOperand);
+ opnd->u.node = create_objectrefnode(expr->x8);
+ opnd->rtype = opnd->u.node->data.objref->type;
+ opnd->index = ++IRO_NumLinear;
+ opnd->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind;
+
+ ind = IRO_NewLinear(IROLinearOp1Arg);
+ ind->nodetype = EINDIRECT;
+ ind->rtype = expr->linear->rtype;
+ ind->u.monadic = opnd;
+ ind->index = ++IRO_NumLinear;
+ ind->flags |= IROLF_Reffed | IROLF_Assigned;
+
+ ass = IRO_NewLinear(IROLinearOp2Arg);
+ ass->nodetype = EASS;
+ ass->u.diadic.left = ind;
+ ass->u.diadic.right = expr->linear;
+ ass->rtype = expr->linear->rtype;
+ ass->index = ++IRO_NumLinear;
+
+ opnd->next = ind;
+ ind->next = ass;
+ IRO_ReplaceReferenceWithNode(expr->linear, ass);
+ IRO_PasteAfter(opnd, ass, expr->linear);
+}
+
+static void IRO_ActUnmarkSubExpressions(IROLinear *linear, Boolean isFirst) {
+ if (isFirst)
+ linear->flags &= ~IROLF_8;
+}
+
+static void CheckCommonSub(IROLinear *linear) {
+ IROExpr *expr;
+
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (expr->linear != linear && !expr->x14) {
+ if (Bv_IsBitSet(expr->index, IRO_Avail) && !expr->notSubable && IRO_ExprsSame(linear, expr->linear)) {
+ IRO_WalkTree(linear, IRO_ActUnmarkSubExpressions);
+ linear->flags |= IROLF_8;
+ linear->expr->x14 = expr;
+ break;
+ }
+ }
+ }
+}
+
+static void MoveCommonSub(IROExpr *expr) {
+ SInt32 best;
+ SInt32 sz1;
+ SInt32 sz2;
+ SInt32 i1;
+ SInt32 i2;
+ IROLinear *scan;
+ IROLinear *array1[64];
+ IROLinear *array2[64];
+ IROExpr *scanexpr;
+
+ sz1 = 0;
+ scan = expr->linear;
+ do {
+ scan = IRO_LocateFather(scan);
+ if (scan) {
+ if (sz1 == 64)
+ return;
+ array1[sz1++] = scan;
+ }
+ } while (scan);
+
+ best = -1;
+ for (scanexpr = IRO_FirstExpr; scanexpr; scanexpr = scanexpr->next) {
+ if (scanexpr->x14 == expr) {
+ sz2 = 0;
+ scan = scanexpr->linear;
+ do {
+ scan = IRO_LocateFather(scan);
+ if (scan) {
+ if (sz2 == 64)
+ return;
+ array2[sz2++] = scan;
+ }
+ } while (scan);
+
+ i1 = sz1;
+ i2 = sz2;
+ while (i1 && i2 && array1[sz1 - 1] == array2[sz2 - 1]) {
+ i1--;
+ i2--;
+ }
+
+ if (i1 != sz1 && i1 > best)
+ best = i1;
+ }
+ }
+
+ if (best < 0) {
+ IRO_MakeReplacementEmbedded(expr);
+ } else {
+ IROLinear *start;
+ IROLinear *comma;
+ IRO_Dump("Moving common sub from node %d to %d\n", expr->linear->index, array1[best]->index);
+ start = IRO_FindStart(array1[best]);
+ IRO_GetTemp(expr);
+ IRO_ReplaceReference(expr->linear, expr->x8, expr->linear);
+ IRO_MoveExpression(expr, start);
+
+ comma = IRO_NewLinear(IROLinearOp2Arg);
+ comma->nodetype = ECOMMA;
+ comma->rtype = array1[best]->rtype;
+ comma->u.diadic.left = IRO_AssignToTemp(expr);
+ comma->u.diadic.right = array1[best];
+ comma->stmt = array1[best]->stmt;
+ IRO_ReplaceReferenceWithNode(array1[best], comma);
+ IRO_PasteAfter(comma, comma, array1[best]);
+ }
+}
+
+static void ReplaceCommonSub(IROLinear *linear) {
+ IROExpr *expr = linear->expr->x14;
+ if (!expr->x8) {
+ MoveCommonSub(expr);
+ if (!expr->x8)
+ return;
+ }
+
+ IRO_Dump("Replacing common sub at %d with %d\n", linear->index, expr->linear->index);
+ IRO_ReplaceReference(linear, expr->x8, linear);
+ IRO_RemoveExpr(linear->expr);
+ IRO_NopOut(linear);
+}
+
+void IRO_CommonSubs(void) {
+ IRONode *node;
+ IROLinear *linear;
+ SInt32 counter;
+
+ counter = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ IRO_Avail = node->x16;
+ linear = node->first;
+ while (1) {
+ if (!linear)
+ break;
+ if (linear->expr && !linear->expr->notSubable)
+ CheckCommonSub(linear);
+ if (linear->expr)
+ Bv_SetBit(linear->expr->index, IRO_Avail);
+ IRO_GetExprKills(linear);
+ Bv_Minus(IRO_ExprKills, IRO_Avail);
+ if (linear == node->last)
+ break;
+ if (counter > 250) {
+ IRO_CheckForUserBreak();
+ counter = 0;
+ } else {
+ counter++;
+ }
+ linear = linear->next;
+ }
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ for (linear = node->first; linear; linear = linear->next) {
+ if (linear->expr && (linear->flags & IROLF_8) && !IRO_HasSideEffect(linear))
+ ReplaceCommonSub(linear);
+ if (linear == node->last)
+ break;
+ if (counter > 250) {
+ IRO_CheckForUserBreak();
+ counter = 0;
+ } else {
+ counter++;
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean CountThisSubableOperandUse() {
+}
+
+static void GetSubableOperandUseCount() {
+}
+
+static void IRO_MakeTopLevelExprForSubableOperand(IROLinear *linear) {
+ IROLinear *copy = IRO_NewLinear(IROLinearOperand);
+ memcpy(copy, linear, sizeof(IROLinear));
+ copy->index = ++IRO_NumLinear;
+
+ if (IRO_FirstLinear && IRO_FirstLinear->type == IROLinearNop)
+ IRO_PasteAfter(copy, copy, IRO_FirstLinear);
+ else
+ IRO_Paste(copy, copy, IRO_FirstLinear);
+}
+
+void IRO_GenerateTopLevelExprsForSubableOperands(void) {
+ IROLinear *nd;
+ IRONode *fnode;
+ VarRecord *var;
+ BitVector *bv;
+
+ Bv_AllocVector(&bv, IRO_NumVars + 1);
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ for (nd = fnode->first; nd; nd = nd->next) {
+ nd->expr = NULL;
+ if ((nd->flags & IROLF_Reffed) && IRO_IsSubableExpression(nd) && IRO_DoesNotHaveVectorOperand(nd)) {
+ if (nd->type == IROLinearOperand && nd->u.node && nd->u.node->type == EOBJREF) {
+ if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) {
+ if (!Bv_IsBitSet(var->index, bv)) {
+ IRO_MakeTopLevelExprForSubableOperand(nd);
+ Bv_SetBit(var->index, bv);
+ }
+ }
+ }
+ }
+
+ if (nd == fnode->last)
+ break;
+ }
+ }
+}
diff --git a/compiler_and_linker/unsorted/IroDump.c b/compiler_and_linker/unsorted/IroDump.c
index e69de29..9472a0f 100644
--- a/compiler_and_linker/unsorted/IroDump.c
+++ b/compiler_and_linker/unsorted/IroDump.c
@@ -0,0 +1,652 @@
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroPropagate.h"
+#include "compiler/IroUtil.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CParser.h"
+#include "compiler/objects.h"
+#include "compiler/IroVars.h"
+#include "compiler/IroCSE.h"
+
+static FILE *DumpFile;
+static char *nodenames[MAXEXPR];
+
+char *IRO_NodeName(ENodeType nodetype) {
+ return nodenames[nodetype];
+}
+
+void IRO_InitializeNodeNamesArray(void) {
+ int i;
+ for (i = 0; i < MAXEXPR; i++)
+ nodenames[i] = "";
+
+ nodenames[EPOSTINC] = "EPOSTINC";
+ nodenames[EPOSTDEC] = "EPOSTDEC";
+ nodenames[EPREINC] = "EPREINC";
+ nodenames[EPREDEC] = "EPREDEC";
+ nodenames[EINDIRECT] = "EINDIRECT";
+ nodenames[EMONMIN] = "EMONMIN";
+ nodenames[EBINNOT] = "EBINNOT";
+ nodenames[ELOGNOT] = "ELOGNOT";
+ nodenames[EFORCELOAD] = "EFORCELOAD";
+ nodenames[EMUL] = "EMUL";
+ nodenames[EMULV] = "EMULV";
+ nodenames[EDIV] = "EDIV";
+ nodenames[EMODULO] = "EMODULO";
+ nodenames[EADDV] = "EADDV";
+ nodenames[ESUBV] = "ESUBV";
+ nodenames[EADD] = "EADD";
+ nodenames[ESUB] = "ESUB";
+ nodenames[ESHL] = "ESHL";
+ nodenames[ESHR] = "ESHR";
+ nodenames[ELESS] = "ELESS";
+ nodenames[EGREATER] = "EGREATER";
+ nodenames[ELESSEQU] = "ELESSEQU";
+ nodenames[EGREATEREQU] = "EGREATEREQU";
+ nodenames[EEQU] = "EEQU";
+ nodenames[ENOTEQU] = "ENOTEQU";
+ nodenames[EAND] = "EAND";
+ nodenames[EXOR] = "EXOR";
+ nodenames[EOR] = "EOR";
+ nodenames[ELAND] = "ELAND";
+ nodenames[ELOR] = "ELOR";
+ nodenames[EASS] = "EASS";
+ nodenames[EMULASS] = "EMULASS";
+ nodenames[EDIVASS] = "EDIVASS";
+ nodenames[EMODASS] = "EMODASS";
+ nodenames[EADDASS] = "EADDASS";
+ nodenames[ESUBASS] = "ESUBASS";
+ nodenames[ESHLASS] = "ESHLASS";
+ nodenames[ESHRASS] = "ESHRASS";
+ nodenames[EANDASS] = "EANDASS";
+ nodenames[EXORASS] = "EXORASS";
+ nodenames[EORASS] = "EORASS";
+ nodenames[ECOMMA] = "ECOMMA";
+ nodenames[EPMODULO] = "EPMODULO";
+ nodenames[EROTL] = "EROTL";
+ nodenames[EROTR] = "EROTR";
+ nodenames[EBCLR] = "EBCLR";
+ nodenames[EBTST] = "EBTST";
+ nodenames[EBSET] = "EBSET";
+ nodenames[ETYPCON] = "ETYPCON";
+ nodenames[EBITFIELD] = "EBITFIELD";
+ nodenames[EINTCONST] = "EINTCONST";
+ nodenames[EFLOATCONST] = "EFLOATCONST";
+ nodenames[ESTRINGCONST] = "ESTRINGCONST";
+ nodenames[ECOND] = "ECOND";
+ nodenames[EFUNCCALL] = "EFUNCCALL";
+ nodenames[EFUNCCALLP] = "EFUNCCALLP";
+ nodenames[EOBJREF] = "EOBJREF";
+ nodenames[EMFPOINTER] = "EMFPOINTER";
+ nodenames[ENULLCHECK] = "ENULLCHECK";
+ nodenames[EPRECOMP] = "EPRECOMP";
+ nodenames[ETEMP] = "ETEMP";
+ nodenames[EARGOBJ] = "EARGOBJ";
+ nodenames[ELOCOBJ] = "ELOCOBJ";
+ nodenames[ELABEL] = "ELABEL";
+ nodenames[ESETCONST] = "ESETCONST";
+ nodenames[ENEWEXCEPTION] = "ENEWEXCEPTION";
+ nodenames[ENEWEXCEPTIONARRAY] = "ENEWEXCEPTIONARRAY";
+ nodenames[EOBJLIST] = "EOBJLIST";
+ nodenames[EMEMBER] = "EMEMBER";
+ nodenames[ETEMPLDEP] = "ETEMPLDEP";
+ nodenames[EINSTRUCTION] = "EINSTRUCTION";
+ nodenames[EDEFINE] = "EDEFINE";
+ nodenames[EREUSE] = "EREUSE";
+ nodenames[EASSBLK] = "EASSBLK";
+ nodenames[EVECTOR128CONST] = "EVECTOR128CONST";
+ nodenames[ECONDASS] = "ECONDASS";
+}
+
+static void DumpENode(ENode *enode) {
+ char buf[64];
+
+ if (IRO_Log) {
+ switch (enode->type) {
+ case EOBJREF:
+ fprintf(DumpFile, "%s", enode->data.objref->name->name);
+ break;
+ case EINTCONST:
+ CInt64_PrintDec(buf, enode->data.intval);
+ fprintf(DumpFile, "%s", buf);
+ break;
+ case EFLOATCONST:
+ fprintf(DumpFile, "%g", enode->data.floatval.value);
+ break;
+ case EVECTOR128CONST:
+ fprintf(DumpFile, "%.8lX%.8lX%.8lX%.8lX",
+ enode->data.vector128val.ul[0],
+ enode->data.vector128val.ul[1],
+ enode->data.vector128val.ul[2],
+ enode->data.vector128val.ul[3]
+ );
+ break;
+ }
+ }
+}
+
+static void DumpLinearNode(IROLinear *linear) {
+ int i;
+
+ if (IRO_Log) {
+ fprintf(DumpFile, "%4d: ", linear->index);
+ switch (linear->type) {
+ case IROLinearNop:
+ fprintf(DumpFile, "Nop");
+ break;
+ case IROLinearOperand:
+ fprintf(DumpFile, "Operand ");
+ DumpENode(linear->u.node);
+ break;
+ case IROLinearOp1Arg:
+ fprintf(DumpFile, "%s %d", nodenames[linear->nodetype], linear->u.monadic->index);
+ break;
+ case IROLinearOp2Arg:
+ fprintf(DumpFile, "%s %d %d", nodenames[linear->nodetype], linear->u.diadic.left->index, linear->u.diadic.right->index);
+ break;
+ case IROLinearGoto:
+ fprintf(DumpFile, "Goto %s", linear->u.label.label->name->name);
+ break;
+ case IROLinearIf:
+ fprintf(DumpFile, "If %d %s", linear->u.label.x4->index, linear->u.label.label->name->name);
+ break;
+ case IROLinearIfNot:
+ fprintf(DumpFile, "IfNot %d %s", linear->u.label.x4->index, linear->u.label.label->name->name);
+ break;
+ case IROLinearReturn:
+ fprintf(DumpFile, "Return ");
+ if (linear->u.monadic)
+ fprintf(DumpFile, "%d", linear->u.monadic->index);
+ break;
+ case IROLinearLabel:
+ fprintf(DumpFile, "Label %s", linear->u.label.label->name->name);
+ break;
+ case IROLinearSwitch:
+ fprintf(DumpFile, "Switch %d", linear->u.swtch.x4->index);
+ break;
+ case IROLinearOp3Arg:
+ fprintf(DumpFile, "%s %d %d %d",
+ nodenames[linear->nodetype],
+ linear->u.args3.a->index,
+ linear->u.args3.b->index,
+ linear->u.args3.c->index);
+ break;
+ case IROLinearFunccall:
+ fprintf(DumpFile, "Funccall %d(", linear->u.funccall.linear8->index);
+ for (i = 0; i < linear->u.funccall.argCount; i++) {
+ fprintf(DumpFile, "%d", linear->u.funccall.args[i]->index);
+ if (i < (linear->u.funccall.argCount - 1))
+ fprintf(DumpFile, ",");
+ }
+ fprintf(DumpFile, ")");
+ break;
+ case IROLinearBeginCatch:
+ fprintf(DumpFile, "BeginCatch %d", linear->u.ctch.linear->index);
+ break;
+ case IROLinearEndCatch:
+ fprintf(DumpFile, "EndCatch %d", linear->u.monadic->index);
+ break;
+ case IROLinearEndCatchDtor:
+ fprintf(DumpFile, "EndCatchDtor %d", linear->u.monadic->index);
+ break;
+ case IROLinearEnd:
+ fprintf(DumpFile, "End");
+ break;
+ }
+
+ if (linear->flags & IROLF_Assigned) fprintf(DumpFile, " <assigned>");
+ if (linear->flags & IROLF_Used) fprintf(DumpFile, " <used>");
+ if (linear->flags & IROLF_Ind) fprintf(DumpFile, " <ind>");
+ if (linear->flags & IROLF_Subs) fprintf(DumpFile, " <subs>");
+ if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " <loop invariant>");
+ if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " <begin loop>");
+ if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " <end loop>");
+ if (linear->flags & IROLF_Ris) fprintf(DumpFile, " <ris>");
+ if (linear->flags & IROLF_Immind) fprintf(DumpFile, " <immind>");
+ if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " <reffed>");
+ if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " <vec op>");
+ if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " <vec op_base>");
+ if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " <counter loop>");
+ if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " <bitfield_indirect>");
+ if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " <could_error>");
+
+ if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS))
+ fprintf(DumpFile, " <volatile>");
+
+ if (IS_LINEAR_ENODE(linear, EOBJREF)) {
+ VarRecord *var = IRO_FindVar(linear->u.node->data.objref, 0, 1);
+ if (var && is_volatile_object(var->object))
+ fprintf(DumpFile, " <volatile obj>");
+ }
+
+ fprintf(DumpFile, "\n");
+ }
+}
+
+static void DumpAct(IROLinear *linear, Boolean isFirst) {
+ if (!isFirst)
+ DumpLinearNode(linear);
+}
+
+void IRO_DumpIntTree(IROLinear *linear) {
+ IRO_WalkTree(linear, DumpAct);
+}
+
+void IRO_DumpLinearList(IROLinear *linear) {
+ if (!IRO_Log)
+ return;
+
+ while (linear) {
+ DumpLinearNode(linear);
+ linear = linear->next;
+ }
+ fprintf(DumpFile, "\n");
+}
+
+static void DumpList(int num, UInt16 *list) {
+ int i;
+
+ if (IRO_Log) {
+ for (i = 0; i < num; i++)
+ fprintf(DumpFile, "%d ", list[i]);
+ fprintf(DumpFile, "\n");
+ }
+}
+
+void IRO_DumpBits(char *name, BitVector *bv) {
+ SInt32 i;
+ SInt32 rangeStart;
+ Boolean inRange = 0;
+ Boolean isFirst = 1;
+
+ if (!IRO_Log)
+ return;
+
+ fprintf(DumpFile, name);
+ if (!bv) {
+ fprintf(DumpFile, "NULL");
+ } else {
+ for (i = 0; i < (bv->size * 32); i++) {
+ if (Bv_IsBitSet(i, bv)) {
+ if (!inRange) {
+ if (!isFirst)
+ fputc(',', DumpFile);
+ isFirst = 0;
+ fprintf(DumpFile, "%d", i);
+ inRange = 1;
+ rangeStart = i;
+ }
+ } else {
+ if (inRange) {
+ inRange = 0;
+ if (i != (rangeStart + 1))
+ fprintf(DumpFile, "-%d", i - 1);
+ }
+ }
+ }
+
+ if (inRange && i != (rangeStart + 1))
+ fprintf(DumpFile, "-%d", i - 1);
+ }
+
+ fprintf(DumpFile, "\n");
+}
+
+void IRO_DumpAfterPhase(char *str, Boolean flag) {
+ if (flag) {
+ IRO_Dump("Dumping function %s after %s \n", FunctionName ? FunctionName->name->name : "Init-code", str);
+ IRO_Dump("--------------------------------------------------------------------------------\n");
+ IRO_DumpFlowgraph();
+ }
+}
+
+void IRO_LogForFunction(char *name) {
+ if (FunctionName) {
+ if (!strcmp(FunctionName->name->name, name))
+ IRO_Log = 1;
+ else
+ IRO_Log = 0;
+ }
+}
+
+void IRO_DumpFlowgraph(void) {
+ IRONode *node;
+ IROLinear *linear;
+
+ if (IRO_Log && DumpFile) {
+ fprintf(DumpFile, "\nFlowgraph\n");
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, node->last->index);
+
+ fprintf(DumpFile, "Succ = ");
+ DumpList(node->numsucc, node->succ);
+ fprintf(DumpFile, "Pred = ");
+ DumpList(node->numpred, node->pred);
+
+ fprintf(DumpFile, "MustReach = %d, MustReach1=%d\n", node->mustreach, node->mustreach1);
+ fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth);
+
+ IRO_DumpBits("Dom: ", node->dom);
+ if ((linear = node->first)) {
+ while (1) {
+ DumpLinearNode(linear);
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+ }
+
+ fprintf(DumpFile, "\n\n");
+ }
+ fprintf(DumpFile, "\n");
+ fflush(DumpFile);
+ }
+}
+
+void IRO_DumpNode(IRONode *node) {
+ IROLinear *linear;
+
+ if (IRO_Log) {
+ if (!DumpFile)
+ return;
+
+ while (node) {
+ fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index,
+ node->last->index);
+
+ fprintf(DumpFile, "Succ = ");
+ DumpList(node->numsucc, node->succ);
+ fprintf(DumpFile, "Pred = ");
+ DumpList(node->numpred, node->pred);
+
+ fprintf(DumpFile, "MustReach = %d MustReach1 = %d\n", node->mustreach, node->mustreach1);
+ fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth);
+
+ IRO_DumpBits("Dom: ", node->dom);
+ if ((linear = node->first)) {
+ while (1) {
+ DumpLinearNode(linear);
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+ }
+
+ fprintf(DumpFile, "\n\n");
+ node = node->nextnode;
+ }
+
+ fprintf(DumpFile, "\n");
+ fflush(DumpFile);
+ }
+}
+
+void IRO_DumpAssignments(void) {
+ IROAssign *assign;
+
+ if (IRO_Log) {
+ fprintf(DumpFile, "\nAssignments\n\n");
+ for (assign = IRO_FirstAssign; assign; assign = assign->next) {
+ fprintf(DumpFile, "%5d ", assign->index);
+ DumpLinearNode(assign->linear);
+ fprintf(DumpFile, "\n");
+ }
+ fprintf(DumpFile, "\n");
+ }
+}
+
+void IRO_DumpVars(void) {
+ VarRecord *var;
+
+ if (IRO_Log) {
+ fprintf(DumpFile, "\nVariables\n");
+ for (var = IRO_FirstVar; var; var = var->next) {
+ fprintf(DumpFile, "%5d %s %s\n", var->index, var->object->name->name, var->xB ? "<addressed>" : "");
+ }
+ fprintf(DumpFile, "\n");
+ }
+}
+
+void IRO_DumpDf(void) {
+ IRONode *node;
+
+ if (IRO_Log) {
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ fprintf(DumpFile, "Node %d\n", node->index);
+ if (node->x16) IRO_DumpBits("In: ", node->x16);
+ if (node->x1E) IRO_DumpBits("Gen: ", node->x1E);
+ if (node->x22) IRO_DumpBits("Kill: ", node->x22);
+ if (node->x1A) IRO_DumpBits("Out: ", node->x1A);
+ if (node->x2A) IRO_DumpBits("AA: ", node->x2A);
+ fprintf(DumpFile, "\n");
+ }
+ fprintf(DumpFile, "\n");
+ }
+}
+
+void IRO_DumpExprs(void) {
+ IROExpr *expr;
+
+ if (IRO_Log) {
+ fprintf(DumpFile, "Expressions\n\n");
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ fprintf(DumpFile, "%4d: %d FN:%d CE:%d NS:%d ", expr->index, expr->linear->index, expr->node->index, expr->couldError, expr->notSubable);
+ IRO_DumpBits("Depends: ", expr->depends);
+ fprintf(DumpFile, "\n");
+ }
+ fprintf(DumpFile, "\n");
+ }
+}
+
+void IRO_SetupDump(void) {
+ if (IRO_Log) {
+ if ((DumpFile = fopen("OPT.LOG", "wt")) == NULL)
+ IRO_Log = 0;
+ }
+}
+
+void IRO_CleanupDump(void) {
+ if (DumpFile)
+ fclose(DumpFile);
+}
+
+void IRO_Dump(char *format, ...) {
+ va_list va;
+ if (IRO_Log) {
+ va_start(va, format);
+ vfprintf(DumpFile, format, va);
+ va_end(va);
+ }
+}
+
+void IRO_DumpAddr(IROAddrRecord *rec) {
+ IROElmList *list;
+
+ if (IRO_Log && DumpFile) {
+ fprintf(DumpFile, "\n");
+ fprintf(DumpFile, "Address :\n");
+ IRO_DumpIntTree(rec->linear);
+ fprintf(DumpFile, "\n");
+ fprintf(DumpFile, "BaseTerms:\n");
+ for (list = rec->objRefs; list; list = list->next) {
+ IRO_DumpIntTree(list->element);
+ fprintf(DumpFile, "\n");
+ }
+ fprintf(DumpFile, "VarTerms:\n");
+ for (list = rec->misc; list; list = list->next) {
+ IRO_DumpIntTree(list->element);
+ fprintf(DumpFile, "\n");
+ }
+ fprintf(DumpFile, "ConstTerms:\n");
+ for (list = rec->ints; list; list = list->next) {
+ IRO_DumpIntTree(list->element);
+ fprintf(DumpFile, "\n");
+ }
+ }
+}
+
+static void IRO_DumpType(Type *type) {
+ char buf[256];
+ IRO_SpellType(type, buf);
+ fprintf(DumpFile, " (%s)", buf);
+}
+
+void IRO_SpellType(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 long ");
+ break;
+ case STRUCT_TYPE_B:
+ strcpy(buf, "vector signed long ");
+ break;
+ case STRUCT_TYPE_C:
+ strcpy(buf, "vector bool long ");
+ 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:
+ IRO_SpellType(TYPE_FUNC(type)->functype, mybuf);
+ strcpy(buf, "freturns(");
+ strcat(buf, mybuf);
+ strcat(buf, ")");
+ break;
+ case TYPEBITFIELD:
+ IRO_SpellType(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:
+ IRO_SpellType(TPTR_TARGET(type), mybuf);
+ strcpy(buf, "pointer(");
+ strcat(buf, mybuf);
+ strcat(buf, ")");
+ break;
+ case TYPEARRAY:
+ IRO_SpellType(TPTR_TARGET(type), mybuf);
+ strcpy(buf, "array(");
+ strcat(buf, mybuf);
+ strcat(buf, ")");
+ break;
+ case TYPEMEMBERPOINTER:
+ IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty2, mybuf);
+ IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty1, mybuf2);
+ strcpy(buf, "memberpointer(");
+ strcat(buf, mybuf);
+ strcat(buf, ",");
+ strcat(buf, mybuf2);
+ strcat(buf, ")");
+ break;
+ }
+}
+
diff --git a/compiler_and_linker/unsorted/IroEmptyLoop.c b/compiler_and_linker/unsorted/IroEmptyLoop.c
index e69de29..1a63f84 100644
--- a/compiler_and_linker/unsorted/IroEmptyLoop.c
+++ b/compiler_and_linker/unsorted/IroEmptyLoop.c
@@ -0,0 +1,567 @@
+#include "compiler/IroEmptyLoop.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroLoop.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CInt64.h"
+
+// forward decls
+static Boolean EmptyLoop(IRONode *fnode);
+static int CanRemoveRedundantLoop(IROLoop *loop);
+static int CanRemoveRedundantLoop1(IROLoop *loop);
+static int RedundantLoopCheck(IROLoop *loop);
+static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
+static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
+
+void IRO_FindEmptyLoops(void) {
+ IRONode *fnode;
+ IRONode *pred;
+ UInt16 i;
+ UInt16 x;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ x = 0;
+ for (i = 0; i < fnode->numpred; i++) {
+ pred = IRO_NodeTable[fnode->pred[i]];
+ if (Bv_IsBitSet(fnode->index, pred->dom)) {
+ if (!x) {
+ Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
+ Bv_Clear(InLoop);
+ Bv_SetBit(fnode->index, InLoop);
+ }
+ x = 1;
+ Bv_SetBit(pred->index, InLoop);
+ if (pred != fnode)
+ AddPreds(pred);
+ }
+ }
+
+ if (x) {
+ IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index);
+ IRO_DumpBits("Loop includes: ", InLoop);
+ EmptyLoop(fnode);
+ IRO_UpdateFlagsOnInts();
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean EmptyLoop(IRONode *fnode) {
+ VarRecord *var;
+ IRONode *bestpred;
+ IRONode *pred;
+ UInt16 i;
+ int flag2;
+ IRONode *r24;
+ Boolean flag;
+ int counter;
+ int j;
+ IRONode *succ;
+ IRONode *bestsucc;
+ int counter2;
+ UInt32 counter3;
+ IROLoop *loop;
+ IRONode *r21;
+ IRONode *r20;
+ IROLinear *constnd;
+ Type *type20;
+ ENode *enode;
+ IROLinear *save;
+
+ flag = 0;
+ counter = 0;
+ LoopNode = fnode;
+ FindMustReach();
+
+ for (var = IRO_FirstVar; var; var = var->next)
+ var->xA = 1;
+
+ ComputeLoopKills();
+ ComputeLoopInvariance();
+ ComputeLoopInduction();
+
+ LoopNode = fnode;
+ ConditionalHeaderAtBottom = 0;
+
+ bestpred = NULL;
+ flag2 = 0;
+ for (i = 0; i < LoopNode->numpred; i++) {
+ pred = IRO_NodeTable[LoopNode->pred[i]];
+ if (!Bv_IsBitSet(pred->index, InLoop)) {
+ flag2 = 1;
+ if (pred->nextnode == fnode) {
+#line 173
+ CError_ASSERT(!bestpred || pred == bestpred);
+ bestpred = pred;
+ }
+ }
+ }
+
+ if (!flag2) {
+ IRO_Dump("No predecessor outside the loop\n");
+ return 0;
+ }
+
+ bestsucc = NULL;
+ for (i = 0; i < LoopNode->numsucc; i++) {
+ succ = IRO_NodeTable[LoopNode->succ[i]];
+ if (Bv_IsBitSet(succ->index, InLoop)) {
+ bestsucc = succ;
+ counter++;
+ }
+ }
+
+ if (LoopNode == bestsucc && counter == 1)
+ flag = 1;
+
+ if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) {
+ counter2 = 0;
+ for (j = 0; j < LoopNode->numpred; j++) {
+ if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
+ r21 = IRO_NodeTable[LoopNode->pred[j]];
+ counter2++;
+ }
+ }
+
+ r24 = NULL;
+ counter3 = 0;
+ for (j = 0; j < LoopNode->numpred; j++) {
+ if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
+ r24 = IRO_NodeTable[LoopNode->pred[j]];
+ counter3++;
+ }
+ }
+
+ if (counter2 == 1 && counter3 == 1) {
+ if (r21->last->type == IROLinearIf) {
+ if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) {
+ IRO_Dump("Standard while loop layout\n");
+ loop = ExtractLoopInfo(r21);
+ if (flag)
+ loop->flags |= LoopFlags_20000;
+ FindAssignmenttoInductionVar(loop, r24);
+ r20 = r24;
+ while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) {
+ FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]);
+ r20 = IRO_NodeTable[r20->pred[0]];
+ }
+
+ if (CanRemoveRedundantLoop(loop)) {
+ IRO_Dump("EmptyLoop: # of iterations =%ld, FinalStoreVal=%ld\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30));
+ IRO_NopOut(r21->last->u.label.x4);
+ r21->last->type = IROLinearNop;
+ type20 = loop->induction->nd->rtype;
+ constnd = IRO_NewLinear(IROLinearOperand);
+ constnd->index = ++IRO_NumLinear;
+ enode = IRO_NewENode(EINTCONST);
+ enode->rtype = type20;
+ enode->data.intval = loop->x30;
+ constnd->u.node = enode;
+ constnd->rtype = type20;
+
+ if (loop->induction->nd->type == IROLinearOp1Arg) {
+ save = loop->induction->nd->u.monadic;
+ loop->induction->nd->type = IROLinearOp2Arg;
+ loop->induction->nd->nodetype = EASS;
+ loop->induction->nd->u.diadic.left = save;
+ loop->induction->nd->u.diadic.right = constnd;
+ IRO_Paste(constnd, constnd, loop->induction->nd);
+ } else if (loop->induction->nd->type == IROLinearOp2Arg) {
+ loop->induction->nd->nodetype = EASS;
+ IRO_NopOut(loop->induction->nd->u.diadic.right);
+ loop->induction->nd->u.diadic.right = constnd;
+ IRO_Paste(constnd, constnd, loop->induction->nd);
+ }
+ } else if (CanRemoveRedundantLoop1(loop)) {
+ IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n");
+
+ r21->last->type = IROLinearNop;
+ type20 = loop->induction->nd->rtype;
+ constnd = IRO_NewLinear(IROLinearOperand);
+ constnd->index = ++IRO_NumLinear;
+ enode = IRO_NewENode(EINTCONST);
+ enode->rtype = type20;
+ enode->data.intval = cint64_zero;
+ constnd->u.node = enode;
+ constnd->rtype = type20;
+
+ save = loop->induction->nd->u.monadic;
+ loop->induction->nd->type = IROLinearOp2Arg;
+ loop->induction->nd->nodetype = EASS;
+ loop->induction->nd->u.diadic.left = save;
+ loop->induction->nd->u.diadic.right = constnd;
+ IRO_Paste(constnd, constnd, loop->induction->nd);
+ }
+ } else {
+ IRO_Dump("NonStandard while loop layout\n");
+ }
+ } else {
+ IRO_Dump("NonStandard while loop layout\n");
+ }
+ } else {
+ IRO_Dump("Cannot handle Do While Loop with multiple tails\n");
+ }
+ }
+
+ return 0;
+}
+
+static int CanRemoveRedundantLoop(IROLoop *loop) {
+ IROLinear *inner;
+
+ if (loop->flags & LoopFlags_10000) {
+ IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HAS_ASM) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HAS_CALLS) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_INDUCTION_NOT_FOUND) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
+ IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
+ return 0;
+ }
+
+ if (!(loop->flags & LoopFlags_200)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n");
+ return 0;
+ }
+
+ if (!(loop->flags & LoopFlags_10000)) {
+ inner = loop->nd18->u.diadic.right;
+ if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n");
+ return 0;
+ }
+
+ if (!loop->nd14) {
+ IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n");
+ return 0;
+ }
+
+ if (!IRO_IsVariable(loop->nd14->u.diadic.left)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n");
+ return 0;
+ }
+
+ if (!IRO_IsUnsignedType(loop->nd14->rtype)) {
+ if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) {
+ if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n");
+ return 0;
+ }
+ } else {
+ IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n");
+ return 0;
+ }
+ }
+
+ if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n");
+ return 0;
+ }
+
+ if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
+ return 0;
+ }
+
+ if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) {
+ IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
+ return 0;
+ }
+ }
+
+ return RedundantLoopCheck(loop) != 0;
+}
+
+static int CanRemoveRedundantLoop1(IROLoop *loop) {
+ if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) {
+ if (loop->flags & LP_LOOP_HAS_ASM) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HAS_CALLS) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_INDUCTION_NOT_FOUND) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
+ return 0;
+ }
+
+ if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
+ IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
+ return 0;
+ }
+
+ if (!(loop->flags & LoopFlags_200)) {
+ IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n");
+ return 0;
+ }
+
+ if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) {
+ if (IRO_IsUnsignedType(loop->induction->nd->rtype))
+ return 1;
+ IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n");
+ return 0;
+ }
+
+ IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n");
+ return 0;
+ } else {
+ return 0;
+ }
+}
+
+static int RedundantLoopCheck(IROLoop *loop) {
+ IRONode *fnode;
+ IROLinear *nd;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) {
+ while (1) {
+ if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) {
+ if (IS_LINEAR_DIADIC(nd, EASS)) {
+ if (!(nd->flags & IROLF_Reffed)) {
+ if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) {
+ if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) {
+ IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index);
+ return 0;
+ }
+
+ if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) {
+ IRO_Dump(" EASS at %d pass\n", nd->index);
+ } else {
+ IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index);
+ return 0;
+ }
+ } else {
+ IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n");
+ return 0;
+ }
+ } else {
+ IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n");
+ return 0;
+ }
+ } else {
+ if (!(nd->flags & IROLF_Reffed)) {
+ IRO_Dump("Found non EASS top level node in the loop\n");
+ return 0;
+ }
+ }
+ }
+
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
+ Boolean isUnsigned;
+ IROLinear *nd2;
+ IROLinear *nd1;
+ CInt64 nd2value;
+ CInt64 nd1value;
+ CInt64 addConst;
+ CInt64 work;
+ CInt64 neg1;
+
+ nd2 = loop->nd14->u.diadic.right;
+ nd1 = loop->nd18->u.diadic.right;
+ isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
+
+ if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
+ nd2value = nd2->u.node->data.intval;
+ nd1value = nd1->u.node->data.intval;
+ if (isUnsigned) {
+ if (CInt64_LessEqualU(nd1value, nd2value))
+ return 1;
+ } else {
+ if (CInt64_LessEqual(nd1value, nd2value))
+ return 1;
+ }
+
+ CInt64_SetLong(&addConst, loop->induction->addConst);
+ CInt64_SetLong(&neg1, -1);
+ *val1 = CInt64_Sub(nd1value, nd2value);
+ *val1 = CInt64_Add(*val1, addConst);
+ if (IS_LINEAR_DIADIC(loop->nd18, ELESS))
+ *val1 = CInt64_Add(*val1, neg1);
+
+#line 855
+ CError_ASSERT(!CInt64_IsZero(&addConst));
+
+ if (isUnsigned)
+ *val1 = CInt64_DivU(*val1, addConst);
+ else
+ *val1 = CInt64_Div(*val1, addConst);
+
+ if (CInt64_Equal(*val1, cint64_zero))
+ return 1;
+
+ if (isUnsigned) {
+ if (CInt64_LessEqualU(*val1, cint64_zero)) {
+#line 877
+ CError_FATAL();
+ }
+ } else {
+ if (CInt64_LessEqual(*val1, cint64_zero)) {
+#line 886
+ CError_FATAL();
+ }
+ }
+
+ if (isUnsigned) {
+ *val2 = CInt64_MulU(*val1, addConst);
+ *val2 = CInt64_Add(*val2, nd2value);
+ } else {
+ *val2 = CInt64_Mul(*val1, addConst);
+ *val2 = CInt64_Add(*val2, nd2value);
+ }
+ } else {
+ return 1;
+ }
+
+ CInt64_SetLong(&addConst, loop->induction->addConst);
+ work = CInt64_Add(nd1value, addConst);
+
+ if (isUnsigned) {
+ if (CInt64_LessU(work, nd1value))
+ return 1;
+ } else {
+ if (CInt64_Less(work, nd1value))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
+ Boolean isUnsigned;
+ IROLinear *nd2;
+ IROLinear *nd1;
+ CInt64 nd2value;
+ CInt64 nd1value;
+ CInt64 addConst;
+ CInt64 work;
+ CInt64 neg1;
+
+ nd1 = loop->nd14->u.diadic.right;
+ nd2 = loop->nd18->u.diadic.right;
+ isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
+
+ if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
+ nd2value = nd2->u.node->data.intval;
+ nd1value = nd1->u.node->data.intval;
+ if (isUnsigned) {
+ if (CInt64_LessEqualU(nd1value, nd2value))
+ return 1;
+ } else {
+ if (CInt64_LessEqual(nd1value, nd2value))
+ return 1;
+ }
+
+ CInt64_SetLong(&addConst, loop->induction->addConst);
+ CInt64_SetLong(&neg1, -1);
+ *val1 = CInt64_Sub(nd1value, nd2value);
+ *val1 = CInt64_Add(*val1, addConst);
+ if (IS_LINEAR_DIADIC(loop->nd18, EGREATER))
+ *val1 = CInt64_Add(*val1, neg1);
+
+#line 995
+ CError_ASSERT(!CInt64_IsZero(&addConst));
+
+ if (isUnsigned)
+ *val1 = CInt64_DivU(*val1, addConst);
+ else
+ *val1 = CInt64_Div(*val1, addConst);
+
+ if (CInt64_Equal(*val1, cint64_zero))
+ return 1;
+
+ if (isUnsigned) {
+ if (CInt64_LessEqualU(*val1, cint64_zero))
+ return 0;
+ } else {
+ if (CInt64_LessEqual(*val1, cint64_zero))
+ return 0;
+ }
+
+ if (isUnsigned) {
+ *val2 = CInt64_MulU(*val1, addConst);
+ *val2 = CInt64_Sub(nd1value, *val2);
+ } else {
+ *val2 = CInt64_Mul(*val1, addConst);
+ *val2 = CInt64_Sub(nd1value, *val2);
+ }
+ } else {
+ return 1;
+ }
+
+ CInt64_SetLong(&addConst, loop->induction->addConst);
+ work = CInt64_Sub(nd2value, addConst);
+
+ if (isUnsigned) {
+ if (CInt64_GreaterU(work, nd2value))
+ return 1;
+ } else {
+ if (CInt64_Greater(work, nd1value))
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/compiler_and_linker/unsorted/IroExprRegeneration.c b/compiler_and_linker/unsorted/IroExprRegeneration.c
index e69de29..074510b 100644
--- a/compiler_and_linker/unsorted/IroExprRegeneration.c
+++ b/compiler_and_linker/unsorted/IroExprRegeneration.c
@@ -0,0 +1,1531 @@
+#include "compiler/IroExprRegeneration.h"
+#include "compiler/IroCSE.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroSubable.h"
+#include "compiler/IroTransform.h"
+#include "compiler/IROUseDef.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CDecl.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/objects.h"
+
+// forward decls
+static void GetExprUses(IROLinear *linear, Boolean isEntry);
+static void RebuildPossibleCondExpression(IRONode *fnode);
+static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2);
+
+static Boolean FindFlowgraphNodeThatStartsWithLabel(CLabel *label, IRONode **result1, IRONode **result2) {
+ IRONode *prev;
+ IRONode *iter;
+
+ prev = IRO_FirstNode;
+ if (prev != NULL)
+ iter = prev->nextnode;
+
+ while (iter) {
+ if (iter->first->type == IROLinearLabel && iter->first->u.label.label == label) {
+ *result1 = iter;
+ *result2 = prev;
+ return 1;
+ }
+
+ prev = iter;
+ iter = iter->nextnode;
+ }
+
+ return 0;
+}
+
+static IROLinear *FindLastDiadicTopLevelAssignmentInFlowgraphNode(IRONode *fnode) {
+ IROLinear *scan;
+ IROLinear *result;
+
+ result = NULL;
+
+ for (scan = fnode->first; scan != fnode->last->next; scan = scan->next) {
+ if (scan->type == IROLinearOp2Arg && scan->nodetype == EASS && !(scan->flags & IROLF_Reffed))
+ result = scan;
+ }
+
+ return result;
+}
+
+static Boolean RewriteUse(IROUse *use, ENode *enode, IROLinear *nd, Boolean flag) {
+ IROLinear *father;
+ IROLinear *father2;
+
+ if (
+ use &&
+ use->x1C &&
+ use->linear &&
+ use->linear->type == IROLinearOperand &&
+ use->linear->u.node->type == EOBJREF &&
+ use->linear->u.node->data.objref == enode->data.objref &&
+ (father = IRO_LocateFather(use->linear)) &&
+ father->type == IROLinearOp1Arg &&
+ father->nodetype == EINDIRECT &&
+ father->rtype == nd->rtype &&
+ (father2 = IRO_LocateFather(father)) &&
+ ((father2->type != IROLinearOp1Arg && father2->type != IROLinearOp2Arg) || !IRO_IsModifyOp[father2->nodetype])
+ ) {
+ if (flag)
+ IRO_LocateFather_Cut_And_Paste(father, nd);
+ return 1;
+ }
+
+ return 0;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+static struct {
+ jmp_buf buf;
+ UInt16 index;
+ Boolean flag;
+} scuai;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void StatementContainsUseAction(IROLinear *linear, Boolean isFirst) {
+ if (isFirst && linear->index == scuai.index) {
+ scuai.flag = 1;
+ longjmp(scuai.buf, 1);
+ }
+}
+
+static Boolean StatementContainsUse(IROLinear *a, IROLinear *b) {
+ memset(&scuai, 0, sizeof(scuai));
+ scuai.index = b->index;
+ scuai.flag = 0;
+
+ if (!setjmp(scuai.buf))
+ IRO_WalkInts(a, a, StatementContainsUseAction);
+
+ return scuai.flag;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+static struct {
+ jmp_buf buf;
+ Boolean flag;
+} scseai;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void StatementContainsSideEffectAction(IROLinear *linear, Boolean isFirst) {
+ if (isFirst) {
+ switch (linear->type) {
+ case IROLinearOperand:
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ case IROLinearOp3Arg:
+ case IROLinearFunccall:
+ case IROLinearAsm:
+ if (IRO_HasSideEffect(linear)) {
+ scseai.flag = 1;
+ longjmp(scseai.buf, 1);
+ }
+ break;
+ }
+ }
+}
+
+static Boolean StatementContainsSideEffect(IROLinear *linear) {
+ memset(&scseai, 0, sizeof(scseai));
+ scseai.flag = 0;
+
+ if (!setjmp(scseai.buf))
+ IRO_WalkInts(linear, linear, StatementContainsSideEffectAction);
+
+ return scseai.flag;
+}
+
+static Boolean HasSideEffectsBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, Boolean flag) {
+ IRONode *fnode;
+ IROLinear *scannd;
+ UInt16 i;
+
+ if (fnode1 != fnode3) {
+ if (flag) {
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
+ fnode->x3C = 0;
+ } else if (fnode1->x3C) {
+ return 0;
+ }
+ fnode1->x3C = 1;
+ }
+
+ for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) {
+ if (!(scannd->flags & IROLF_Reffed)) {
+ if (StatementContainsUse(scannd, nd))
+ return 0;
+ if (StatementContainsSideEffect(scannd))
+ return 1;
+ }
+ }
+
+ if (fnode1 != fnode3) {
+ for (i = 0; i < fnode1->numsucc; i++) {
+ if (HasSideEffectsBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, 0))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static Boolean UsesAKilledVarBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, BitVector *bv, Boolean flag) {
+ IRONode *fnode;
+ UInt16 i;
+ IROLinear *scannd;
+
+ if (fnode1 != fnode3) {
+ if (flag) {
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
+ fnode->x3C = 0;
+ } else if (fnode1->x3C) {
+ return 0;
+ }
+ fnode1->x3C = 1;
+ }
+
+ for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) {
+ if (!(scannd->flags & IROLF_Reffed)) {
+ if (StatementContainsUse(scannd, nd))
+ return 0;
+ Bv_Clear(IRO_VarKills);
+ IRO_WalkInts(scannd, scannd, GetExprUses);
+ if (Bv_BitsInCommon(bv, IRO_VarKills))
+ return 1;
+ }
+ }
+
+ if (fnode1 != fnode3) {
+ for (i = 0; i < fnode1->numsucc; i++) {
+ if (UsesAKilledVarBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, bv, 0))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void GetExprUses(IROLinear *linear, Boolean isEntry) {
+ Object *obj;
+ VarRecord *var;
+
+ if (isEntry) {
+ if (linear->type == IROLinearOperand && linear->u.node->type == EOBJREF) {
+ obj = linear->u.node->data.objref;
+ if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) {
+ if ((var = IRO_FindVar(obj, 0, 1)))
+ Bv_SetBit(var->index, IRO_VarKills);
+ }
+ }
+ }
+}
+
+static void GetExprKills(IROLinear *linear, Boolean isEntry) {
+ if (isEntry)
+ IRO_GetKills(linear);
+}
+
+static void CheckUnorderedRegionForSideEffectsAndUses(IROLinear *nd, BitVector *bv1, BitVector *bv2, Boolean *result) {
+ if (IRO_HasSideEffect(nd)) {
+ *result = 1;
+ } else {
+ Bv_Clear(bv2);
+ Bv_Clear(IRO_VarKills);
+ IRO_WalkTree(nd, GetExprUses);
+ Bv_Or(IRO_VarKills, bv2);
+
+ if (Bv_BitsInCommon(bv1, bv2))
+ *result = 1;
+ }
+}
+
+static void CheckUnorderedRegionsForSideEffectsAndUses(IROLinear *nd1, IROLinear *nd2, BitVector *bv1, BitVector *bv2, Boolean *result) {
+ int i;
+
+ switch (nd1->type) {
+ case IROLinearOp2Arg:
+ if (nd1->nodetype != ELAND && nd1->nodetype != ELOR && nd1->nodetype != ECOMMA) {
+ if (nd1->u.diadic.left != nd2)
+ CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.left, bv1, bv2, result);
+ if (nd1->u.diadic.right != nd2)
+ CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.right, bv1, bv2, result);
+ }
+ break;
+ case IROLinearFunccall:
+ if (nd1->u.funccall.linear8 != nd2)
+ CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.linear8, bv1, bv2, result);
+ for (i = 0; !*result && i < nd1->u.funccall.argCount; i++) {
+ if (nd1->u.funccall.args[i] != nd2)
+ CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.args[i], bv1, bv2, result);
+ }
+ break;
+ }
+}
+
+static Boolean CheckThenOrElseBranch(IRONode *fnode1, IRONode *fnode2, IROLinear *nd, Boolean flag) {
+ IRONode *fnode;
+ IROLinear *scannd;
+ IRONodes nodes;
+ Boolean result;
+
+ IROFlowgraph_sub_4C2140(&nodes);
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
+ fnode->x3C = 0;
+ AddNodeAndSuccessorsRecursively(&nodes, fnode1, fnode2);
+
+ while (IROFlowgraph_sub_4C2040(&nodes)) {
+ fnode = IRO_NodeTable[IROFlowgraph_sub_4C2100(&nodes)];
+ if (fnode) {
+ if (!Bv_IsBitSet(fnode1->index, fnode->dom)) {
+ result = 0;
+ goto done;
+ }
+
+ for (scannd = fnode->first; scannd && scannd != fnode->last->next; scannd = scannd->next) {
+ if (!nd || scannd != nd) {
+ if (!flag || (scannd->type != IROLinearReturn)) {
+ if (fnode->numpred == 2 && scannd->type == IROLinearLabel)
+ RebuildPossibleCondExpression(fnode);
+
+ if (scannd->type != IROLinearNop &&
+ scannd->type != IROLinearLabel &&
+ scannd->type != IROLinearGoto &&
+ !(scannd->flags & IROLF_Reffed)) {
+ result = 0;
+ goto done;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = 1;
+done:
+ IROFlowgraph_sub_4C20E0(&nodes);
+ return result;
+}
+
+static void RebuildPossibleCondExpression(IRONode *fnode) {
+ IRONode *pred1;
+ IRONode *pred2;
+ IRONode *r30;
+ IROLinear *leftAss;
+ IROLinear *rightAss;
+ IROLinear *r27;
+ IROLinear *r13;
+ IROLinear *var_58;
+ IRONode *left;
+ IRONode *right;
+ IRONode *r24;
+ ENode *r23;
+ IRODef *r22;
+ IRODef *r21;
+ IRODef *def;
+ IROUse *use;
+ UInt32 r20;
+ UInt32 r19;
+ Boolean r18;
+ Boolean r17;
+ UInt32 i;
+ Boolean compareType;
+ Type *var_60;
+ IROLinear copy1;
+ IROLinear copy2;
+ IROLinear copy3;
+
+ if (
+ !fnode ||
+ fnode->numpred != 2 ||
+ !fnode->first ||
+ fnode->first->type != IROLinearLabel
+ )
+ return;
+
+ pred1 = IRO_NodeTable[fnode->pred[0]];
+ pred2 = IRO_NodeTable[fnode->pred[1]];
+ if (
+ !pred1 || !pred2 ||
+ pred1->numsucc != 1 || pred2->numsucc != 1
+ )
+ return;
+
+ r24 = NULL;
+ for (i = 0; i < IRO_NumNodes; i++) {
+ if (
+ Bv_IsBitSet(i, fnode->dom) &&
+ (r24 = IRO_NodeTable[i]) &&
+ r24->last &&
+ (r24->last->type == IROLinearIf || r24->last->type == IROLinearIfNot) &&
+ r24->last->u.label.label &&
+ r24->numsucc == 2
+ ) {
+ if (Bv_IsBitSet(r24->succ[0], pred1->dom) &&
+ !Bv_IsBitSet(r24->succ[0], pred2->dom) &&
+ Bv_IsBitSet(r24->succ[1], pred2->dom) &&
+ !Bv_IsBitSet(r24->succ[1], pred1->dom))
+ break;
+
+ if (Bv_IsBitSet(r24->succ[0], pred2->dom) &&
+ !Bv_IsBitSet(r24->succ[0], pred1->dom) &&
+ Bv_IsBitSet(r24->succ[1], pred1->dom) &&
+ !Bv_IsBitSet(r24->succ[1], pred2->dom))
+ break;
+ }
+ }
+
+ if (i >= IRO_NumNodes)
+ return;
+
+ /*if (
+ (r30 = IRO_NodeTable[r24->succ[0]]) &&
+ r30->numpred == 1 &&
+ r30->first &&
+ r30->first->type == IROLinearLabel &&
+ r30->first->u.label.label == r24->last->u.label.label
+ ) {
+ goto ok;
+ } else if (
+ (r30 = IRO_NodeTable[r24->succ[1]]) &&
+ r30->numpred == 1 &&
+ r30->first &&
+ r30->first->type == IROLinearLabel &&
+ r30->first->u.label.label == r24->last->u.label.label
+ ) {
+ goto ok;
+ } else {
+ return;
+ }*/
+ /*if (
+ (!(r30 = IRO_NodeTable[r24->succ[0]]) ||
+ r30->numpred != 1 ||
+ !r30->first ||
+ r30->first->type != IROLinearLabel ||
+ r30->first->u.label.label != r24->last->u.label.label)
+ &&
+ (!(r30 = IRO_NodeTable[r24->succ[1]]) ||
+ r30->numpred != 1 ||
+ !r30->first ||
+ r30->first->type != IROLinearLabel ||
+ r30->first->u.label.label != r24->last->u.label.label)
+ )
+ return;*/
+ r30 = IRO_NodeTable[r24->succ[0]];
+ if (
+ r30 &&
+ r30->numpred == 1 &&
+ r30->first &&
+ r30->first->type == IROLinearLabel &&
+ r30->first->u.label.label == r24->last->u.label.label
+ ) {
+ (void)0;
+ } else {
+ r30 = IRO_NodeTable[r24->succ[1]];
+ if (
+ r30 &&
+ r30->numpred == 1 &&
+ r30->first &&
+ r30->first->type == IROLinearLabel &&
+ r30->first->u.label.label == r24->last->u.label.label
+ ) {
+ } else {
+ return;
+ }
+ }
+
+ok:
+ if (Bv_IsBitSet(r30->index, pred1->dom)) {
+ left = pred2;
+ right = pred1;
+ } else {
+ left = pred1;
+ right = pred2;
+ }
+
+ leftAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(left);
+ if (
+ !leftAss ||
+ leftAss->type != IROLinearOp2Arg ||
+ !leftAss->u.diadic.left ||
+ leftAss->u.diadic.left->type != IROLinearOp1Arg ||
+ leftAss->u.diadic.left->nodetype != EINDIRECT ||
+ !leftAss->u.diadic.left->u.monadic ||
+ leftAss->u.diadic.left->u.monadic->type != IROLinearOperand ||
+ !(r23 = leftAss->u.diadic.left->u.monadic->u.node) ||
+ !r23->rtype ||
+ !IS_TYPE_POINTER_ONLY(r23->rtype) ||
+ !r23->data.objref ||
+ is_volatile_object(r23->data.objref) ||
+ r23->data.objref->datatype != DLOCAL
+ )
+ r23 = NULL;
+
+ if (r23) {
+ rightAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(right);
+ if (
+ !rightAss ||
+ rightAss->type != IROLinearOp2Arg ||
+ !rightAss->u.diadic.left ||
+ rightAss->u.diadic.left->type != IROLinearOp1Arg ||
+ rightAss->u.diadic.left->nodetype != EINDIRECT ||
+ !rightAss->u.diadic.left->u.monadic ||
+ rightAss->u.diadic.left->u.monadic->type != IROLinearOperand ||
+ !rightAss->u.diadic.left->u.monadic->u.node ||
+ !rightAss->u.diadic.left->u.monadic->u.node->rtype ||
+ !IS_TYPE_POINTER_ONLY(rightAss->u.diadic.left->u.monadic->u.node->rtype) ||
+ rightAss->u.diadic.left->u.monadic->u.node->type != EOBJREF ||
+ rightAss->u.diadic.left->u.monadic->u.node->data.objref != r23->data.objref ||
+ rightAss->rtype != leftAss->rtype
+ )
+ r23 = NULL;
+ }
+
+ if (r23) {
+ if (!CheckThenOrElseBranch(r24->nextnode, left, leftAss, 0) || !CheckThenOrElseBranch(r30, right, rightAss, 0))
+ return;
+
+ r19 = 0;
+ r20 = 0;
+ r18 = 0;
+ r17 = 0;
+ if (!r23->data.objref->varptr || !r23->data.objref->varptr->uses || !r23->data.objref->varptr->defs) {
+ r23 = NULL;
+ } else {
+ r21 = NULL;
+ r22 = NULL;
+ for (def = r23->data.objref->varptr->defs; def && (!r22 || !r21); def = def->varnext) {
+ if (def->x18 && def->linear == leftAss)
+ r22 = def;
+ else if (def->x18 && def->linear == rightAss)
+ r21 = def;
+ }
+
+ if (!r22 || !r21) {
+ r23 = NULL;
+ } else {
+ for (use = r23->data.objref->varptr->uses; r23 && use; use = use->varnext) {
+ if (use->x1C) {
+ r20++;
+ if (Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) {
+ for (i = 0; r23 && i < use->x18->size; i++) {
+ if (i != r22->index && i != r21->index && Bv_IsBitSet(i, use->x18))
+ r23 = NULL;
+ }
+
+ if (r23 && !Bv_IsBitSet(fnode->index, use->node->dom))
+ r23 = NULL;
+
+ if (r23) {
+ if (RewriteUse(use, r23, rightAss, 0))
+ r19++;
+ else
+ r23 = NULL;
+ }
+
+ if (r23 && !r17)
+ r17 = HasSideEffectsBeforeUse(fnode, fnode, use->node, use->linear, 1);
+
+ if (r23 && !r18 && (IRO_HasSideEffect(r24->last->u.label.x4) || IRO_HasSideEffect(leftAss->u.label.x4) ||
+ IRO_HasSideEffect(rightAss->u.label.x4)))
+ r18 = 1;
+ } else if (Bv_IsBitSet(r22->index, use->x18) || Bv_IsBitSet(r21->index, use->x18)) {
+ r23 = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!r23)
+ return;
+
+ compareType = r24->last->type == IROLinearIf;
+ r27 = r24->last->u.label.x4;
+ r13 = leftAss->u.label.x4;
+ var_58 = rightAss->u.label.x4;
+ var_60 = rightAss->rtype;
+ memcpy(&copy1, r13, sizeof(IROLinear));
+ memcpy(&copy2, rightAss, sizeof(IROLinear));
+
+ r24->last->type = IROLinearNop;
+ r24->last->expr = NULL;
+ r30->first->type = IROLinearNop;
+ r30->first->expr = NULL;
+ fnode->first->type = IROLinearNop;
+ fnode->first->expr = NULL;
+ if (left->last->type == IROLinearGoto) {
+ left->last->type = IROLinearNop;
+ left->last->expr = NULL;
+ }
+ if (right->last->type == IROLinearGoto) {
+ right->last->type = IROLinearNop;
+ right->last->expr = NULL;
+ }
+
+ if (r23) {
+ IRO_NopOut(leftAss->u.diadic.left);
+ leftAss->type = IROLinearNop;
+ leftAss->expr = NULL;
+ }
+
+ memcpy(rightAss, &copy1, sizeof(IROLinear));
+ rightAss->type = IROLinearOp3Arg;
+ rightAss->nodetype = ECOND;
+ rightAss->index = copy2.index;
+ rightAss->u.args3.a = r27;
+ rightAss->rtype = var_60;
+ rightAss->next = copy2.next;
+ if (compareType) {
+ rightAss->u.args3.b = var_58;
+ rightAss->u.args3.c = r13;
+ } else {
+ rightAss->u.args3.b = r13;
+ rightAss->u.args3.c = var_58;
+ }
+ rightAss->flags |= IROLF_Reffed;
+
+ if (r19 == 1 && !r17 && !r18 && !r23->data.objref->varptr->xB) {
+ for (use = r23->data.objref->varptr->uses; use; use = use->varnext) {
+ if (use->x1C && Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) {
+ RewriteUse(use, r23, rightAss, 1);
+ if ((r18 = (use->linear->flags & IROLF_4000) && IRO_HasSideEffect(r27))) {
+ IROLinear *tmp;
+ Object *obj;
+
+ tmp = IRO_NewLinear(IROLinearOperand);
+ memcpy(tmp, copy2.u.diadic.left->u.monadic, sizeof(IROLinear));
+ tmp->index = IRO_NumLinear++;
+ tmp->rtype = r27->rtype;
+ if (r20 == 1) {
+ tmp->u.node->data.objref->type = r27->rtype;
+ tmp->u.node->rtype = CDecl_NewPointerType(r27->rtype);
+ } else {
+ obj = create_temp_object(tmp->rtype);
+ IRO_FindVar(obj, 1, 1);
+ tmp->u.node = create_objectrefnode(obj);
+ }
+ IRO_PasteAfter(tmp, tmp, r27);
+
+ tmp = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(tmp, copy2.u.diadic.left, sizeof(IROLinear));
+ tmp->index = IRO_NumLinear++;
+ tmp->u.monadic = r27->next;
+ tmp->rtype = r27->rtype;
+ IRO_PasteAfter(tmp, tmp, r27->next);
+
+ tmp = IRO_NewLinear(IROLinearOp2Arg);
+ memcpy(tmp, &copy2, sizeof(IROLinear));
+ tmp->index = IRO_NumLinear++;
+ tmp->u.diadic.right = r27;
+ tmp->u.diadic.left = r27->next->next;
+ tmp->rtype = r27->rtype;
+ IRO_PasteAfter(tmp, tmp, r27->next->next);
+
+ if (r20 != 1) {
+ tmp = copy2.u.diadic.left->u.monadic;
+ tmp->u.node = create_objectrefnode(obj);
+ }
+
+ rightAss->u.args3.a = copy2.u.diadic.left;
+ rightAss->u.args3.a->rtype = r27->rtype;
+
+ if (r20 == 1) {
+ r21->linear = r27->next->next;
+ if (Bv_IsBitSet(r21->index, right->x1A)) {
+ Bv_ClearBit(r21->index, right->x1A);
+ Bv_SetBit(r21->index, r24->x1A);
+ }
+ if (Bv_IsBitSet(r21->index, right->x1E)) {
+ Bv_ClearBit(r21->index, right->x1E);
+ Bv_SetBit(r21->index, r24->x1E);
+ }
+ if (Bv_IsBitSet(r21->index, right->x22)) {
+ Bv_ClearBit(r21->index, right->x22);
+ Bv_SetBit(r21->index, r24->x22);
+ }
+ }
+ }
+ }
+ }
+
+ if (!r18) {
+ if (r20 == 1 && r23->data.objref->u.var.info) {
+ r23->data.objref->u.var.info->usage = 0;
+ r23->data.objref->u.var.info->used = 0;
+ }
+ r22->x18 = 0;
+ IRO_NopOut(copy2.u.diadic.left);
+ r21->x18 = 0;
+ }
+ } else {
+ memcpy(&copy3, fnode->first, sizeof(IROLinear));
+ memcpy(fnode->first, &copy2, sizeof(IROLinear));
+
+ fnode->first->index = copy3.index;
+ fnode->first->u.diadic.right = rightAss;
+ fnode->first->next = copy3.next;
+ r22->x18 = 0;
+ r21->linear = fnode->first;
+ if (Bv_IsBitSet(r21->index, right->x1A)) {
+ Bv_ClearBit(r21->index, right->x1A);
+ Bv_SetBit(r21->index, fnode->x1A);
+ }
+ if (Bv_IsBitSet(r21->index, right->x1E)) {
+ Bv_ClearBit(r21->index, right->x1E);
+ Bv_SetBit(r21->index, fnode->x1E);
+ }
+ if (Bv_IsBitSet(r21->index, right->x22)) {
+ Bv_ClearBit(r21->index, right->x22);
+ Bv_SetBit(r21->index, fnode->x22);
+ }
+ }
+}
+
+static void RebuildPossibleReturnCondExpression(IRONode *fnode) {
+ IRONode *succ1;
+ IRONode *succ2;
+ IROLinear *node1;
+ IROLinear *node2;
+ IROLinear *node3;
+ IRONode *r27;
+ Boolean isIf;
+ Type *type;
+ IROList list;
+
+ if (
+ !fnode ||
+ fnode->numsucc != 2 ||
+ !fnode->last ||
+ (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot)
+ )
+ return;
+
+ succ1 = IRO_NodeTable[fnode->succ[0]];
+ succ2 = IRO_NodeTable[fnode->succ[1]];
+ if (
+ !succ1 || !succ2 ||
+ succ1->numsucc != 0 || succ1->numpred != 1 ||
+ succ2->numsucc != 0 || succ2->numpred != 1
+ )
+ return;
+
+ if (succ1->first && succ1->first->type == IROLinearLabel && succ1->first->u.label.label == fnode->last->u.label.label) {
+ r27 = succ1;
+ } else if (succ2->first && succ2->first->type == IROLinearLabel && succ2->first->u.label.label == fnode->last->u.label.label) {
+ r27 = succ2;
+ } else {
+ return;
+ }
+
+ if (r27->numpred != 1)
+ return;
+
+ if (!CheckThenOrElseBranch(fnode->nextnode, fnode->nextnode, NULL, 1) || !CheckThenOrElseBranch(r27, r27, NULL, 1))
+ return;
+
+ if (
+ !fnode->nextnode->last ||
+ fnode->nextnode->last->type != IROLinearReturn ||
+ !fnode->nextnode->last->u.monadic ||
+ !r27->last ||
+ r27->last->type != IROLinearReturn ||
+ !r27->last->u.monadic ||
+ !IRO_TypesEqual(fnode->nextnode->last->u.monadic->rtype, r27->last->u.monadic->rtype)
+ )
+ return;
+
+ isIf = fnode->last->type == IROLinearIf;
+ node1 = fnode->last->u.diadic.right;
+ node2 = fnode->nextnode->last->u.diadic.left;
+ node3 = r27->last->u.diadic.left;
+ type = node2->rtype;
+
+ fnode->last->type = IROLinearNop;
+ fnode->last->expr = NULL;
+ r27->last->type = IROLinearNop;
+ r27->last->expr = NULL;
+ r27->first->type = IROLinearNop;
+ r27->first->expr = NULL;
+
+ if (IRO_IsIntConstant(node2) && IRO_IsIntConstant(node3) &&
+ ((IRO_IsConstantOne(node2) && IRO_IsConstantZero(node3)) ||
+ (IRO_IsConstantZero(node2) && IRO_IsConstantOne(node3)))) {
+ if (!(node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == type)) {
+ IROLinear *tmp1;
+ IROLinear *tmp2;
+
+ tmp1 = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(tmp1, node2, sizeof(IROLinear));
+ tmp1->type = IROLinearOp1Arg;
+ tmp1->nodetype = ELOGNOT;
+ tmp1->index = IRO_NumLinear++;
+ tmp1->u.monadic = node1;
+
+ tmp1->next = tmp2 = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(tmp2, node2, sizeof(IROLinear));
+ tmp2->type = IROLinearOp1Arg;
+ tmp2->nodetype = ELOGNOT;
+ tmp2->index = IRO_NumLinear++;
+ tmp2->u.monadic = tmp1;
+
+ IRO_PasteAfter(tmp1, tmp2, node1);
+ node1 = tmp2;
+ }
+
+ if ((IRO_IsConstantZero(node2) && !isIf) || (IRO_IsConstantOne(node2) && isIf)) {
+ if (node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == node1->u.monadic->rtype) {
+ IROLinear *tmp = node1;
+ node1 = node1->u.monadic;
+ tmp->type = IROLinearNop;
+ tmp->expr = NULL;
+ } else {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(tmp, node2, sizeof(IROLinear));
+ tmp->type = IROLinearOp1Arg;
+ tmp->nodetype = ELOGNOT;
+ tmp->index = IRO_NumLinear++;
+ tmp->u.monadic = node1;
+ IRO_PasteAfter(tmp, tmp, node1);
+ node1 = tmp;
+ }
+ }
+
+ node2->type = IROLinearNop;
+ node2->expr = NULL;
+ node3->type = IROLinearNop;
+ node3->expr = NULL;
+ fnode->nextnode->last->u.monadic = node1;
+ } else {
+ IROLinear *tmp1;
+ IROLinear *tmp2;
+
+ IRO_InitList(&list);
+ tmp1 = IRO_DuplicateExpr(node3, &list);
+ IRO_NopOut(node3);
+ IRO_Paste(list.head, list.tail, fnode->nextnode->last);
+
+ tmp2 = IRO_NewLinear(IROLinearOp3Arg);
+ memcpy(tmp2, node2, sizeof(IROLinear));
+ tmp2->type = IROLinearOp3Arg;
+ tmp2->nodetype = ECOND;
+ tmp2->index = IRO_NumLinear++;
+ tmp2->u.args3.a = node1;
+ tmp2->rtype = type;
+ IRO_Paste(tmp2, tmp2, fnode->nextnode->last);
+
+ if (isIf) {
+ tmp2->u.args3.b = tmp1;
+ tmp2->u.args3.c = node2;
+ } else {
+ tmp2->u.args3.b = node2;
+ tmp2->u.args3.c = tmp1;
+ }
+
+ fnode->nextnode->last->u.monadic = tmp2;
+ }
+}
+
+static void RebuildCondExpressions(void) {
+ IRONode *fnode;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (fnode->numpred == 2) {
+ if (fnode->first && fnode->first->type == IROLinearLabel)
+ RebuildPossibleCondExpression(fnode);
+ } else if (fnode->numsucc == 2) {
+ if (fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot))
+ RebuildPossibleReturnCondExpression(fnode);
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean IsLogicalExpressionAssign(IROLinear *nd) {
+ IROLinear *right;
+ IROLinear *left;
+
+ return (
+ nd->type == IROLinearOp2Arg &&
+ nd->nodetype == EASS &&
+ (left = nd->u.diadic.left) &&
+ (right = nd->u.diadic.right) &&
+ right->type == IROLinearOperand &&
+ right->u.node &&
+ right->u.node->type == EINTCONST &&
+ (CInt64_Equal(right->u.node->data.intval, cint64_one) || CInt64_Equal(right->u.node->data.intval, cint64_zero)) &&
+ left->type == IROLinearOp1Arg &&
+ left->nodetype == EINDIRECT &&
+ left->u.monadic &&
+ IS_TYPE_POINTER_ONLY(left->u.monadic->rtype) &&
+ left->u.monadic->type == IROLinearOperand &&
+ left->u.monadic->u.node &&
+ left->u.monadic->u.node->type == EOBJREF &&
+ left->u.monadic->u.node->data.objref &&
+ left->u.monadic->u.node->data.objref->datatype == DLOCAL);
+}
+
+static Boolean IsPossibleLogicalExpressionStart(IRONode *fnode, IROLinear *nd) {
+ return
+ fnode->numsucc == 2 &&
+ fnode->last &&
+ (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) &&
+ IsLogicalExpressionAssign(nd);
+}
+
+static Boolean CheckForTopLevelExpressions(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd1, IROLinear *nd2, Boolean flag) {
+ IRONode *fnode;
+ IROLinear *nd;
+ UInt16 i;
+
+ if (fnode1 != fnode3) {
+ if (!Bv_IsBitSet(fnode2->index, fnode1->dom))
+ return 0;
+
+ if (flag) {
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
+ fnode->x3C = 0;
+ } else if (fnode1->x3C) {
+ return 1;
+ }
+ fnode1->x3C = 1;
+
+ for (i = 0; i < fnode1->numsucc; i++) {
+ fnode = IRO_NodeTable[fnode1->succ[i]];
+ if (!CheckForTopLevelExpressions(fnode, fnode2, fnode3, fnode->first, nd2, 0))
+ return 0;
+ }
+ }
+
+ for (nd = nd1; nd && nd != fnode1->last->next; nd = nd->next) {
+ if (nd == nd2)
+ return 1;
+
+ if (nd->type != IROLinearNop && nd->type != IROLinearLabel && !(nd->flags & IROLF_Reffed))
+ return 0;
+ }
+
+ return 1;
+}
+
+static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2) {
+ UInt16 i;
+
+ if (fnode1 && !fnode1->x3C) {
+ fnode1->x3C = 1;
+ IROFlowgraph_sub_4C3880(nodes, fnode1->index);
+ if (fnode1 != fnode2) {
+ for (i = 0; i < fnode1->numsucc; i++)
+ AddNodeAndSuccessorsRecursively(nodes, IRO_NodeTable[fnode1->succ[i]], fnode2);
+ }
+ }
+}
+
+static Boolean RebuildPossibleLogicalExpression(IRONode *fnode, IROLinear *nd) {
+ IROUse *use;
+ IROLinear *nd2;
+ IROLinear *left;
+ IROLinear *right;
+ IRONode *r25;
+ IRONode *r24;
+ ENode *objnode;
+ IRODef *def1;
+ IRODef *def2;
+ UInt32 useCount;
+ UInt32 rewrittenUseCount;
+ Boolean sideEffectFlag;
+ IROLinearType compareType;
+ CLabel *somelab;
+ IRONode *var_68;
+ IRONode *var_6C;
+ CInt64 compareVal;
+ Boolean killedFlag;
+ BitVector *bv1;
+ BitVector *bv2;
+
+ IROLinear *father;
+ IROLinear *iter;
+ IRODef *def;
+ UInt32 i;
+ IROLinear *newlin;
+
+ objnode = nd->u.diadic.left->u.monadic->u.node;
+ if (!objnode->data.objref->varptr)
+ return 0;
+
+ if (CInt64_Equal(nd->u.diadic.right->u.node->data.intval, cint64_zero)) {
+ compareType = IROLinearIfNot;
+ compareVal = cint64_one;
+ } else {
+ compareType = IROLinearIf;
+ compareVal = cint64_zero;
+ }
+
+ var_68 = NULL;
+ def1 = NULL;
+ for (def = objnode->data.objref->varptr->defs; def && !def1; def = def->varnext) {
+ if (def->x18 && def->linear == nd)
+ def1 = def;
+ }
+
+ if (def1) {
+ for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
+ if (use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18)) {
+ if (!var_68) {
+ var_68 = use->node;
+ } else if (Bv_IsBitSet(use->node->index, var_68->dom)) {
+ var_68 = use->node;
+ }
+ }
+ }
+
+ if (var_68) {
+ for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
+ if (use->node != var_68 && use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18) && !Bv_IsBitSet(var_68->index, use->node->dom)) {
+ var_68 = NULL;
+ break;
+ }
+ }
+ }
+ }
+
+ if (
+ !var_68 ||
+ !var_68->first ||
+ var_68->first->type != IROLinearLabel ||
+ !(somelab = var_68->first->u.label.label) ||
+ var_68->numpred != 3
+ )
+ return 0;
+
+ r25 = IRO_NodeTable[var_68->pred[0]];
+ if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[1]]->index, r25->dom)) {
+ r25 = IRO_NodeTable[var_68->pred[1]];
+ } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[1]]->dom)) {
+ return 0;
+ }
+
+ if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[2]]->index, r25->dom)) {
+ r25 = IRO_NodeTable[var_68->pred[2]];
+ } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[2]]->dom)) {
+ return 0;
+ }
+
+ if (
+ !r25 ||
+ !(left = r25->last) ||
+ left->type != compareType ||
+ left->u.label.label != somelab
+ )
+ return 0;
+
+ if (
+ !FindFlowgraphNodeThatStartsWithLabel(left->u.label.label, &var_68, &var_6C) ||
+ !var_6C ||
+ var_6C->numpred != 1 ||
+ !(r24 = IRO_NodeTable[var_6C->pred[0]]) ||
+ !(right = r24->last) ||
+ right->type != compareType ||
+ right->u.label.label != left->u.label.label ||
+ !(nd2 = FindLastDiadicTopLevelAssignmentInFlowgraphNode(var_6C)) ||
+ !IsLogicalExpressionAssign(nd2) ||
+ nd2->u.diadic.left->u.monadic->u.node->data.objref != objnode->data.objref ||
+ !CInt64_Equal(compareVal, nd2->u.diadic.right->u.node->data.intval) ||
+ nd2->rtype != nd->rtype
+ )
+ return 0;
+
+ if (
+ !CheckForTopLevelExpressions(fnode, fnode, r25, nd->next, left, 1) ||
+ !CheckForTopLevelExpressions(r25->nextnode, r25->nextnode, r24, r25->nextnode->first, right, 1) ||
+ !CheckForTopLevelExpressions(r24->nextnode, r24->nextnode, var_6C, right->next, nd2, 1) ||
+ !CheckForTopLevelExpressions(var_6C, var_6C, var_6C, nd2->next, var_68->first, 1)
+ )
+ return 0;
+
+ rewrittenUseCount = 0;
+ useCount = 0;
+ killedFlag = 0;
+ sideEffectFlag = 0;
+ if (!objnode->data.objref->varptr || !(objnode->data.objref->varptr->uses) || !(objnode->data.objref->varptr->defs)) {
+ objnode = NULL;
+ } else {
+ def1 = def2 = NULL;
+ for (def = objnode->data.objref->varptr->defs; def && (!def1 || !def2); def = def->varnext) {
+ if (def->x18 && def->linear == nd)
+ def1 = def;
+ else if (def->x18 && def->linear == nd2)
+ def2 = def;
+ }
+
+ if (!def1 || !def2) {
+ objnode = NULL;
+ } else {
+ for (use = objnode->data.objref->varptr->uses; objnode && use; use = use->varnext) {
+ if (use->x1C) {
+ useCount++;
+ if (Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) {
+ for (i = 0; objnode && i < use->x18->size; i++) {
+ if (i != def1->index && i != def2->index && Bv_IsBitSet(i, use->x18))
+ objnode = NULL;
+ }
+
+ if (objnode && !Bv_IsBitSet(var_68->index, use->node->dom))
+ objnode = NULL;
+
+ if (objnode) {
+ if (RewriteUse(use, objnode, nd2, 0))
+ rewrittenUseCount++;
+ else
+ objnode = NULL;
+ }
+
+ if (objnode) {
+ if (!sideEffectFlag)
+ sideEffectFlag = HasSideEffectsBeforeUse(var_68, var_68, use->node, use->linear, 1);
+
+ if (!killedFlag && (IRO_HasSideEffect(left->u.label.x4) || IRO_HasSideEffect(right->u.label.x4))) {
+ iter = use->linear;
+ if ((father = IRO_LocateFather(use->linear))) {
+ Bv_AllocVector(&bv1, IRO_NumVars + 1);
+ Bv_AllocVector(&bv2, IRO_NumVars + 1);
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ IRO_WalkTree(left->u.label.x4, GetExprKills);
+ IRO_WalkTree(right->u.label.x4, GetExprKills);
+ Bv_Or(IRO_VarKills, bv1);
+ while (father && !killedFlag) {
+ CheckUnorderedRegionsForSideEffectsAndUses(father, iter, bv1, bv2, &killedFlag);
+ iter = father;
+ father = IRO_LocateFather(father);
+ }
+ }
+
+ if (!killedFlag)
+ killedFlag = UsesAKilledVarBeforeUse(var_68, var_68, use->node, use->linear, bv1, 1);
+ }
+ }
+ } else if (Bv_IsBitSet(def1->index, use->x18) || Bv_IsBitSet(def2->index, use->x18))
+ objnode = NULL;
+ }
+ }
+ }
+ }
+
+ if (!objnode)
+ return 0;
+
+ left->type = right->type = IROLinearNop;
+ left->expr = right->expr = NULL;
+
+ IRO_NopOut(nd);
+
+ newlin = IRO_NewLinear(IROLinearOp2Arg);
+ memcpy(newlin, nd2, sizeof(IROLinear));
+ newlin->nodetype = (compareType == IROLinearIf) ? ELOR : ELAND;
+ newlin->index = IRO_NumLinear++;
+ newlin->u.diadic.left = left->u.label.x4;
+ newlin->u.diadic.right = right->u.label.x4;
+ newlin->flags |= IROLF_Reffed;
+ IRO_Paste(newlin, newlin, nd2);
+
+ if (rewrittenUseCount == 1 && !sideEffectFlag && !killedFlag && !objnode->data.objref->varptr->xB) {
+ for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
+ if (use->x1C && Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18))
+ RewriteUse(use, objnode, newlin, 1);
+ }
+
+ if (useCount == 1 && objnode->data.objref->u.var.info) {
+ objnode->data.objref->u.var.info->usage = 0;
+ objnode->data.objref->u.var.info->used = 0;
+ }
+ IRO_NopOut(nd2);
+ def1->x18 = 0;
+ def2->x18 = 0;
+ } else {
+ IRO_NopOut(nd2->u.label.x4);
+ nd2->u.label.x4 = newlin;
+ def1->x18 = 0;
+ }
+
+ if (r24->numpred == 1 && IRO_NodeTable[r24->pred[0]] == r25 && IRO_MergeFlowGraphNodes(r25, r24))
+ r24 = r25;
+ if (var_6C->numpred == 1 && IRO_NodeTable[var_6C->pred[0]] == r24 && IRO_MergeFlowGraphNodes(r24, var_6C))
+ var_6C = r24;
+ if (var_68->numpred == 1 && r24 == r25 && var_6C == r24)
+ IRO_MergeFlowGraphNodes(var_6C, var_68);
+ return 1;
+}
+
+static void RebuildLogicalExpressions(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+ Boolean flag;
+
+ flag = 1;
+ while (flag) {
+ flag = 0;
+ for (fnode = IRO_FirstNode; fnode && fnode->last; fnode = fnode->nextnode) {
+ for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) {
+ if (IsPossibleLogicalExpressionStart(fnode, nd) && RebuildPossibleLogicalExpression(fnode, nd))
+ flag = 1;
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean IsPossibleCondAssStart(IRONode *fnode) {
+ return (fnode->numsucc == 2) && fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot);
+}
+
+static Type *logicalType(void) {
+ if (copts.cplusplus && copts.booltruefalse)
+ return TYPE(&stbool);
+ else
+ return TYPE(&stsignedint);
+}
+
+static Boolean GeneratePossibleCondAss(IRONode *fnode) {
+ IROLinear *r31;
+ IRONode *node2;
+ IRONode *r29;
+ Boolean r28;
+ IRONode *node1;
+ IROLinear *r24;
+ Boolean r23;
+ IROLinear *r19;
+ Boolean r18;
+ IROLinear *r20;
+ Boolean r19flag;
+ IROLinear *r18nd;
+ IROLinear *ass;
+ IROLinear *cond;
+ IROLinear *r16;
+ IROLinear *r15;
+ BitVector *saveVarKills;
+ IROList list;
+ Object *obj;
+ IROLinear *r14;
+
+ if (!fnode || fnode->numsucc != 2 || !fnode->last || (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot))
+ return 0;
+
+ if (IRO_NodeTable[fnode->succ[0]] &&
+ IRO_NodeTable[fnode->succ[0]]->first &&
+ IRO_NodeTable[fnode->succ[0]]->first->type == IROLinearLabel &&
+ IRO_NodeTable[fnode->succ[0]]->first->u.label.label == fnode->last->u.label.label) {
+ node1 = IRO_NodeTable[fnode->succ[0]];
+ node2 = IRO_NodeTable[fnode->succ[1]];
+ } else {
+ node1 = IRO_NodeTable[fnode->succ[1]];
+ if (node1 && node1->first && node1->first->type == IROLinearLabel && node1->first->u.label.label == fnode->last->u.label.label) {
+ node2 = IRO_NodeTable[fnode->succ[0]];
+ } else {
+ return 0;
+ }
+ }
+
+ if (!node2 || node2->numpred != 1 || node2->numsucc != 1 || node2->last->next != node1->first)
+ return 0;
+
+ if (IRO_NodeTable[node2->succ[0]] == node1 && Bv_IsBitSet(fnode->index, node1->dom)) {
+ r28 = 0;
+ } else if (
+ node1->numpred == 1 && node1->numsucc == 1 &&
+ node2->succ[0] == node1->succ[0] &&
+ (r29 = IRO_NodeTable[node2->succ[0]]) &&
+ Bv_IsBitSet(fnode->index, r29->dom) &&
+ node1->last->next == r29->first
+ ) {
+ r28 = 1;
+ } else {
+ return 0;
+ }
+
+ r24 = NULL;
+ if (node2->last) {
+ for (r19 = node2->first; r19 && r19 != node2->last->next; r19 = r19->next) {
+ if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r24) {
+ r24 = r19;
+ } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) {
+ return 0;
+ }
+ }
+ }
+
+ if (
+ !r24 ||
+ (r24->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r24)) ||
+ !r24->u.diadic.left ||
+ r24->u.diadic.left->type != IROLinearOp1Arg ||
+ r24->u.diadic.left->nodetype != EINDIRECT ||
+ !r24->u.diadic.left->u.monadic ||
+ r24->u.diadic.left->u.monadic->type != IROLinearOperand ||
+ !r24->u.diadic.left->u.monadic->u.node ||
+ !r24->u.diadic.left->u.monadic->u.node->rtype ||
+ !IS_TYPE_POINTER_ONLY(r24->u.diadic.left->u.monadic->u.node->rtype) ||
+ !r24->u.diadic.left->u.monadic->u.node->data.monadic
+ )
+ return 0;
+
+ if (r28) {
+ r31 = NULL;
+ if (node1->last) {
+ for (r19 = node1->first; r19 && r19 != node1->last->next; r19 = r19->next) {
+ if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r31) {
+ r31 = r19;
+ } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) {
+ return 0;
+ }
+ }
+ }
+
+ if (
+ !r31 ||
+ (r31->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r31)) ||
+ !r31->u.diadic.left ||
+ r31->u.diadic.left->type != IROLinearOp1Arg ||
+ r31->u.diadic.left->nodetype != EINDIRECT ||
+ !r31->u.diadic.left->u.monadic ||
+ r31->u.diadic.left->u.monadic->type != IROLinearOperand ||
+ !r31->u.diadic.left->u.monadic->u.node ||
+ !r31->u.diadic.left->u.monadic->u.node->rtype ||
+ !IS_TYPE_POINTER_ONLY(r31->u.diadic.left->u.monadic->u.node->rtype) ||
+ !r31->u.diadic.left->u.monadic->u.node->data.monadic
+ )
+ return 0;
+
+ r18 = IRO_ExprsSame(r24->u.diadic.left, r31->u.diadic.left);
+ }
+
+ r23 = fnode->last->type == IROLinearIf;
+ r20 = fnode->last->u.diadic.right;
+ r19flag = 0;
+ if (r28 && copts.opt_common_subs && IRO_IsSubableExpression(r20))
+ r19flag = 1;
+
+ if (r19flag) {
+ IRO_FindDepends(r20);
+ r19flag = !IRO_NotSubable;
+ }
+
+ if (r28) {
+ if (r18) {
+ r19flag = 0;
+ } else if (IRO_HasSideEffect(r20)) {
+ r19flag = 1;
+ } else {
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ IRO_WalkTree(r20, GetExprUses);
+ saveVarKills = IRO_VarKills;
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ IRO_WalkTree(r20, GetExprKills);
+ if (Bv_BitsInCommon(IRO_VarKills, saveVarKills))
+ r19flag = 1;
+ }
+
+ if (r19flag && !copts.opt_common_subs)
+ return 0;
+ }
+
+ if (r19flag) {
+ IRO_InitList(&list);
+ obj = create_temp_object(r20->rtype);
+ IRO_FindVar(obj, 1, 1);
+ ass = IRO_NewLinear(IROLinearOp2Arg);
+ ass->u.diadic.left = IRO_TempReference(obj, &list);
+ ass->rtype = r20->rtype;
+ ass->nodetype = EASS;
+ ass->index = ++IRO_NumLinear;
+ ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.right = r20;
+ IRO_AddToList(ass, &list);
+ IRO_PasteAfter(list.head, list.tail, r20);
+ }
+
+ r16 = r24->u.diadic.left;
+ r15 = r24->u.diadic.right;
+ fnode->last->type = IROLinearNop;
+ fnode->last->expr = NULL;
+ if (node2->last->type == IROLinearGoto) {
+ node2->last->type = IROLinearNop;
+ node2->last->expr = NULL;
+ }
+ if (r28 || node1->numpred == 2) {
+ node1->first->type = IROLinearNop;
+ node1->first->expr = NULL;
+ }
+
+ if (r28 && r18) {
+ if (node1->last->type == IROLinearGoto) {
+ node1->last->type = IROLinearNop;
+ node1->last->expr = NULL;
+ }
+ if (r29->numpred == 2) {
+ r29->first->type = IROLinearNop;
+ r29->first->expr = NULL;
+ }
+
+ cond = IRO_NewLinear(IROLinearOp3Arg);
+ memcpy(cond, r24, sizeof(IROLinear));
+ cond->type = IROLinearOp3Arg;
+ cond->nodetype = ECOND;
+ cond->index = ++IRO_NumLinear;
+ cond->rtype = r16->rtype;
+ cond->flags |= IROLF_Reffed;
+ if (r19flag) {
+ IRO_InitList(&list);
+ r14 = IRO_TempReference(obj, &list);
+ IRO_Paste(list.head, list.tail, r31);
+ } else {
+ r14 = r20;
+ }
+ cond->u.args3.a = r14;
+
+ if (r23) {
+ cond->u.args3.b = r31->u.diadic.right;
+ cond->u.args3.c = r15;
+ } else {
+ cond->u.args3.b = r15;
+ cond->u.args3.c = r31->u.diadic.right;
+ }
+
+ r24->type = IROLinearNop;
+ r24->expr = NULL;
+ IRO_NopOut(r24->u.diadic.left);
+ IRO_Paste(cond, cond, r31);
+ r31->u.diadic.right = cond;
+ } else {
+ r24->type = IROLinearOp3Arg;
+ r24->nodetype = ECONDASS;
+ if (r19flag) {
+ IRO_InitList(&list);
+ r20 = IRO_TempReference(obj, &list);
+ IRO_Paste(list.head, list.tail, r24);
+ }
+ cond = r20;
+ if (r23) {
+ r18nd = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(r18nd, r20, sizeof(IROLinear));
+ r18nd->type = IROLinearOp1Arg;
+ r18nd->nodetype = ELOGNOT;
+ r18nd->index = ++IRO_NumLinear;
+ r18nd->rtype = logicalType();
+ r18nd->u.monadic = r20;
+ r18nd->flags |= IROLF_Reffed;
+ IRO_Paste(r18nd, r18nd, r24);
+ r20 = r18nd;
+ }
+ r24->u.args3.a = r20;
+ r24->u.args3.b = r16;
+ r24->u.args3.c = r15;
+ if (r28) {
+ r15 = r31->u.diadic.left;
+ r16 = r31->u.diadic.right;
+ if (node1->last->type == IROLinearGoto) {
+ node1->last->type = IROLinearNop;
+ node1->last->expr = NULL;
+ }
+ if (r29->numpred == 2) {
+ r29->first->type = IROLinearNop;
+ r29->first->expr = NULL;
+ }
+ r31->type = IROLinearOp3Arg;
+ r31->nodetype = ECONDASS;
+ if (r19flag) {
+ IRO_InitList(&list);
+ cond = IRO_TempReference(obj, &list);
+ IRO_Paste(list.head, list.tail, r31);
+ } else {
+ IRO_InitList(&list);
+ cond = IRO_DuplicateExpr(cond, &list);
+ IRO_Paste(list.head, list.tail, r31);
+ }
+ if (!r23) {
+ r14 = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(r14, cond, sizeof(IROLinear));
+ r14->type = IROLinearOp1Arg;
+ r14->nodetype = ELOGNOT;
+ r14->index = ++IRO_NumLinear;
+ r14->rtype = logicalType();
+ r14->u.monadic = cond;
+ r14->flags |= IROLF_Reffed;
+ IRO_Paste(r14, r14, r31);
+ cond = r14;
+ }
+ r31->u.args3.a = cond;
+ r31->u.args3.b = r15;
+ r31->u.args3.c = r16;
+ }
+ }
+
+ if (IRO_MergeFlowGraphNodes(fnode, node2))
+ node2 = fnode;
+ if ((r28 || node1->numpred == 1) && IRO_MergeFlowGraphNodes(node2, node1))
+ node1 = node2;
+ if (r28 && r29->numpred == 1)
+ IRO_MergeFlowGraphNodes(node1, r29);
+ return 1;
+}
+
+static void GenerateCondAssignments(void) {
+ IRONode *fnode;
+
+ fnode = IRO_FirstNode;
+ while (fnode && fnode->last) {
+ if (IsPossibleCondAssStart(fnode)) {
+ if (!GeneratePossibleCondAss(fnode))
+ fnode = fnode->nextnode;
+ } else {
+ fnode = fnode->nextnode;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+void IRO_RegenerateExpressions(void) {
+ IRO_UpdateFlagsOnInts();
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ IRO_UseDef(0, 0);
+
+ if (copts.optimizationlevel > 0) {
+ IRO_Dump("Rebuilding ELORs and ELANDs\n");
+ RebuildLogicalExpressions();
+ IRO_DumpAfterPhase("RebuildLogicalExpressions", 0);
+ }
+
+ if (copts.optimizationlevel > 0) {
+ IRO_Dump("Rebuilding ECONDs\n");
+ RebuildCondExpressions();
+ IRO_DumpAfterPhase("RebuildCondExpressions", 0);
+ }
+
+ if (copts.optimizationlevel > 0) {
+ IRO_Dump("Generating ECONDASSes\n");
+ GenerateCondAssignments();
+ IRO_DumpAfterPhase("GenerateCondAssignments", 0);
+ }
+}
diff --git a/compiler_and_linker/unsorted/IroFlowgraph.c b/compiler_and_linker/unsorted/IroFlowgraph.c
index e69de29..7b6aa3a 100644
--- a/compiler_and_linker/unsorted/IroFlowgraph.c
+++ b/compiler_and_linker/unsorted/IroFlowgraph.c
@@ -0,0 +1,336 @@
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroCSE.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroPropagate.h"
+#include "compiler/IROUseDef.h"
+#include "compiler/IroUtil.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/Exceptions.h"
+#include "compiler/InlineAsmPPC.h"
+
+UInt16 IRO_NumNodes;
+IRONode *IRO_FirstNode;
+IRONode *IRO_LastNode;
+IRONode *IRO_EndNode;
+IRONode **IRO_NodeTable;
+BitVector *IRO_VarKills;
+BitVector *IRO_Avail;
+BitVector *IRO_FuncKills;
+BitVector *IRO_ExprKills;
+
+static IRONode *StartNode(IROLinear *linear) {
+ IRONode *node = oalloc(sizeof(IRONode));
+
+ node->index = IRO_NumNodes;
+ node->numsucc = 0;
+ node->succ = NULL;
+ node->numpred = 0;
+ node->pred = NULL;
+ node->first = linear;
+ node->last = linear;
+ node->x16 = NULL;
+ node->x1A = NULL;
+ node->x1E = NULL;
+ node->x22 = NULL;
+ node->x26 = 0;
+ node->x2A = NULL;
+ node->dom = NULL;
+ node->nextnode = NULL;
+ node->x36 = 0;
+ node->x37 = 0;
+ node->mustreach = 0;
+ node->x39 = 0;
+ node->loopdepth = 0;
+ node->x3C = 0;
+ node->addressed = NULL;
+
+ IRO_NumNodes++;
+ if (!IRO_FirstNode)
+ IRO_FirstNode = node;
+ else
+ IRO_LastNode->nextnode = node;
+ IRO_LastNode = node;
+ return node;
+}
+
+static void AddSucc(IRONode *a, IRONode *b) {
+ a->succ[a->numsucc++] = b->index;
+ b->numpred++;
+}
+
+static void AddLabelSucc(IRONode *node, CLabel *label) {
+ IRONode *targetnode = (IRONode *) label->stmt;
+ if (targetnode) {
+ AddSucc(node, targetnode);
+ targetnode->x39 = 1;
+ } else {
+#line 126
+ CError_FATAL();
+ }
+}
+
+static void AddSwitchSucc(IRONode *node) {
+ SwitchInfo *info = node->last->u.swtch.info;
+ SwitchCase *curcase = info->cases;
+ SInt32 i = 1;
+
+ while (curcase) {
+ curcase = curcase->next;
+ i++;
+ }
+
+ node->succ = oalloc(sizeof(UInt16) * i);
+ for (curcase = info->cases; curcase; curcase = curcase->next)
+ AddLabelSucc(node, curcase->label);
+ AddLabelSucc(node, info->defaultlabel);
+}
+
+static void AddPred(UInt32 a, UInt16 b) {
+ IRONode *node = IRO_NodeTable[a];
+ node->pred[node->numpred++] = b;
+}
+
+void IRO_ComputeSuccPred(void) {
+ CLabel *label;
+ IRONode *node;
+ SInt32 count;
+ IROLinear *linear;
+ ExceptionAction *action;
+ IAEffects effects;
+ UInt16 i;
+
+ for (label = Labels; label; label = label->next)
+ label->stmt = NULL;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ node->x39 = 0;
+ node->numsucc = 0;
+ node->numpred = 0;
+ node->x36 = 0;
+ node->x37 = 0;
+ if (node->first && node->first->type == IROLinearLabel)
+ node->first->u.label.label->stmt = (Statement *) node;
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (!node->first) {
+ if (node->nextnode) {
+ node->succ = oalloc(sizeof(UInt16));
+ AddSucc(node, node->nextnode);
+ }
+ } else {
+ linear = node->last;
+ next_linear:
+ switch (linear->type) {
+ case IROLinearReturn:
+ case IROLinearEnd:
+ break;
+ case IROLinearGoto:
+ node->succ = oalloc(sizeof(UInt16));
+ AddLabelSucc(node, linear->u.label.label);
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ node->succ = oalloc(sizeof(UInt16) * 2);
+ AddSucc(node, node->nextnode);
+ AddLabelSucc(node, linear->u.label.label);
+ break;
+ case IROLinearSwitch:
+ AddSwitchSucc(node);
+ break;
+ case IROLinearFunccall:
+ count = 1;
+ if (IRO_FunctionCallMightThrowException(linear)) {
+ for (action = linear->stmt->dobjstack; action; action = action->prev) {
+ if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION)
+ count++;
+ }
+ }
+ node->succ = oalloc(sizeof(UInt16) * count);
+ AddSucc(node, node->nextnode);
+ if (IRO_FunctionCallMightThrowException(linear)) {
+ for (action = linear->stmt->dobjstack; action; action = action->prev) {
+ if (action->type == EAT_CATCHBLOCK)
+ AddLabelSucc(node, action->data.catch_block.catch_label);
+ else if (action->type == EAT_SPECIFICATION)
+ AddLabelSucc(node, action->data.specification.unexp_label);
+ }
+ }
+ break;
+ case IROLinearAsm:
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+ node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels));
+ if (!effects.x5)
+ AddSucc(node, node->nextnode);
+ for (i = 0; i < effects.numlabels; i++)
+ AddLabelSucc(node, effects.labels[i]);
+ break;
+ case IROLinearOp2Arg:
+ if (linear->nodetype == ECOMMA) {
+ linear = linear->u.diadic.right;
+ goto next_linear;
+ }
+ default:
+ if (node->nextnode) {
+ node->succ = oalloc(sizeof(UInt16));
+ AddSucc(node, node->nextnode);
+ }
+ }
+ }
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->numpred)
+ node->pred = oalloc(sizeof(UInt16) * node->numpred);
+ else
+ node->pred = NULL;
+ node->numpred = 0;
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ for (i = 0; i < node->numsucc; i++)
+ AddPred(node->succ[i], node->index);
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first && node->first->type == IROLinearLabel) {
+ IROLinear *linear = node->first;
+ do {
+ if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) {
+ node->x39 = 1;
+ break;
+ }
+ } while (linear != node->last && (linear = linear->next));
+ }
+ }
+}
+
+void IRO_ComputeDom(void) {
+ IRONode *node;
+ BitVector *bv;
+ SInt32 i;
+ int repeat;
+
+ Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes);
+ Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom);
+ for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
+ Bv_AllocVector(&node->dom, IRO_NumNodes);
+ Bv_Set(node->dom);
+ }
+
+ Bv_AllocVector(&bv, IRO_NumNodes);
+
+ do {
+ repeat = 0;
+ for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
+ if (node->numpred) {
+ Bv_Set(bv);
+ for (i = 0; i < node->numpred; i++) {
+ Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv);
+ }
+ Bv_SetBit(node->index, bv);
+ } else {
+ Bv_Clear(bv);
+ Bv_SetBit(node->index, bv);
+ }
+
+ if (!Bv_Compare(bv, node->dom)) {
+ Bv_Copy(bv, node->dom);
+ repeat = 1;
+ }
+ }
+ } while (repeat);
+}
+
+void IRO_BuildFlowgraph(IROLinear *linear) {
+ IROLinear *scan;
+ CLabel *label;
+ ExceptionAction *action;
+ IAEffects effects;
+ IRONode *node;
+ SInt32 i;
+ int flag;
+
+ for (label = Labels; label; label = label->next)
+ label->stmt = NULL;
+
+ scan = linear;
+ IRO_NumNodes = 0;
+ IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL;
+ while (scan) {
+ StartNode(scan);
+ if (scan->type == IROLinearLabel)
+ scan->u.label.label->stmt = (Statement *) IRO_LastNode;
+
+ flag = 0;
+ while (!flag && scan->next && !(scan->next->flags & IROLF_1)) {
+ switch (scan->type) {
+ case IROLinearGoto:
+ case IROLinearReturn:
+ case IROLinearEntry:
+ case IROLinearExit:
+ case IROLinearEnd:
+ flag = 1;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ case IROLinearSwitch:
+ flag = 1;
+ skip:
+ if (scan->next->type == IROLinearLabel) {
+ IROLinear *nw = IRO_NewLinear(IROLinearNop);
+ nw->index = ++IRO_NumLinear;
+ nw->next = scan->next;
+ scan->next = nw;
+ }
+ break;
+ case IROLinearFunccall:
+ if (IRO_FunctionCallMightThrowException(scan)) {
+ for (action = scan->stmt->dobjstack; action; action = action->prev) {
+ if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) {
+ flag = 1;
+ goto skip;
+ }
+ }
+ }
+ break;
+ case IROLinearAsm:
+ CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects);
+ if (effects.numlabels)
+ flag = 1;
+ break;
+ }
+ if (!flag)
+ scan = scan->next;
+ }
+
+ if (scan->type == IROLinearEnd)
+ IRO_EndNode = IRO_LastNode;
+ IRO_LastNode->last = scan;
+ scan = scan->next;
+ }
+
+ IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *));
+ memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *));
+ for (node = IRO_FirstNode, i = 0; node; node = node->nextnode)
+ IRO_NodeTable[i++] = node;
+
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ IRO_CheckForUserBreak();
+}
+
+IRONode *IRO_NewFlowGraphNode(void) {
+ IRONode *node = oalloc(sizeof(IRONode));
+ memset(node, 0, sizeof(IRONode));
+ node->index = IRO_NumNodes;
+ IRO_NumNodes++;
+ node->nextnode = NULL;
+ return node;
+}
+
+IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) {
+ // TODO
+}
diff --git a/compiler_and_linker/unsorted/IroJump.c b/compiler_and_linker/unsorted/IroJump.c
index e69de29..e39e3f0 100644
--- a/compiler_and_linker/unsorted/IroJump.c
+++ b/compiler_and_linker/unsorted/IroJump.c
@@ -0,0 +1,267 @@
+#include "compiler/IroJump.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroUtil.h"
+#include "compiler/CFunc.h"
+#include "compiler/Exceptions.h"
+
+static Boolean CheckChain(CLabel **labelptr) {
+ IRONode *node;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) {
+ IROLinear *linear;
+ CLabel *lab;
+ for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) {
+ if (linear->type == IROLinearLabel)
+ lab = linear->u.label.label;
+ }
+
+ if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) {
+ *labelptr = linear->u.label.label;
+ IRO_Dump("Chaining goto at %d\n", linear->index);
+ return 1;
+ }
+
+ if (lab && *labelptr != lab)
+ *labelptr = lab;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+Boolean IRO_DoJumpChaining(void) {
+ IRONode *node;
+ IROLinear *linear;
+ Boolean flag;
+ SwitchInfo *info;
+ SwitchCase *curcase;
+ Boolean result;
+
+ result = 0;
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first) {
+ linear = node->last;
+ switch (linear->type) {
+ case IROLinearGoto:
+ if (CheckChain(&linear->u.label.label))
+ flag = 1;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ if (CheckChain(&linear->u.label.label))
+ flag = 1;
+ break;
+ case IROLinearSwitch:
+ info = linear->u.swtch.info;
+ for (curcase = info->cases; curcase; curcase = curcase->next) {
+ if (CheckChain(&curcase->label))
+ flag = 1;
+ }
+ if (CheckChain(&info->defaultlabel))
+ flag = 1;
+ break;
+ }
+ }
+ }
+ result |= flag;
+ IRO_CheckForUserBreak();
+ } while (flag);
+
+ return result;
+}
+
+void IRO_MakeReachable(IRONode *node) {
+ UInt16 i;
+ Boolean flag;
+
+ node->x36 = 1;
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->x36 && !node->x37) {
+ for (i = 0; i < node->numsucc; i++) {
+ if (!IRO_NodeTable[node->succ[i]]->x36) {
+ flag = 1;
+ IRO_NodeTable[node->succ[i]]->x36 = 1;
+ }
+ }
+ node->x37 = 1;
+ }
+ }
+ } while (flag);
+}
+
+Boolean IRO_RemoveUnreachable(void) {
+ IRONode *node2;
+ IRONode *node1;
+ IROLinear *scan;
+ IROLinear *linear;
+ Boolean result;
+ ExceptionAction **actptr;
+ ExceptionAction *act;
+
+ result = 0;
+ IRO_ComputeSuccPred();
+ IRO_MakeReachable(IRO_FirstNode);
+ node1 = IRO_FirstNode;
+ for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) {
+ if (node2->first && !node2->x36) {
+ IRO_Dump("Removing unreachable code at: %d\n", node2->index);
+ node1->nextnode = node2->nextnode;
+ node1->last->next = node2->last->next;
+ result = 1;
+ for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) {
+ for (scan = IRO_FirstLinear; scan; scan = scan->next) {
+ if (scan->stmt)
+ scan->stmt->marked = 0;
+ }
+
+ for (scan = IRO_FirstLinear; scan; scan = scan->next) {
+ if (scan->stmt && !scan->stmt->marked) {
+ scan->stmt->marked = 1;
+ for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) {
+ if (
+ (act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) ||
+ (act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) {
+ *actptr = act->prev;
+ }
+ }
+ }
+ }
+ }
+ if (node2 == IRO_LastNode)
+ IRO_LastNode = node1;
+ } else {
+ node1 = node2;
+ }
+ }
+
+ if (result) {
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
+
+Boolean IRO_RemoveRedundantJumps(void) {
+ IRONode *node;
+ IROLinear *linear;
+ IROLinear *scan;
+ IROLinear *scan2;
+ SwitchInfo *info;
+ SwitchCase *curcase;
+ Boolean result;
+
+ result = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first) {
+ linear = node->last;
+ switch (linear->type) {
+ case IROLinearGoto:
+ scan = linear->next;
+ while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label)))
+ scan = scan->next;
+ while (1) {
+ if (!scan) break;
+ if (scan->type != IROLinearLabel) break;
+ if (scan->u.label.label == linear->u.label.label) {
+ IRO_Dump("Removing goto next at %d\n", linear->index);
+ linear->type = IROLinearNop;
+ result = 1;
+ break;
+ }
+ scan = scan->next;
+ }
+ break;
+
+ case IROLinearIf:
+ case IROLinearIfNot:
+ scan = linear->next;
+ while (scan && scan->type == IROLinearNop)
+ scan = scan->next;
+ if (scan && scan->type == IROLinearGoto) {
+ scan2 = scan->next;
+ while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
+ scan2 = scan2->next;
+
+ if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) {
+ if (linear->type == IROLinearIf)
+ linear->type = IROLinearIfNot;
+ else
+ linear->type = IROLinearIf;
+
+ linear->u.label.label = scan->u.label.label;
+ scan->type = IROLinearNop;
+ IRO_Dump("Removing branch around goto at %d\n", linear->index);
+ result = 1;
+ }
+ }
+
+ scan2 = linear->next;
+ while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
+ scan2 = scan2->next;
+ while (1) {
+ if (!scan2) break;
+ if (scan2->type != IROLinearLabel) break;
+ if (scan2->u.label.label == linear->u.label.label) {
+ IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index);
+ linear->type = IROLinearNop;
+ IRO_CheckSideEffect(linear->u.label.x4);
+ result = 1;
+ break;
+ }
+ scan2 = scan2->next;
+ }
+ break;
+
+ case IROLinearSwitch:
+ info = linear->u.swtch.info;
+ curcase = info->cases;
+ while (curcase && curcase->label == info->defaultlabel)
+ curcase = curcase->next;
+ if (!curcase) {
+ IRO_Dump("Removing Switch next at %d\n", linear->index);
+ IRO_CheckSideEffect(linear->u.swtch.x4);
+ linear->type = IROLinearGoto;
+ linear->u.label.label = info->defaultlabel;
+ result = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ if (result) {
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
+
+Boolean IRO_RemoveLabels(void) {
+ Boolean result;
+ IRONode *node;
+
+ result = 0;
+ IRO_ComputeSuccPred();
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first && node->first->type == IROLinearLabel && !node->x39) {
+ node->first->type = IROLinearNop;
+ node->first->flags &= ~IROLF_1;
+ result = 1;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
diff --git a/compiler_and_linker/unsorted/IroLinearForm.c b/compiler_and_linker/unsorted/IroLinearForm.c
index e69de29..8b8e305 100644
--- a/compiler_and_linker/unsorted/IroLinearForm.c
+++ b/compiler_and_linker/unsorted/IroLinearForm.c
@@ -0,0 +1,1831 @@
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CParser.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/types.h"
+
+typedef struct NullCheckListNode {
+ SInt32 precompid;
+ Object *tempobj;
+ struct NullCheckListNode *next;
+} NullCheckListNode;
+
+IROLinear *IRO_FirstLinear;
+IROLinear *IRO_LastLinear;
+UInt32 IRO_NumLinear;
+Statement *CurStat;
+static NullCheckListNode *NullCheckList;
+static Statement *CurrStmt;
+static Statement *PrevStmt;
+
+static void LinkLinear(IROLinear *linear) {
+ linear->index = IRO_NumLinear++;
+ if (IRO_FirstLinear)
+ IRO_LastLinear->next = linear;
+ else
+ IRO_FirstLinear = linear;
+ IRO_LastLinear = linear;
+}
+
+IROLinear *IRO_NewLinear(IROLinearType type) {
+ IROLinear *linear = oalloc(sizeof(IROLinear));
+ memset(linear, 0, sizeof(IROLinear));
+ linear->stmt = CurStat;
+ linear->nodetype = EPOSTINC;
+ linear->next = NULL;
+ linear->type = type;
+ linear->rtype = NULL;
+ linear->flags = 0;
+ linear->nodeflags = 0;
+ linear->expr = NULL;
+ linear->x16 = 0;
+ return linear;
+}
+
+static void MarkAssigned(IROLinear *linear, Boolean flag) {
+ IROLinear *inner;
+ IROAddrRecord *rec;
+
+ if (IS_LINEAR_MONADIC(linear, EINDIRECT) && IS_LINEAR_MONADIC(linear->u.monadic, EBITFIELD)) {
+ linear->flags |= IROLF_Assigned;
+ inner = linear->u.monadic->u.monadic;
+ if (inner->type == IROLinearOperand) {
+ inner->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ inner->flags |= IROLF_Used;
+ }
+ }
+
+ if (IS_LINEAR_DIADIC(inner, EADD)) {
+ if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) {
+ if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST))
+ inner->u.diadic.left->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ inner->u.diadic.left->flags |= IROLF_Used;
+ }
+ }
+
+ rec = IRO_InitAddrRecordPointer(inner);
+ IRO_DecomposeAddressExpression(inner, rec);
+ if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) {
+ rec->objRefs->element->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ rec->objRefs->element->flags |= IROLF_Used;
+ }
+ }
+ }
+ }
+
+ if (IS_LINEAR_MONADIC(linear, EINDIRECT)) {
+ linear->flags |= IROLF_Assigned;
+ if (linear->u.monadic->type == IROLinearOperand) {
+ linear->u.monadic->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ linear->u.monadic->flags |= IROLF_Used;
+ }
+ }
+ }
+
+ if (IS_LINEAR_MONADIC(linear, EINDIRECT)) {
+ linear->flags |= IROLF_Assigned;
+ inner = linear->u.monadic;
+
+ if (IS_LINEAR_DIADIC(inner, EADD)) {
+ if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) {
+ if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST))
+ inner->u.diadic.left->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ inner->u.diadic.left->flags |= IROLF_Used;
+ }
+ }
+
+ rec = IRO_InitAddrRecordPointer(inner);
+ IRO_DecomposeAddressExpression(inner, rec);
+ if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) {
+ rec->objRefs->element->flags |= IROLF_Assigned;
+ if (flag) {
+ linear->flags |= IROLF_Used;
+ rec->objRefs->element->flags |= IROLF_Used;
+ }
+ }
+ }
+ }
+}
+
+static void MarkSubscript(IROLinear *linear) {
+ linear->flags |= IROLF_Subs;
+ if (IS_LINEAR_DIADIC(linear, EADD)) {
+ if (IRO_IsAddressMultiply(linear->u.diadic.left) || IS_LINEAR_MONADIC(linear->u.diadic.left, EINDIRECT))
+ linear->u.diadic.left->flags |= IROLF_Subs;
+ if (IRO_IsAddressMultiply(linear->u.diadic.right) || IS_LINEAR_MONADIC(linear->u.diadic.right, EINDIRECT))
+ linear->u.diadic.right->flags |= IROLF_Subs;
+
+ if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD))
+ MarkSubscript(linear->u.diadic.left);
+ if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD))
+ MarkSubscript(linear->u.diadic.right);
+ }
+}
+
+static void MarkArgs(IROLinear *linear) {
+ int i;
+ linear->flags |= IROLF_4000;
+
+ switch (linear->type) {
+ case IROLinearEnd:
+ break;
+ case IROLinearOp1Arg:
+ case IROLinearBeginCatch:
+ case IROLinearEndCatch:
+ case IROLinearEndCatchDtor:
+ MarkArgs(linear->u.monadic);
+ break;
+ case IROLinearOp2Arg:
+ MarkArgs(linear->u.diadic.left);
+ MarkArgs(linear->u.diadic.right);
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ MarkArgs(linear->u.label.x4);
+ break;
+ case IROLinearReturn:
+ if (linear->u.monadic)
+ MarkArgs(linear->u.monadic);
+ break;
+ case IROLinearSwitch:
+ MarkArgs(linear->u.swtch.x4);
+ break;
+ case IROLinearOp3Arg:
+ MarkArgs(linear->u.args3.a);
+ MarkArgs(linear->u.args3.b);
+ MarkArgs(linear->u.args3.c);
+ break;
+ case IROLinearFunccall:
+ MarkArgs(linear->u.funccall.linear8);
+ for (i = 0; i < linear->u.funccall.argCount; i++)
+ MarkArgs(linear->u.funccall.args[i]);
+ break;
+ }
+}
+
+// assumed name, position
+static inline void MarkSubExpr(IROLinear *linear) {
+ int i;
+
+ switch (linear->type) {
+ case IROLinearNop:
+ case IROLinearOperand:
+ case IROLinearGoto:
+ case IROLinearLabel:
+ case IROLinearEntry:
+ case IROLinearExit:
+ case IROLinearAsm:
+ case IROLinearEnd:
+ break;
+ case IROLinearOp1Arg:
+ case IROLinearBeginCatch:
+ case IROLinearEndCatch:
+ case IROLinearEndCatchDtor:
+ linear->u.monadic->flags |= IROLF_Reffed;
+ break;
+ case IROLinearOp2Arg:
+ linear->u.diadic.left->flags |= IROLF_Reffed;
+ linear->u.diadic.right->flags |= IROLF_Reffed;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ linear->u.label.x4->flags |= IROLF_Reffed;
+ break;
+ case IROLinearReturn:
+ if (linear->u.monadic)
+ linear->u.monadic->flags |= IROLF_Reffed;
+ break;
+ case IROLinearSwitch:
+ linear->u.swtch.x4->flags |= IROLF_Reffed;
+ break;
+ case IROLinearOp3Arg:
+ linear->u.args3.a->flags |= IROLF_Reffed;
+ linear->u.args3.b->flags |= IROLF_Reffed;
+ linear->u.args3.c->flags |= IROLF_Reffed;
+ break;
+ case IROLinearFunccall:
+ linear->u.funccall.linear8->flags |= IROLF_Reffed;
+ for (i = 0; i < linear->u.funccall.argCount; i++)
+ linear->u.funccall.args[i]->flags |= IROLF_Reffed;
+ break;
+ default:
+#line 368
+ CError_FATAL();
+ }
+}
+
+static void MarkSubs1(IROLinear *linear) {
+ IROAddrRecord *rec;
+
+ if (IS_LINEAR_MONADIC(linear, EBITFIELD)) {
+ linear = linear->u.monadic;
+ if (IS_LINEAR_ENODE(linear, EOBJREF))
+ linear->flags |= IROLF_Ind;
+ }
+
+ if (IS_LINEAR_DIADIC(linear, EADD)) {
+ if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST))
+ linear->u.diadic.left->flags |= IROLF_Ind;
+
+ rec = IRO_InitAddrRecordPointer(linear);
+ IRO_DecomposeAddressExpression(linear, rec);
+ if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF))
+ rec->objRefs->element->flags |= IROLF_Ind;
+ }
+}
+
+static void MakeLeftChildAsAssignment(ENode *enode) {
+ Statement *stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = enode->data.diadic.left;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void AssignCommaRToTemp(ENode *enode, Boolean flag) {
+ Statement *stmt;
+
+ if (!IS_TYPE_VOID(enode->rtype) && !flag) {
+ Object *obj = create_temp_object(enode->rtype);
+ ENode *indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(obj);
+
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 548
+ CError_FATAL();
+ }
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.diadic.right;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ enode->type = EINDIRECT;
+ enode->data.monadic = create_objectrefnode(obj);
+#line 580
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+ } else {
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = enode->data.diadic.right;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ enode->type = EINTCONST;
+ enode->data.intval = cint64_zero;
+ }
+}
+
+static void AssignDangerousArgumentToTemp(ENode *enode) {
+ Statement *stmt;
+ Object *obj;
+ ENode *indnode;
+ ENode *rightnode;
+
+ obj = create_temp_object(enode->rtype);
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(obj);
+
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 627
+ CError_FATAL();
+ }
+
+ rightnode = IRO_NewENode(enode->type);
+ memcpy(rightnode, enode, sizeof(ENode));
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = rightnode;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ enode->type = EINDIRECT;
+ enode->data.monadic = create_objectrefnode(obj);
+}
+
+static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+ ENode *rightnode;
+
+ *objptr = create_temp_object(enode->rtype);
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 678
+ CError_FATAL();
+ }
+
+ rightnode = IRO_NewENode(EINTCONST);
+ rightnode->data.intval = cint64_zero;
+ rightnode->rtype = enode->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = rightnode;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+ ENode *rightnode;
+
+ *objptr = create_temp_object(enode->rtype);
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 720
+ CError_FATAL();
+ }
+
+ rightnode = IRO_NewENode(EINTCONST);
+ rightnode->data.intval = cint64_one;
+ rightnode->rtype = enode->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = rightnode;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateCondExpression(ENode *enode, CLabel **label) {
+ Statement *stmt;
+
+ *label = IRO_NewLabel();
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFNGOTO;
+ stmt->expr = enode->data.cond.cond;
+ stmt->label = *label;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateGoToStmt(ENode *enode, CLabel **label) {
+ Statement *stmt;
+
+ *label = IRO_NewLabel();
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_GOTO;
+ stmt->label = *label;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void PutTempOnNullCheckList(ENode *expr, Object *obj) {
+ NullCheckListNode *n = lalloc(sizeof(NullCheckListNode));
+ n->precompid = expr->data.nullcheck.precompid;
+ n->tempobj = obj;
+ n->next = NULL;
+ if (NullCheckList) {
+ n->next = NullCheckList;
+ NullCheckList = n;
+ } else {
+ NullCheckList = n;
+ }
+}
+
+static Object *GetTempFromtheList(ENode *expr) {
+ NullCheckListNode *n;
+
+ for (n = NullCheckList; n; n = n->next) {
+ if (n->precompid == expr->data.precompid)
+ break;
+ }
+
+#line 839
+ CError_ASSERT(n);
+ return n->tempobj;
+}
+
+static void GenerateNullcheckExprTempAssignment(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ if (!IS_TYPE_VOID(enode->rtype))
+ *objptr = create_temp_object(enode->rtype);
+ else
+ *objptr = create_temp_object(enode->data.nullcheck.nullcheckexpr->rtype);
+
+ PutTempOnNullCheckList(enode, *objptr);
+
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype))
+ indnode->rtype = enode->rtype;
+ else
+ indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.nullcheck.nullcheckexpr;
+ if (!IS_TYPE_VOID(enode->rtype))
+ stmt->expr->rtype = enode->rtype;
+ else
+ stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype;
+
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ *objptr = create_temp_object(enode->rtype);
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ indnode->rtype = enode->rtype;
+#line 905
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+ }
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.cond.expr1;
+ stmt->expr->rtype = enode->rtype;
+ } else {
+ stmt->expr = enode->data.cond.expr1;
+ }
+
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ indnode->rtype = enode->rtype;
+#line 953
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+ }
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.cond.expr2;
+ stmt->expr->rtype = enode->rtype;
+ } else {
+ stmt->expr = enode->data.cond.expr2;
+ }
+
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ *objptr = create_temp_object(enode->rtype);
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ indnode->rtype = enode->rtype;
+#line 1003
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+ }
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.monadic;
+ stmt->expr->rtype = enode->rtype;
+ } else {
+ stmt->expr = enode->data.monadic;
+ }
+
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateLabel(CLabel **labelptr) {
+ Statement *stmt;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_LABEL;
+ stmt->label = *labelptr;
+ stmt->label->stmt = stmt;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateIfNotTemp(ENode *enode, Object **objptr, CLabel **labelptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype))
+ indnode->rtype = enode->rtype;
+ else
+ indnode->rtype = enode->data.monadic->rtype;
+
+ *labelptr = IRO_NewLabel();
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFNGOTO;
+ stmt->expr = indnode;
+ stmt->label = *labelptr;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void GenerateNullcheckCondExpr(ENode *enode, Object **objptr) {
+ Statement *stmt;
+ ENode *indnode;
+
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype))
+ indnode->rtype = enode->rtype;
+ else
+ indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = enode->data.nullcheck.condexpr;
+ if (!IS_TYPE_VOID(enode->rtype))
+ stmt->expr->rtype = enode->rtype;
+ else
+ stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void TransformLogicalAndLHS(ENode *enode, Object **objptr, CLabel **labelptr) {
+ Statement *stmt;
+
+ *labelptr = IRO_NewLabel();
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFNGOTO;
+ stmt->expr = enode->data.diadic.left;
+ stmt->label = *labelptr;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **labelptr) {
+ Statement *stmt;
+ ENode *indnode;
+ ENode *rightnode;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFNGOTO;
+ stmt->expr = enode->data.diadic.right;
+ stmt->label = *labelptr;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 1225
+ CError_FATAL();
+ }
+
+ rightnode = IRO_NewENode(EINTCONST);
+ rightnode->data.intval = cint64_one;
+ rightnode->rtype = enode->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = rightnode;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_LABEL;
+ stmt->label = *labelptr;
+ stmt->label->stmt = stmt;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ enode->type = EINDIRECT;
+ enode->data.monadic = create_objectrefnode(*objptr);
+#line 1276
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+}
+
+static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) {
+ Statement *stmt;
+
+ *labelptr = IRO_NewLabel();
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFGOTO;
+ stmt->expr = enode->data.diadic.left;
+ stmt->label = *labelptr;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+}
+
+static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelptr) {
+ Statement *stmt;
+ ENode *indnode;
+ ENode *rightnode;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_IFGOTO;
+ stmt->expr = enode->data.diadic.right;
+ stmt->label = *labelptr;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ indnode = IRO_NewENode(EINDIRECT);
+ indnode->data.monadic = create_objectrefnode(*objptr);
+ if (!IS_TYPE_VOID(enode->rtype)) {
+ indnode->rtype = enode->rtype;
+ } else {
+#line 1354
+ CError_FATAL();
+ }
+
+ rightnode = IRO_NewENode(EINTCONST);
+ rightnode->data.intval = cint64_zero;
+ rightnode->rtype = enode->rtype;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = IRO_NewENode(EASS);
+ stmt->expr->data.diadic.left = indnode;
+ stmt->expr->data.diadic.right = rightnode;
+ stmt->expr->rtype = enode->rtype;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = ST_LABEL;
+ stmt->label = *labelptr;
+ stmt->label->stmt = stmt;
+ stmt->dobjstack = CurrStmt->dobjstack;
+ stmt->sourceoffset = CurrStmt->sourceoffset;
+ stmt->sourcefilepath = CurrStmt->sourcefilepath;
+ stmt->value = CurrStmt->value;
+ stmt->flags = CurrStmt->flags;
+
+ if (PrevStmt) {
+ stmt->next = PrevStmt->next;
+ PrevStmt->next = stmt;
+ } else {
+ stmt->next = NULL;
+ }
+ PrevStmt = stmt;
+
+ enode->type = EINDIRECT;
+ enode->data.monadic = create_objectrefnode(*objptr);
+#line 1405
+ CError_ASSERT(!IS_TYPE_VOID(enode->rtype));
+}
+
+static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) {
+ switch (a->type) {
+ 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));
+ }
+ break;
+ ENODE_CASE_DIADIC_1
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBTST:
+ if (a->type == ECOMMA) {
+ LinearizeExpr1(a->data.diadic.left, a, 1, 0);
+ MakeLeftChildAsAssignment(a);
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ AssignCommaRToTemp(a, flag);
+ } else if (a->data.diadic.right->cost >= a->data.diadic.left->cost) {
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ LinearizeExpr1(a->data.diadic.left, a, 0, 0);
+ } else {
+ LinearizeExpr1(a->data.diadic.left, a, 0, 0);
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ }
+ break;
+ ENODE_CASE_ASSIGN
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ LinearizeExpr1(a->data.diadic.left, a, 0, 0);
+ break;
+ case ELAND:
+ case ELOR:
+ if (a->type == ELAND) {
+ CLabel *label;
+ Object *obj;
+ CreateTempAssignmentToZero(a, &obj);
+ LinearizeExpr1(a->data.diadic.left, a, 0, 0);
+ TransformLogicalAndLHS(a, &obj, &label);
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ TransformLogicalAndRHS(a, &obj, &label);
+ } else if (a->type == ELOR) {
+ CLabel *label;
+ Object *obj;
+ CreateTempAssignmentToOne(a, &obj);
+ LinearizeExpr1(a->data.diadic.left, a, 0, 0);
+ TransformLogicalOrLHS(a, &obj, &label);
+ LinearizeExpr1(a->data.diadic.right, a, 0, 0);
+ TransformLogicalOrRHS(a, &obj, &label);
+ }
+ break;
+ case ECOND: {
+ CLabel *label1, *label2;
+ Object *obj;
+ LinearizeExpr1(a->data.cond.cond, a, 0, 0);
+ GenerateCondExpression(a, &label1);
+ LinearizeExpr1(a->data.cond.expr1, a, 0, 0);
+ GenerateExpr1TempAssignment(a, &obj);
+ GenerateGoToStmt(a, &label2);
+ GenerateLabel(&label1);
+ LinearizeExpr1(a->data.cond.expr2, a, 0, 0);
+ GenerateExpr2TempAssignment(a, &obj);
+ GenerateLabel(&label2);
+ if (!IS_TYPE_VOID(a->rtype)) {
+ a->type = EINDIRECT;
+ a->data.monadic = create_objectrefnode(obj);
+#line 1596
+ CError_ASSERT(!IS_TYPE_VOID(a->rtype));
+ } else {
+ a->type = EINTCONST;
+ a->data.intval = cint64_zero;
+ }
+ break;
+ }
+ case EPRECOMP: {
+ Object *temp = GetTempFromtheList(a);
+ a->type = EINDIRECT;
+ a->data.monadic = create_objectrefnode(temp);
+#line 1614
+ CError_ASSERT(!IS_TYPE_VOID(a->rtype));
+ break;
+ }
+ case ENULLCHECK: {
+ CLabel *label;
+ Object *obj;
+ LinearizeExpr1(a->data.nullcheck.nullcheckexpr, a, 0, 0);
+ GenerateNullcheckExprTempAssignment(a, &obj);
+ GenerateIfNotTemp(a, &obj, &label);
+ LinearizeExpr1(a->data.nullcheck.condexpr, a, 0, 0);
+ GenerateNullcheckCondExpr(a, &obj);
+ GenerateLabel(&label);
+ if (!IS_TYPE_VOID(a->rtype)) {
+ a->type = EINDIRECT;
+ a->data.monadic = create_objectrefnode(obj);
+#line 1639
+ CError_ASSERT(!IS_TYPE_VOID(a->rtype));
+ } else {
+ a->type = EINTCONST;
+ a->data.intval = cint64_zero;
+ }
+ break;
+ }
+ case EFUNCCALL:
+ case EFUNCCALLP: {
+ SInt32 count;
+ SInt32 i;
+ ENodeList *list;
+ ENode **arr;
+ SInt16 *arr2;
+
+ IRO_IsLeafFunction = 0;
+
+ list = a->data.funccall.args;
+ count = 0;
+ while (list) {
+ list = list->next;
+ count++;
+ }
+
+ if (count) {
+ arr = oalloc(sizeof(ENode *) * count);
+ list = a->data.funccall.args;
+ count = 0;
+ while (list) {
+ arr[count] = list->node;
+ list = list->next;
+ count++;
+ }
+
+ arr2 = oalloc(sizeof(SInt16) * count);
+ for (i = 0; i < count; i++)
+ arr2[i] = count - i - 1;
+
+ for (i = 0; i < count; i++)
+ LinearizeExpr1(arr[arr2[i]], a, 0, 0);
+ }
+
+ LinearizeExpr1(a->data.funccall.funcref, a, 0, 0);
+ break;
+ }
+
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case ESETCONST:
+ case EVECTOR128CONST:
+ break;
+
+ default:
+#line 1723
+ CError_FATAL();
+ }
+}
+
+static IROLinear *LinearizeExpr(ENode *enode) {
+ IROLinear *linear = NULL;
+
+ switch (enode->type) {
+ ENODE_CASE_MONADIC
+ linear = IRO_NewLinear(IROLinearOp1Arg);
+ linear->u.monadic = LinearizeExpr(enode->data.monadic);
+ linear->nodetype = enode->type;
+ linear->rtype = enode->rtype;
+ linear->nodeflags = enode->flags;
+ if (IRO_IsAssignOp[linear->nodetype])
+ MarkAssigned(linear->u.monadic, 1);
+ if (linear->nodetype == EINDIRECT) {
+ MarkSubs1(linear->u.monadic);
+ linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind;
+ if (IS_LINEAR_DIADIC(linear->u.monadic, EADD))
+ MarkSubscript(linear->u.monadic);
+ }
+ break;
+ ENODE_CASE_DIADIC_1
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBTST:
+ linear = IRO_NewLinear(IROLinearOp2Arg);
+ linear->nodeflags = enode->flags;
+ if (!ENODE_IS(enode, ECOMMA) && enode->data.diadic.right->cost >= enode->data.diadic.left->cost) {
+ linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right);
+ linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left);
+ linear->flags |= IROLF_8000;
+ } else {
+ linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left);
+ linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right);
+ }
+ linear->nodetype = enode->type;
+ linear->rtype = enode->rtype;
+ if (IRO_IsAssignOp[linear->nodetype])
+ MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]);
+ break;
+ ENODE_CASE_ASSIGN
+ linear = IRO_NewLinear(IROLinearOp2Arg);
+ linear->nodeflags = enode->flags;
+ linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right);
+ linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left);
+ linear->flags |= IROLF_8000;
+ linear->nodetype = enode->type;
+ linear->rtype = enode->rtype;
+ MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]);
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ linear = IRO_NewLinear(IROLinearOperand);
+ linear->nodeflags = enode->flags;
+ linear->u.node = enode;
+ linear->rtype = enode->rtype;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP: {
+ SInt32 count;
+ SInt32 i;
+ ENodeList *list;
+ ENode **arr;
+ SInt16 *arr2;
+
+ linear = IRO_NewLinear(IROLinearFunccall);
+ linear->nodeflags = enode->flags;
+ linear->u.funccall.ispascal = enode->type == EFUNCCALLP;
+
+ list = enode->data.funccall.args;
+ count = 0;
+ while (list) {
+ list = list->next;
+ count++;
+ }
+
+ arr = NULL;
+ if (count) {
+ arr = oalloc(sizeof(ENode *) * count);
+ list = enode->data.funccall.args;
+ count = 0;
+ while (list) {
+ arr[count] = list->node;
+ list = list->next;
+ count++;
+ }
+
+ arr2 = oalloc(sizeof(SInt16) * count);
+ for (i = 0; i < count; i++)
+ arr2[i] = count - i - 1;
+
+ for (i = 0; i < count; i++) {
+ arr[arr2[i]] = (ENode *) LinearizeExpr(arr[arr2[i]]);
+ MarkArgs((IROLinear *) arr[arr2[i]]);
+ }
+ }
+
+ linear->u.funccall.argCount = count;
+ linear->u.funccall.args = (IROLinear **) arr;
+ linear->u.funccall.linear8 = LinearizeExpr(enode->data.funccall.funcref);
+ linear->u.funccall.functype = enode->data.funccall.functype;
+ linear->rtype = enode->rtype;
+ break;
+ }
+ default:
+#line 1943
+ CError_FATAL();
+ }
+
+ if (linear)
+ LinkLinear(linear);
+ return linear;
+}
+
+void IRO_PreLinearize(Statement *stmt) {
+ IRO_FirstLinear = IRO_LastLinear = NULL;
+ IRO_NumLinear = 0;
+ CurrStmt = PrevStmt = NULL;
+
+ while (stmt) {
+ CurStat = stmt;
+ CurrStmt = stmt;
+ NullCheckList = NULL;
+
+ switch (stmt->type) {
+ case ST_NOP:
+ case ST_LABEL:
+ case ST_GOTO:
+ break;
+ case ST_OVF:
+#line 1989
+ CError_FATAL();
+ case ST_EXPRESSION:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_SWITCH:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_IFGOTO:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_IFNGOTO:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_RETURN:
+ if (stmt->expr)
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_BEGINCATCH:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_ENDCATCH:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+ case ST_ENDCATCHDTOR:
+ LinearizeExpr1(stmt->expr, NULL, 0, 0);
+ break;
+
+ case ST_EXIT:
+ case ST_ENTRY:
+ case ST_ASM:
+ break;
+
+ default:
+#line 2038
+ CError_FATAL();
+ }
+
+ PrevStmt = stmt;
+ stmt = stmt->next;
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static void MarkAllSubExprs(IROLinear *linear) {
+ IROLinear *scan;
+ int i;
+
+ for (scan = linear; scan; scan = scan->next)
+ scan->flags &= ~IROLF_Reffed;
+
+ for (scan = linear; scan; scan = scan->next)
+ MarkSubExpr(scan);
+}
+
+void IRO_Linearize(Statement *stmt) {
+ IROLinear *linear;
+
+ IRO_FirstLinear = IRO_LastLinear = NULL;
+ IRO_NumLinear = 0;
+
+ while (stmt) {
+ CurStat = stmt;
+ linear = NULL;
+
+ switch (stmt->type) {
+ case ST_NOP:
+ linear = IRO_NewLinear(IROLinearNop);
+ break;
+ case ST_LABEL:
+ linear = IRO_NewLinear(IROLinearLabel);
+ linear->u.label.label = stmt->label;
+ linear->flags |= IROLF_1;
+ break;
+ case ST_GOTO:
+ linear = IRO_NewLinear(IROLinearGoto);
+ linear->u.label.label = stmt->label;
+ break;
+ case ST_EXPRESSION:
+ LinearizeExpr(stmt->expr);
+ break;
+ case ST_SWITCH:
+ linear = IRO_NewLinear(IROLinearSwitch);
+ linear->u.swtch.x4 = LinearizeExpr(stmt->expr);
+ linear->u.swtch.info = (SwitchInfo *) stmt->label;
+ break;
+ case ST_IFGOTO:
+ linear = IRO_NewLinear(IROLinearIf);
+ linear->u.label.x4 = LinearizeExpr(stmt->expr);
+ linear->u.label.label = stmt->label;
+ break;
+ case ST_IFNGOTO:
+ linear = IRO_NewLinear(IROLinearIfNot);
+ linear->u.label.x4 = LinearizeExpr(stmt->expr);
+ linear->u.label.label = stmt->label;
+ break;
+ case ST_RETURN:
+ IRO_FunctionHasReturn = 1;
+ linear = IRO_NewLinear(IROLinearReturn);
+ if (stmt->expr)
+ linear->u.monadic = LinearizeExpr(stmt->expr);
+ else
+ linear->u.monadic = NULL;
+ break;
+ case ST_OVF:
+#line 2143
+ CError_FATAL();
+ break;
+ case ST_EXIT:
+ linear = IRO_NewLinear(IROLinearExit);
+ linear->u.label.label = stmt->label;
+ break;
+ case ST_ENTRY:
+ linear = IRO_NewLinear(IROLinearEntry);
+ linear->u.label.label = stmt->label;
+ linear->flags |= IROLF_1;
+ break;
+ case ST_BEGINCATCH:
+ linear = IRO_NewLinear(IROLinearBeginCatch);
+ linear->u.ctch.linear = LinearizeExpr(stmt->expr);
+ linear->u.ctch.x4 = 0;
+ linear->u.ctch.x8 = 0;
+ break;
+ case ST_ENDCATCH:
+ linear = IRO_NewLinear(IROLinearEndCatch);
+ linear->u.monadic = LinearizeExpr(stmt->expr);
+ break;
+ case ST_ENDCATCHDTOR:
+ linear = IRO_NewLinear(IROLinearEndCatchDtor);
+ linear->u.monadic = LinearizeExpr(stmt->expr);
+ break;
+ case ST_ASM:
+ linear = IRO_NewLinear(IROLinearAsm);
+ linear->u.asm_stmt = stmt;
+ if (copts.optimizewithasm) {
+ IAEffects effects;
+ CodeGen_GetAsmEffects(stmt, &effects);
+ if (effects.x0 || effects.x3)
+ DisableDueToAsm = 1;
+ } else {
+ DisableDueToAsm = 1;
+ }
+ break;
+ default:
+#line 2194
+ CError_FATAL();
+ }
+
+ if (linear)
+ LinkLinear(linear);
+ stmt = stmt->next;
+ }
+
+ linear = IRO_NewLinear(IROLinearEnd);
+ linear->flags |= IROLF_1;
+ LinkLinear(linear);
+
+ MarkAllSubExprs(IRO_FirstLinear);
+ IRO_CheckForUserBreak();
+}
+
+static Statement *NewStatement(IROLinear *linear, StatementType sttype) {
+ Statement *stmt = lalloc(sizeof(Statement));
+ memset(stmt, 0, sizeof(Statement));
+ stmt->type = sttype;
+ stmt->value = 1;
+ if (linear->stmt) {
+ stmt->dobjstack = linear->stmt->dobjstack;
+ stmt->sourceoffset = linear->stmt->sourceoffset;
+ stmt->sourcefilepath = linear->stmt->sourcefilepath;
+ stmt->value = linear->stmt->value;
+ stmt->flags = linear->stmt->flags;
+ } else {
+ stmt->sourceoffset = -1;
+ stmt->sourcefilepath = NULL;
+ }
+ return stmt;
+}
+
+ENode *IRO_NewENode(ENodeType nodetype) {
+ ENode *enode = lalloc(sizeof(ENode));
+ memset(enode, 0, sizeof(ENode));
+ enode->type = nodetype;
+ return enode;
+}
+
+static ENode *BuildExpr(IROLinear *linear) {
+ ENode *enode;
+
+ switch (linear->type) {
+ case IROLinearOperand:
+ enode = IRO_NewENode(linear->u.node->type);
+ enode->flags = linear->nodeflags;
+ *enode = *linear->u.node;
+ break;
+ case IROLinearOp1Arg:
+ enode = IRO_NewENode(linear->nodetype);
+ enode->flags = linear->nodeflags;
+ enode->data.monadic = BuildExpr(linear->u.monadic);
+ enode->rtype = linear->rtype;
+ enode->cost = enode->data.monadic->cost;
+ if (!enode->cost)
+ enode->cost = 1;
+ break;
+ case IROLinearOp2Arg:
+ enode = IRO_NewENode(linear->nodetype);
+ enode->flags = linear->nodeflags;
+ enode->data.diadic.left = BuildExpr(linear->u.diadic.left);
+ enode->data.diadic.right = BuildExpr(linear->u.diadic.right);
+
+ enode->cost = enode->data.diadic.left->cost;
+ if (enode->data.diadic.right->cost > enode->cost)
+ enode->cost = enode->data.diadic.right->cost;
+ else if (enode->data.diadic.right->cost == enode->cost)
+ enode->cost += 1;
+
+ if (ENODE_IS4(enode, ESHL, ESHR, EDIV, EMODULO))
+ enode->cost += 2;
+ if (enode->cost > 200)
+ enode->cost = 200;
+
+ enode->rtype = linear->rtype;
+ break;
+ case IROLinearOp3Arg:
+ enode = IRO_NewENode(linear->nodetype);
+ enode->flags = linear->nodeflags;
+ enode->data.cond.cond = BuildExpr(linear->u.args3.a);
+ enode->data.cond.expr1 = BuildExpr(linear->u.args3.b);
+ enode->data.cond.expr2 = BuildExpr(linear->u.args3.c);
+ enode->rtype = linear->rtype;
+
+ enode->cost = enode->data.cond.cond->cost;
+ if (enode->data.cond.expr1->cost > enode->cost)
+ enode->cost = enode->data.cond.expr1->cost;
+ if (enode->data.cond.expr2->cost > enode->cost)
+ enode->cost = enode->data.cond.expr2->cost;
+ enode->cost += 1;
+
+ if (enode->cost > 200)
+ enode->cost = 200;
+
+ break;
+
+ case IROLinearFunccall: {
+ int i;
+ enode = IRO_NewENode(linear->u.funccall.ispascal ? EFUNCCALLP : EFUNCCALL);
+ enode->flags = linear->nodeflags;
+ enode->data.funccall.funcref = BuildExpr(linear->u.funccall.linear8);
+ enode->data.funccall.functype = linear->u.funccall.functype;
+ enode->data.funccall.args = NULL;
+ enode->cost = 200;
+ for (i = linear->u.funccall.argCount - 1; i >= 0; i--) {
+ ENodeList *list = lalloc(sizeof(ENodeList));
+ list->node = BuildExpr(linear->u.funccall.args[i]);
+ list->next = enode->data.funccall.args;
+ enode->data.funccall.args = list;
+ }
+ enode->rtype = linear->rtype;
+ break;
+ }
+
+ default:
+ IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index);
+#line 2390
+ CError_FATAL();
+ }
+
+ enode->pointsTo = linear->pointsToFunction;
+ return enode;
+}
+
+Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) {
+ IROLinear *scanlin;
+ Statement *firstStmt;
+ Statement *lastStmt;
+ IRONode *scan;
+ Statement *stmt;
+ IRONode mynode;
+
+ firstStmt = lastStmt = NULL;
+
+ if (node) {
+ scan = node;
+ MarkAllSubExprs(IRO_FirstLinear);
+ } else {
+ memset(&mynode, 0, sizeof(IRONode));
+ mynode.first = linear;
+ scan = &mynode;
+ MarkAllSubExprs(linear);
+ }
+
+ while (scan) {
+ for (scanlin = scan->first; scanlin; scanlin = scanlin->next) {
+ stmt = NULL;
+ if (!(scanlin->flags & IROLF_Reffed)) {
+ switch (scanlin->type) {
+ case IROLinearNop:
+ if (scan == node)
+ stmt = NewStatement(scanlin, ST_NOP);
+ else
+ stmt = NULL;
+ break;
+ case IROLinearOperand:
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ case IROLinearOp3Arg:
+ case IROLinearFunccall:
+ stmt = NewStatement(scanlin, ST_EXPRESSION);
+ stmt->expr = BuildExpr(scanlin);
+ break;
+ case IROLinearGoto:
+ stmt = NewStatement(scanlin, ST_GOTO);
+ stmt->label = scanlin->u.label.label;
+ break;
+ case IROLinearExit:
+ stmt = NewStatement(scanlin, ST_EXIT);
+ stmt->label = scanlin->u.label.label;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ stmt = NewStatement(scanlin, (scanlin->type == IROLinearIf) ? ST_IFGOTO : ST_IFNGOTO);
+ stmt->label = scanlin->u.label.label;
+ stmt->expr = BuildExpr(scanlin->u.label.x4);
+ break;
+ case IROLinearReturn:
+ stmt = NewStatement(scanlin, ST_RETURN);
+ if (scanlin->u.monadic)
+ stmt->expr = BuildExpr(scanlin->u.monadic);
+ break;
+ case IROLinearLabel:
+ stmt = NewStatement(scanlin, ST_LABEL);
+ stmt->label = scanlin->u.label.label;
+ stmt->label->stmt = stmt;
+ break;
+ case IROLinearEntry:
+ stmt = NewStatement(scanlin, ST_ENTRY);
+ stmt->label = scanlin->u.label.label;
+ stmt->label->stmt = stmt;
+ break;
+ case IROLinearSwitch:
+ stmt = NewStatement(scanlin, ST_SWITCH);
+ stmt->expr = BuildExpr(scanlin->u.swtch.x4);
+ stmt->label = (CLabel *) scanlin->u.swtch.info;
+ break;
+ case IROLinearBeginCatch:
+ stmt = NewStatement(scanlin, ST_BEGINCATCH);
+ stmt->expr = BuildExpr(scanlin->u.ctch.linear);
+ break;
+ case IROLinearEndCatch:
+ stmt = NewStatement(scanlin, ST_ENDCATCH);
+ stmt->expr = BuildExpr(scanlin->u.monadic);
+ break;
+ case IROLinearEndCatchDtor:
+ stmt = NewStatement(scanlin, ST_ENDCATCHDTOR);
+ stmt->expr = BuildExpr(scanlin->u.monadic);
+ break;
+ case IROLinearAsm:
+ stmt = scanlin->u.asm_stmt;
+ break;
+ case IROLinearEnd:
+ stmt = NULL;
+ break;
+ default:
+#line 2685
+ CError_FATAL();
+ }
+
+ if (stmt) {
+ if (LoopOptimizerRun) {
+ SInt32 i;
+ SInt32 value = 1;
+ for (i = 0; i < scan->loopdepth; i++) {
+ value = (value < 4096) ? (value * 8) : (value + 1);
+ }
+ stmt->value = value;
+ }
+ if (firstStmt)
+ lastStmt->next = stmt;
+ else
+ firstStmt = stmt;
+ lastStmt = stmt;
+ }
+ }
+ if (scanlin == scan->last)
+ break;
+ }
+ scan = scan->nextnode;
+ }
+
+ return firstStmt;
+}
+
+void IRO_RenumberInts(void) {
+ IROLinear *linear = IRO_FirstLinear;
+ IRO_NumLinear = 0;
+ while (linear) {
+ linear->index = IRO_NumLinear++;
+ linear = linear->next;
+ }
+}
+
+static void TravExprToUpdateFlags(IROLinear *linear) {
+ int i;
+
+ linear->flags &= ~(IROLF_Assigned | IROLF_8 | IROLF_Used | IROLF_Ind | IROLF_Subs | IROLF_LoopInvariant | IROLF_Ris | IROLF_Immind | IROLF_CouldError);
+ switch (linear->type) {
+ case IROLinearNop:
+ case IROLinearOperand:
+ break;
+ case IROLinearOp1Arg:
+ TravExprToUpdateFlags(linear->u.monadic);
+ if (IRO_IsAssignOp[linear->nodetype])
+ MarkAssigned(linear->u.monadic, 1);
+ if (linear->nodetype == EINDIRECT) {
+ MarkSubs1(linear->u.monadic);
+ linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind;
+ if (IS_LINEAR_DIADIC(linear->u.monadic, EADD))
+ MarkSubscript(linear->u.monadic);
+ }
+ break;
+ case IROLinearOp2Arg:
+ TravExprToUpdateFlags(linear->u.diadic.left);
+ TravExprToUpdateFlags(linear->u.diadic.right);
+ if (IRO_IsAssignOp[linear->nodetype])
+ MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]);
+ break;
+ case IROLinearOp3Arg:
+ TravExprToUpdateFlags(linear->u.args3.a);
+ TravExprToUpdateFlags(linear->u.args3.b);
+ TravExprToUpdateFlags(linear->u.args3.c);
+ break;
+ case IROLinearFunccall:
+ TravExprToUpdateFlags(linear->u.funccall.linear8);
+ for (i = linear->u.funccall.argCount - 1; i >= 0; i--)
+ TravExprToUpdateFlags(linear->u.funccall.args[i]);
+ break;
+ default:
+ IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index);
+#line 2853
+ CError_FATAL();
+ }
+}
+
+void IRO_UpdateFlagsOnInts(void) {
+ IROLinear *linear;
+ IRONode *node;
+
+ MarkAllSubExprs(IRO_FirstLinear);
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ for (linear = node->first; linear; linear = linear->next) {
+ if (!(linear->flags & IROLF_Reffed)) {
+ switch (linear->type) {
+ case IROLinearOperand:
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ case IROLinearOp3Arg:
+ case IROLinearFunccall:
+ TravExprToUpdateFlags(linear);
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ TravExprToUpdateFlags(linear->u.label.x4);
+ break;
+ case IROLinearReturn:
+ if (linear->u.monadic)
+ TravExprToUpdateFlags(linear->u.monadic);
+ break;
+ case IROLinearSwitch:
+ TravExprToUpdateFlags(linear->u.swtch.x4);
+ break;
+ case IROLinearBeginCatch:
+ TravExprToUpdateFlags(linear->u.ctch.linear);
+ break;
+ case IROLinearEndCatch:
+ TravExprToUpdateFlags(linear->u.monadic);
+ break;
+ case IROLinearEndCatchDtor:
+ TravExprToUpdateFlags(linear->u.monadic);
+ break;
+ case IROLinearNop:
+ case IROLinearGoto:
+ case IROLinearLabel:
+ case IROLinearEntry:
+ case IROLinearExit:
+ case IROLinearAsm:
+ case IROLinearEnd:
+ break;
+ default:
+#line 2931
+ CError_FATAL();
+ }
+ }
+ if (linear == node->last)
+ break;
+ }
+ }
+}
+
+void IRO_SaveLinearIR(IROLinearIRSave *save) {
+ save->firstLinear = IRO_FirstLinear;
+ save->lastLinear = IRO_LastLinear;
+ save->numLinear = IRO_NumLinear;
+ save->curStat = CurStat;
+ save->disableDueToAsm = DisableDueToAsm;
+ save->isLeafFunction = IRO_IsLeafFunction;
+ save->functionHasReturn = IRO_FunctionHasReturn;
+ save->nullCheckList = NullCheckList;
+ save->currStmt = CurrStmt;
+ save->prevStmt = PrevStmt;
+}
+
+void IRO_RestoreLinearIR(IROLinearIRSave *save) {
+ IRO_FirstLinear = save->firstLinear;
+ IRO_LastLinear = save->lastLinear;
+ IRO_NumLinear = save->numLinear;
+ CurStat = save->curStat;
+ DisableDueToAsm = save->disableDueToAsm;
+ IRO_IsLeafFunction = save->isLeafFunction;
+ IRO_FunctionHasReturn = save->functionHasReturn;
+ NullCheckList = save->nullCheckList;
+ CurrStmt = save->currStmt;
+ PrevStmt = save->prevStmt;
+}
+
diff --git a/compiler_and_linker/unsorted/IroLoop.c b/compiler_and_linker/unsorted/IroLoop.c
index e69de29..7f207e6 100644
--- a/compiler_and_linker/unsorted/IroLoop.c
+++ b/compiler_and_linker/unsorted/IroLoop.c
@@ -0,0 +1,2335 @@
+#include "compiler/IroLoop.h"
+#include "compiler/IroCSE.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroPropagate.h"
+#include "compiler/IroSubable.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+IRONode *LoopNode;
+Boolean ConditionalHeaderAtBottom;
+IROLoopInd *FirstInd;
+BitVector *InLoop;
+IROList IRO_InitLList;
+BitVector *InLoop_Exits;
+BitVector *InLoop_Tails;
+UInt32 LoopExitNumber;
+UInt32 LoopTailNum;
+IRONode *LoopExitSuccessor;
+IRONode *LoopTail;
+IROLoopMemRef *IRO_LoopMemRefFirst;
+IROLoopMemRef *IRO_LoopMemRefCurrent;
+static IROExpr *RisList;
+static BitVector *AllKills;
+static Boolean KnownBounds;
+static SInt32 Times;
+static IROLinear *PredInt;
+static IROElmList *FirstAddendLinear;
+static IROElmList *LastAddendLinear;
+static int NoSubableSubs;
+
+// forward decls
+static void MyHandleLoop_Vector(IRONode *fnode);
+static void MyHandleLoop_Motion(IRONode *fnode);
+static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag);
+static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2);
+static void MoveInvarianceInAddressExpr(void);
+static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list);
+static UInt32 IsAssignmentReductionCandidate(IROLinear *nd);
+
+void FindMustReach(void) {
+ IRONode *fnode;
+ IRONode *fnode2;
+ IRONode *pred;
+ int i;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ fnode->mustreach = 0;
+ if (Bv_IsBitSet(fnode->index, InLoop)) {
+ fnode->mustreach = 1;
+
+ for (i = 0; i < LoopNode->numpred; i++) {
+ pred = IRO_NodeTable[LoopNode->pred[i]];
+ if (Bv_IsBitSet(pred->index, InLoop) && !Bv_IsBitSet(fnode->index, pred->dom)) {
+ fnode->mustreach = 0;
+ break;
+ }
+ }
+
+ for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) {
+ if (Bv_IsBitSet(fnode2->index, InLoop)) {
+ for (i = 0; i < fnode2->numsucc; i++) {
+ if (!Bv_IsBitSet(fnode2->succ[i], InLoop) && !Bv_IsBitSet(fnode->index, fnode2->dom)) {
+ fnode->mustreach = 0;
+ break;
+ }
+ }
+
+ if (!fnode->mustreach)
+ break;
+ }
+ }
+ }
+ }
+}
+
+void FindMustReach1(IRONode *checkfnode) {
+ IRONode *fnode;
+ IRONode *fnode2;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop)) {
+ fnode->mustreach1 = 1;
+ for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) {
+ if (Bv_IsBitSet(fnode2->index, InLoop)) {
+ if (Bv_IsBitSet(fnode2->index, InLoop_Tails) && !Bv_IsBitSet(fnode->index, fnode2->dom))
+ fnode->mustreach1 = 0;
+
+ if (Bv_IsBitSet(fnode2->index, InLoop_Exits) && fnode2 != checkfnode && !Bv_IsBitSet(fnode->index, fnode2->dom))
+ fnode->mustreach1 = 0;
+
+ if (!fnode->mustreach1)
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void IRO_FindLoopTailsAndExits(IRONode *fnode) {
+ IRONode *scan;
+ IRONode *succ;
+ int i;
+
+ for (scan = IRO_FirstNode; scan; scan = scan->nextnode) {
+ if (Bv_IsBitSet(scan->index, InLoop)) {
+ for (i = 0; i < scan->numsucc; i++) {
+ succ = IRO_NodeTable[scan->succ[i]];
+ if (succ == fnode) {
+ Bv_SetBit(scan->index, InLoop_Tails);
+ LoopTail = scan;
+ LoopTailNum++;
+ }
+ if (!Bv_IsBitSet(succ->index, InLoop)) {
+ LoopExitNumber++;
+ LoopExitSuccessor = succ;
+ Bv_SetBit(scan->index, InLoop_Exits);
+ }
+ }
+ }
+ }
+
+ IRO_Dump("IRO_FindLoopTailsAndExits:For header %d, Loop exits and loop tails are \n", fnode->index);
+ IRO_DumpBits("Loop Exits: ", InLoop_Exits);
+ IRO_DumpBits("Loop Tails: ", InLoop_Tails);
+ IRO_Dump("LoopExitNum=%d: \n", LoopExitNumber);
+ if (LoopExitSuccessor)
+ IRO_Dump("LoopExitSuccessor node =%d: \n", LoopExitSuccessor->index);
+}
+
+static int IsSafeTypcon(IROLinear *nd) {
+ Type *srcType;
+ Type *destType;
+ SInt32 srcSize;
+ SInt32 destSize;
+ Boolean srcUnsigned;
+ Boolean destUnsigned;
+
+ srcType = nd->u.monadic->rtype;
+ destType = nd->rtype;
+ if (!IS_TYPE_INT(srcType) || !IS_TYPE_INT(destType))
+ return 0;
+
+ srcSize = srcType->size;
+ destSize = destType->size;
+ srcUnsigned = IRO_IsUnsignedType(srcType);
+ destUnsigned = IRO_IsUnsignedType(destType);
+
+ if (srcUnsigned == destUnsigned && destSize >= srcSize)
+ return 1;
+ if (srcUnsigned == 1 && destUnsigned == 0 && destSize > srcSize)
+ return 1;
+ return 0;
+}
+
+static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2, VarRecord **resultVar) {
+ IROLinear *indirect;
+ IROLinear *left;
+ IROLinear *right;
+ Boolean leftInvariant;
+ Boolean rightInvariant;
+ Boolean leftTypcon;
+ Boolean rightTypcon;
+ Object *obj;
+ ENode *enode;
+ IROLoopInd *ind;
+ CInt64 val64;
+ SInt32 val;
+ SInt32 div;
+
+ leftInvariant = 0;
+ rightInvariant = 0;
+ leftTypcon = 0;
+ rightTypcon = 0;
+
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) {
+ leftTypcon = 1;
+ leftInvariant = (left->flags & IROLF_LoopInvariant) != 0;
+ left = left->u.monadic;
+ }
+ if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON) {
+ rightTypcon = 1;
+ rightInvariant = (right->flags & IROLF_LoopInvariant) != 0;
+ right = right->u.monadic;
+ }
+
+ if (((left->flags & IROLF_LoopInvariant) || leftInvariant) && IRO_IsVariable(right)) {
+ if (leftInvariant || ((!(obj = IRO_IsVariable(left)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(left))) {
+ if (
+ left->type == IROLinearOp2Arg &&
+ left->nodetype == EADD &&
+ (obj = IRO_IsVariable(left->u.diadic.left)) &&
+ IRO_IsRegable(obj) &&
+ IRO_IsConstant(left->u.diadic.right)
+ )
+ return 0;
+
+ if (rightTypcon) {
+ if (!IsSafeTypcon(nd->u.diadic.right))
+ return 0;
+ *resultNd2 = nd->u.diadic.right;
+ } else {
+ *resultNd2 = right;
+ }
+
+ indirect = right;
+ *resultNd1 = IRO_NewLinear(IROLinearOperand);
+
+ enode = IRO_NewENode(EINTCONST);
+ enode->data.intval = cint64_one;
+ enode->rtype = nd->u.diadic.right->rtype;
+ (*resultNd1)->rtype = nd->u.diadic.right->rtype;
+ (*resultNd1)->u.node = enode;
+ } else {
+ return 0;
+ }
+ } else if (
+ ((left->flags & IROLF_LoopInvariant) || leftInvariant) &&
+ right->type == IROLinearOp2Arg &&
+ !rightTypcon &&
+ (right->nodetype == EMUL || right->nodetype == ESHL)
+ ) {
+ if (IRO_IsConstant(right->u.diadic.right)) {
+ if (right->nodetype == ESHL) {
+ right->nodetype = EMUL;
+ right->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, right->u.diadic.right->u.node->data.intval);
+ }
+ if (right->u.diadic.left->type == IROLinearOp1Arg) {
+ if (IRO_IsVariable(right->u.diadic.left)) {
+ *resultNd2 = right->u.diadic.left;
+ indirect = right->u.diadic.left;
+ *resultNd1 = right->u.diadic.right;
+ } else if (right->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(right->u.diadic.left->u.monadic)) {
+ if (!IsSafeTypcon(right->u.diadic.left))
+ return 0;
+ *resultNd2 = right->u.diadic.left;
+ indirect = right->u.diadic.left->u.monadic;
+ *resultNd1 = right->u.diadic.right;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else if (
+ ((right->flags & IROLF_LoopInvariant) || rightInvariant) &&
+ left->type == IROLinearOp2Arg &&
+ !leftTypcon &&
+ (left->nodetype == EMUL || left->nodetype == ESHL)
+ ) {
+ if (IRO_IsConstant(left->u.diadic.right)) {
+ if (left->nodetype == ESHL) {
+ left->nodetype = EMUL;
+ left->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, left->u.diadic.right->u.node->data.intval);
+ }
+ if (left->u.diadic.left->type == IROLinearOp1Arg) {
+ if (IRO_IsVariable(left->u.diadic.left)) {
+ *resultNd2 = left->u.diadic.left;
+ indirect = left->u.diadic.left;
+ *resultNd1 = left->u.diadic.right;
+ } else if (left->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(left->u.diadic.left->u.monadic)) {
+ if (!IsSafeTypcon(left->u.diadic.left))
+ return 0;
+ *resultNd2 = left->u.diadic.left;
+ indirect = left->u.diadic.left->u.monadic;
+ *resultNd1 = left->u.diadic.right;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else if (
+ ((right->flags & IROLF_LoopInvariant) || rightInvariant) &&
+ IRO_IsVariable(left)
+ ) {
+ if (rightInvariant || ((!(obj = IRO_IsVariable(right)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(right))) {
+ if (
+ right->type == IROLinearOp2Arg &&
+ right->nodetype == EADD &&
+ (obj = IRO_IsVariable(right->u.diadic.left)) &&
+ IRO_IsRegable(obj) &&
+ IRO_IsConstant(right->u.diadic.right)
+ )
+ return 0;
+
+ if (leftTypcon) {
+ if (!IsSafeTypcon(nd->u.diadic.left))
+ return 0;
+ *resultNd2 = nd->u.diadic.left;
+ } else {
+ *resultNd2 = left;
+ }
+
+ indirect = left;
+ *resultNd1 = IRO_NewLinear(IROLinearOperand);
+
+ enode = IRO_NewENode(EINTCONST);
+ enode->data.intval = cint64_one;
+ enode->rtype = nd->u.diadic.left->rtype;
+ (*resultNd1)->rtype = nd->u.diadic.left->rtype;
+ (*resultNd1)->u.node = enode;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EMUL || nd->nodetype == ESHL) && nd->rtype->size <= 4 && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+
+ if (IRO_IsConstant(right) && IRO_IsVariable(left)) {
+ *resultNd2 = left;
+ indirect = left;
+ *resultNd1 = right;
+ } else if (IRO_IsConstant(nd->u.diadic.right) && left->type == IROLinearOp1Arg && left->nodetype == ETYPCON &&
+ IRO_IsVariable(left->u.monadic)) {
+ if (!IsSafeTypcon(left))
+ return 0;
+ *resultNd2 = left;
+ indirect = left->u.monadic;
+ *resultNd1 = right;
+ } else {
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL)
+ return 0;
+
+ if (nd->u.diadic.right->flags & IROLF_LoopInvariant) {
+ if (IRO_IsVariable(left)) {
+ *resultNd2 = left;
+ indirect = left;
+ *resultNd1 = right;
+ } else if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && IRO_IsVariable(left->u.monadic)) {
+ if (!IsSafeTypcon(left))
+ return 0;
+ *resultNd2 = left;
+ indirect = left->u.monadic;
+ *resultNd1 = right;
+ } else {
+ return 0;
+ }
+ } else if (nd->u.diadic.left->flags & IROLF_LoopInvariant) {
+ if (IRO_IsVariable(right)) {
+ *resultNd2 = right;
+ indirect = right;
+ *resultNd1 = left;
+ } else if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON && IRO_IsVariable(right->u.monadic) && nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) {
+ if (!IsSafeTypcon(right))
+ return 0;
+ *resultNd2 = right;
+ indirect = right->u.monadic;
+ *resultNd1 = left;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EDIV || nd->nodetype == ESHR) && nd->rtype->size <= 4 && IS_TYPE_INT(nd->rtype)) {
+ if (IRO_IsVariable(nd->u.diadic.left) && IRO_IsConstant(nd->u.diadic.right)) {
+ val64 = nd->u.diadic.right->u.node->data.intval;
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHR) {
+ CInt64_GetULong(&val64);
+ if (CInt64_GetULong(&val64) > 32 || CTool_EndianReadWord32(&val64.hi))
+ return 0;
+ val64 = CInt64_Shl(cint64_one, val64);
+ }
+ *resultNd2 = nd->u.diadic.left;
+ indirect = nd->u.diadic.left;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ if (
+ nd->type == IROLinearOp2Arg &&
+ nd->nodetype == ESHL &&
+ (
+ !IRO_IsConstant(*resultNd1) ||
+ (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) < 0 ||
+ (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) > 32 ||
+ CTool_EndianReadWord32(&(*resultNd1)->u.node->data.intval.hi)
+ )
+ )
+ return 0;
+
+#line 802
+ CError_ASSERT(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;
+
+ if (copts.ANSI_strict || copts.opt_strength_reduction_strict) {
+ Type *type = (*resultVar)->object->type;
+ if (IRO_IsUnsignedType(type) && type->size < stunsignedlong.size)
+ return 0;
+ }
+
+ if (nd->type == IROLinearOp2Arg && (nd->nodetype == ESHR || nd->nodetype == EDIV)) {
+ ind = FirstInd;
+ while (ind && ind->var != *resultVar)
+ ind = ind->next;
+
+#line 845
+ CError_ASSERT(ind != NULL);
+
+ if (ind->addNode == NULL) {
+ if (ind->addConst < (val = CInt64_GetULong(&val64)))
+ return 0;
+ if ((div = ind->addConst / val) <= 0)
+ return 0;
+
+ *resultNd1 = IRO_NewLinear(IROLinearOperand);
+ enode = IRO_NewENode(EINTCONST);
+ CInt64_SetULong(&enode->data.intval, div);
+ enode->rtype = nd->u.diadic.left->rtype;
+ (*resultNd1)->rtype = nd->u.diadic.left->rtype;
+ (*resultNd1)->u.node = enode;
+ } else {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void IRO_RemoveExpr_Action(IROLinear *linear, Boolean isFirst) {
+ if (isFirst && linear->expr)
+ IRO_RemoveExpr(linear->expr);
+}
+
+static void IRO_ActUnmarkRISCandidate(IROLinear *linear, Boolean isFirst) {
+ if (isFirst && linear->expr)
+ linear->flags &= ~IROLF_Ris;
+}
+
+static IROExpr *CreateRIS(IROExpr *expr, IROLinear *nd1, IROLinear *nd2, IROLoopInd *induction, int unk) {
+ Object *tempObj;
+ Type *type;
+ Boolean flag23;
+ Object *tempObj2;
+ IROLinear *firstnode;
+ IROLinear *fourthnode;
+ IROLinear *fifthnode;
+ IROLinear *secondnode;
+ IROLinear *thirdnode;
+ IROLinear *tmp;
+ ENode *enode;
+ IROList list1;
+ IROList list2;
+
+ flag23 = 0;
+ type = expr->linear->rtype;
+ tempObj = create_temp_object(type);
+ IRO_FindVar(tempObj, 1, 1);
+ IRO_InitList(&list1);
+
+ if (IS_LINEAR_DIADIC(expr->linear, EADD)) {
+ firstnode = IRO_DuplicateExpr(expr->linear, &list1);
+ } else if (IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) {
+ firstnode = IRO_DuplicateExpr(expr->linear, &list1);
+ } else {
+ firstnode = IRO_NewLinear(IROLinearOp2Arg);
+ firstnode->index = ++IRO_NumLinear;
+ firstnode->rtype = type;
+ firstnode->nodetype = EMUL;
+ firstnode->u.diadic.left = IRO_DuplicateExpr(nd1, &list1);
+ if (unk)
+ firstnode->u.diadic.right = IRO_DuplicateExpr(nd1, &list1);
+ else
+ firstnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list1);
+ IRO_AddToList(firstnode, &list1);
+ }
+
+ secondnode = IRO_NewLinear(IROLinearOp2Arg);
+ secondnode->index = ++IRO_NumLinear;
+ secondnode->rtype = type;
+ secondnode->nodetype = EASS;
+ secondnode->u.diadic.left = IRO_TempReference(tempObj, &list1);
+ secondnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
+ secondnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
+ secondnode->u.diadic.right = firstnode;
+ IRO_AddToList(secondnode, &list1);
+ IRO_Paste(list1.head, list1.tail, PredInt);
+ if (
+ !IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR) &&
+ induction->addConst != 1 &&
+ (induction->addNode || !IRO_IsConstant(nd2))
+ ) {
+ flag23 = 1;
+ IRO_InitList(&list1);
+ thirdnode = IRO_NewLinear(IROLinearOp2Arg);
+ thirdnode->index = ++IRO_NumLinear;
+ thirdnode->rtype = nd2->rtype;
+ thirdnode->nodetype = EMUL;
+
+ if (!induction->addNode) {
+ thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1);
+ thirdnode->u.diadic.right = IRO_NewLinear(IROLinearOperand);
+ thirdnode->u.diadic.right->index = ++IRO_NumLinear;
+ enode = IRO_NewENode(EINTCONST);
+ enode->rtype = nd2->rtype;
+ thirdnode->u.diadic.right->rtype = nd2->rtype;
+ CInt64_SetLong(&enode->data.intval, induction->addConst);
+ thirdnode->u.diadic.right->u.node = enode;
+ IRO_AddToList(thirdnode->u.diadic.right, &list1);
+ } else {
+ thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1);
+ thirdnode->u.diadic.right = IRO_DuplicateExpr(induction->addNode, &list1);
+ if (nd2->rtype != induction->addNode->rtype) {
+ tmp = IRO_NewLinear(IROLinearOp1Arg);
+ tmp->nodetype = ETYPCON;
+ tmp->index = ++IRO_NumLinear;
+ tmp->rtype = nd2->rtype;
+ tmp->u.monadic = thirdnode->u.diadic.right;
+ IRO_AddToList(tmp, &list1);
+ thirdnode->u.diadic.right = tmp;
+ }
+ }
+ IRO_AddToList(thirdnode, &list1);
+
+ tempObj2 = create_temp_object(nd2->rtype);
+
+ fourthnode = IRO_NewLinear(IROLinearOp2Arg);
+ fourthnode->index = ++IRO_NumLinear;
+ fourthnode->rtype = nd2->rtype;
+ fourthnode->nodetype = EASS;
+ fourthnode->u.diadic.left = IRO_TempReference(tempObj2, &list1);
+ fourthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
+ fourthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
+ fourthnode->u.diadic.right = thirdnode;
+ IRO_AddToList(fourthnode, &list1);
+ IRO_Paste(list1.head, list1.tail, PredInt);
+ }
+
+ IRO_InitList(&list2);
+ fifthnode = IRO_NewLinear(IROLinearOp2Arg);
+ fifthnode->index = ++IRO_NumLinear;
+ fifthnode->rtype = type;
+ if (induction->nd->type == IROLinearOp2Arg) {
+ if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, EADD))
+ fifthnode->nodetype = EADDASS;
+ else if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, ESUB))
+ fifthnode->nodetype = ESUBASS;
+ else
+ fifthnode->nodetype = induction->nd->nodetype;
+ } else {
+ if (induction->nd->nodetype == EPREINC || induction->nd->nodetype == EPOSTINC)
+ fifthnode->nodetype = EADDASS;
+ else
+ fifthnode->nodetype = ESUBASS;
+ }
+
+ fifthnode->u.diadic.left = IRO_TempReference(tempObj, &list2);
+ fifthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned;
+ fifthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned;
+ if (!unk) {
+ if (!flag23) {
+ if (induction->addConst == 1 || IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) {
+ fifthnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list2);
+ } else {
+ fifthnode->u.diadic.right = IRO_NewLinear(IROLinearOperand);
+ fifthnode->u.diadic.right->index = ++IRO_NumLinear;
+ enode = IRO_NewENode(EINTCONST);
+ enode->rtype = nd2->rtype;
+ fifthnode->u.diadic.right->rtype = nd2->rtype;
+ CInt64_SetLong(&enode->data.intval, induction->addConst * CInt64_GetULong(&nd2->u.node->data.intval));
+ fifthnode->u.diadic.right->u.node = enode;
+ IRO_AddToList(fifthnode->u.diadic.right, &list2);
+ }
+ } else {
+ fifthnode->u.diadic.right = IRO_TempReference(tempObj2, &list2);
+ fifthnode->u.diadic.right->flags |= IROLF_Used;
+ }
+ }
+
+ fifthnode->index = ++IRO_NumLinear;
+ IRO_AddToList(fifthnode, &list2);
+ IRO_Paste(list2.head, list2.tail, IRO_FindStart(induction->nd));
+ IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action);
+ expr->x8 = tempObj;
+ expr->next = RisList;
+ RisList = expr;
+ return expr;
+}
+
+static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) {
+ IROLinear *labelnode;
+ IRONode *newfnode;
+ IRONode *iter;
+ CLabel *oldlabel;
+ CLabel *newlabel;
+ SwitchInfo *swinfo;
+ SwitchCase *swcase;
+
+ newfnode = oalloc(sizeof(IRONode));
+ memset(newfnode, 0, sizeof(IRONode));
+ newfnode->index = IRO_NumNodes;
+ IRO_NumNodes++;
+
+ labelnode = IRO_NewLinear(IROLinearLabel);
+ labelnode->index = IRO_NumLinear++;
+ labelnode->next = NULL;
+ labelnode->u.label.label = IRO_NewLabel();
+ labelnode->flags |= IROLF_1;
+ labelnode->u.label.label->stmt = (Statement *) newfnode;
+ newfnode->first = labelnode;
+ newfnode->last = labelnode;
+
+ if (fnode2) {
+ fnode2->last->next = labelnode;
+ labelnode->next = IRO_NewLinear(IROLinearNop);
+ labelnode->next->next = fnode1->first;
+ fnode2->nextnode = newfnode;
+ newfnode->nextnode = fnode1;
+ } else {
+#line 1254
+ CError_ASSERT(fnode1->first->type == IROLinearLabel);
+ labelnode->next = IRO_NewLinear(IROLinearGoto);
+ labelnode->next->u.label.label = fnode1->first->u.label.label;
+ IRO_LastNode->last->next = labelnode;
+ IRO_LastNode->nextnode = newfnode;
+ IRO_LastNode = newfnode;
+ IRO_LastLinear = labelnode->next;
+ }
+
+ newfnode->last = labelnode->next;
+
+ IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
+ memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
+ IRO_NodeTable[iter->index] = iter;
+
+ if (fnode1->first->type == IROLinearLabel) {
+ oldlabel = fnode1->first->u.label.label;
+ newlabel = newfnode->first->u.label.label;
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode) {
+ if (!Bv_IsBitSet(iter->index, InLoop) && iter != newfnode) {
+ switch (iter->last->type) {
+ case IROLinearGoto:
+ if (iter->last->u.label.label == oldlabel)
+ iter->last->u.label.label = newlabel;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ if (iter->last->u.label.label == oldlabel)
+ iter->last->u.label.label = newlabel;
+ break;
+ case IROLinearSwitch:
+ swinfo = iter->last->u.swtch.info;
+ for (swcase = swinfo->cases; swcase; swcase = swcase->next) {
+ if (swcase->label == oldlabel)
+ swcase->label = newlabel;
+ }
+ if (swinfo->defaultlabel == oldlabel)
+ swinfo->defaultlabel = newlabel;
+ break;
+ }
+ }
+ }
+ }
+
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ return newfnode;
+}
+
+static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) {
+ IROLinear *labelnode;
+ IRONode *fnode2;
+ IRONode *newfnode;
+ Boolean flag;
+ IRONode *iter;
+ CLabel *oldlabel;
+ CLabel *newlabel;
+ SwitchInfo *swinfo;
+ SwitchCase *swcase;
+ UInt16 i;
+
+#line 1355
+ CError_ASSERT(fnode1 != NULL && LoopExitNumber == 1);
+
+ fnode2 = NULL;
+ flag = 0;
+
+ 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);
+ fnode2 = iter;
+ if (!flag) {
+ if (
+ !iter->last ||
+ !fnode1->first ||
+ fnode1->first->type != IROLinearLabel ||
+ (
+ (iter->last->type == IROLinearIf || iter->last->type == IROLinearIfNot) &&
+ iter->last->u.label.label != fnode1->first->u.label.label
+ ))
+ flag = 1;
+ }
+ }
+ }
+
+#line 1382
+ CError_ASSERT(fnode2 != NULL);
+
+ newfnode = oalloc(sizeof(IRONode));
+ memset(newfnode, 0, sizeof(IRONode));
+ newfnode->index = IRO_NumNodes;
+ IRO_NumNodes++;
+
+ labelnode = IRO_NewLinear(IROLinearLabel);
+ labelnode->index = IRO_NumLinear++;
+ labelnode->next = NULL;
+ labelnode->u.label.label = IRO_NewLabel();
+ labelnode->flags |= IROLF_1;
+ labelnode->u.label.label->stmt = (Statement *) newfnode;
+ newfnode->first = labelnode;
+ newfnode->last = labelnode;
+
+ if (flag) {
+ fnode2->last->next = labelnode;
+ labelnode->next = IRO_NewLinear(IROLinearNop);
+ labelnode->next->next = fnode1->first;
+ fnode2->nextnode = newfnode;
+ newfnode->nextnode = fnode1;
+ } else {
+#line 1422
+ CError_ASSERT(fnode1->first->type == IROLinearLabel);
+ labelnode->next = IRO_NewLinear(IROLinearGoto);
+ labelnode->next->u.label.label = fnode1->first->u.label.label;
+ IRO_LastNode->last->next = labelnode;
+ IRO_LastNode->nextnode = newfnode;
+ IRO_LastNode = newfnode;
+ IRO_LastLinear = labelnode->next;
+ }
+
+ newfnode->last = labelnode->next;
+
+ IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
+ memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
+ IRO_NodeTable[iter->index] = iter;
+
+ if (fnode1->first->type == IROLinearLabel) {
+ oldlabel = fnode1->first->u.label.label;
+ newlabel = newfnode->first->u.label.label;
+ switch (fnode2->last->type) {
+ case IROLinearGoto:
+ if (fnode2->last->u.label.label == oldlabel)
+ fnode2->last->u.label.label = newlabel;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ if (fnode2->last->u.label.label == oldlabel)
+ fnode2->last->u.label.label = newlabel;
+ break;
+ case IROLinearSwitch:
+ swinfo = fnode2->last->u.swtch.info;
+ for (swcase = swinfo->cases; swcase; swcase = swcase->next) {
+ if (swcase->label == oldlabel)
+ swcase->label = newlabel;
+ }
+ if (swinfo->defaultlabel == oldlabel)
+ swinfo->defaultlabel = newlabel;
+ break;
+ }
+ }
+
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ return newfnode;
+}
+
+void AddPreds(IRONode *fnode) {
+ IRONode *pred;
+ int i;
+
+ for (i = 0; i < fnode->numpred; i++) {
+ pred = IRO_NodeTable[fnode->pred[i]];
+ if (!Bv_IsBitSet(pred->index, InLoop)) {
+ Bv_SetBit(pred->index, InLoop);
+ AddPreds(pred);
+ }
+ }
+}
+
+static void RemoveNoopsFromExprList(void) {
+ IROExpr *expr;
+ IROExpr *prev;
+
+ expr = IRO_FirstExpr;
+ prev = NULL;
+ while (expr) {
+ if (expr->linear->type == IROLinearNop) {
+ if (prev)
+ prev->next = expr->next;
+ else
+ IRO_FirstExpr = expr->next;
+ expr = expr->next;
+ } else {
+ prev = expr;
+ expr = expr->next;
+ }
+ }
+}
+
+void IncLoopDepth(void) {
+ IRONode *fnode;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop))
+ fnode->loopdepth++;
+ }
+}
+
+void IRO_SetLoopDepth(void) {
+ IRONode *fnode;
+ IRONode *pred;
+ UInt16 i;
+ UInt16 flag;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
+ fnode->loopdepth = 0;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ flag = 0;
+
+ for (i = 0; i < fnode->numpred; i++) {
+ pred = IRO_NodeTable[fnode->pred[i]];
+ if (Bv_IsBitSet(fnode->index, pred->dom)) {
+ if (!flag) {
+ Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
+ Bv_Clear(InLoop);
+ Bv_SetBit(fnode->index, InLoop);
+ }
+ flag = 1;
+ Bv_SetBit(pred->index, InLoop);
+ if (pred != fnode)
+ AddPreds(pred);
+ }
+ }
+
+ if (flag)
+ IncLoopDepth();
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static void InsertBranchAroundLoopPreheaders(void) {
+ IRONode *fnode;
+ CLabel *label;
+ IRONode *iter;
+ IROLinear *endnode;
+ IROLinear *labelnode;
+
+ if (IRO_EndNode && IRO_EndNode->last && IRO_EndNode->last->type == IROLinearEnd) {
+ label = IRO_NewLabel();
+ fnode = IRO_NewFlowGraphNode();
+ IRO_LastNode->nextnode = fnode;
+ label->stmt = (Statement *) fnode;
+
+ IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
+ memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
+ IRO_NodeTable[iter->index] = iter;
+
+ labelnode = IRO_NewLinear(IROLinearLabel);
+ labelnode->index = ++IRO_NumLinear;
+ labelnode->u.label.label = label;
+ labelnode->flags |= IROLF_1;
+ fnode->first = labelnode;
+ IRO_LastLinear->next = labelnode;
+
+ endnode = IRO_NewLinear(IROLinearEnd);
+ memcpy(endnode, IRO_EndNode->last, sizeof(IROLinear));
+ endnode->index = ++IRO_NumLinear;
+ endnode->next = NULL;
+ fnode->last = endnode;
+ labelnode->next = endnode;
+ IRO_LastLinear = endnode;
+
+ IRO_EndNode->last->type = IROLinearGoto;
+ IRO_EndNode->last->u.label.label = label;
+ IRO_LastNode = fnode;
+ IRO_EndNode = fnode;
+
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+}
+
+void IRO_FindLoops(void) {
+ IRONode *fnode;
+ IRONode *pred;
+ UInt16 i;
+ UInt16 flag;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ flag = 0;
+
+ for (i = 0; i < fnode->numpred; i++) {
+ pred = IRO_NodeTable[fnode->pred[i]];
+ if (Bv_IsBitSet(fnode->index, pred->dom)) {
+ if (!flag) {
+ Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
+ Bv_Clear(InLoop);
+ Bv_SetBit(fnode->index, InLoop);
+ }
+ flag = 1;
+ Bv_SetBit(pred->index, InLoop);
+ if (pred != fnode)
+ AddPreds(pred);
+ }
+ }
+
+ if (flag) {
+ IncLoopDepth();
+ IRO_Dump("IRO_FindLoops:Found loop with header %d\n", fnode->index);
+ IRO_DumpBits("Loop includes: ", InLoop);
+ MyHandleLoop_Motion(fnode);
+ IRO_UpdateFlagsOnInts();
+ MyHandleLoop_Vector(fnode);
+ RemoveNoopsFromExprList();
+ IRO_UpdateFlagsOnInts();
+ IRO_UpdateVars();
+ }
+ }
+
+ if (!IRO_FunctionHasReturn && IRO_EndNode != IRO_LastNode)
+ InsertBranchAroundLoopPreheaders();
+}
+
+static void CheckSubableSub(IROLinear *linear, Boolean isFirst) {
+ if (isFirst && IRO_IsSubableExpression(linear)) {
+ IRO_Dump("Subable Expression is %d\n", linear->index);
+ NoSubableSubs = 0;
+ }
+}
+
+static int NoSubableSubExprs(IROLinear *nd) {
+ NoSubableSubs = 1;
+ IRO_WalkTree(nd, CheckSubableSub);
+ return NoSubableSubs;
+}
+
+void ComputeLoopKills(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+
+ Bv_AllocVector(&AllKills, IRO_NumVars + 1);
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
+ Bv_AllocVector(&fnode->x16, IRO_NumVars + 1);
+ Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1);
+ while (1) {
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(nd);
+ Bv_Or(IRO_VarKills, AllKills);
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+ }
+ }
+}
+
+void ComputeLoopInvariance(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+
+ IRO_Depends = IRO_VarKills;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
+ nd->flags &= ~IROLF_LoopInvariant;
+ while (1) {
+ if ((nd->flags & IROLF_Reffed) && nd->type != IROLinearNop) {
+ IRO_FindDepends_NoAlloc(nd);
+ if (!IRO_IsVolatile && !Bv_BitsInCommon(IRO_Depends, AllKills))
+ nd->flags |= IROLF_LoopInvariant;
+
+ if (IRO_CouldError)
+ nd->flags |= IROLF_CouldError;
+ else
+ nd->flags &= ~IROLF_CouldError;
+ }
+
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+ }
+ }
+}
+
+void ComputeLoopInduction(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+ Boolean flag;
+ Object *obj;
+ Object *obj2;
+ Object *obj3;
+ VarRecord *var;
+ IROLinear *tmpnd;
+ IROLoopInd *ind;
+ Boolean isUnsigned;
+
+ Bv_AllocVector(&AllKills, IRO_NumVars + 1);
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
+ while (1) {
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(nd);
+ Bv_Or(IRO_VarKills, AllKills);
+ flag = 0;
+ if (
+ (
+ nd->type == IROLinearOp2Arg &&
+ nd->rtype->size <= 4 &&
+ (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) &&
+ (obj = IRO_IsVariable(nd->u.diadic.left)) &&
+ obj->type->size == nd->rtype->size &&
+ IS_TYPE_INT(obj->type) &&
+ (
+ (IRO_IsIntConstant(nd->u.diadic.right) && CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval))
+ ||
+ (nd->u.diadic.right->flags & IROLF_LoopInvariant)
+ )
+ )
+ ||
+ (
+ nd->type == IROLinearOp1Arg &&
+ nd->rtype->size <= 4 &&
+ (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) &&
+ (obj = IRO_IsVariable(nd->u.monadic)) &&
+ obj->type->size == nd->rtype->size &&
+ IS_TYPE_INT(obj->type)
+ )
+ )
+ {
+ flag = 1;
+ }
+ else if (
+ nd->type == IROLinearOp2Arg &&
+ nd->rtype->size <= 4 &&
+ nd->nodetype == EASS &&
+ (obj = IRO_IsVariable(nd->u.diadic.left)) &&
+ obj->type->size == nd->rtype->size &&
+ IS_TYPE_INT(obj->type) &&
+ nd->u.diadic.right->type == IROLinearOp2Arg &&
+ (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)
+ )
+ {
+ if (nd->u.diadic.right->nodetype == EADD) {
+ obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left);
+ obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right);
+ if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant))
+ flag = 1;
+
+ if (obj3 == obj && obj2 != obj && (nd->u.diadic.right->u.diadic.left->flags & IROLF_LoopInvariant)) {
+ flag = 1;
+ tmpnd = nd->u.diadic.right->u.diadic.left;
+ nd->u.diadic.right->u.diadic.left = nd->u.diadic.right->u.diadic.right;
+ nd->u.diadic.right->u.diadic.right = tmpnd;
+ }
+ } else {
+ obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left);
+ obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right);
+ if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant))
+ flag = 1;
+ }
+ }
+
+ if (flag) {
+ if ((var = IRO_FindAssigned(nd))) {
+ if (var->xA == 2)
+ var->xA = 0;
+ else if (var->xA == 1)
+ var->xA = 2;
+ }
+ } else {
+ for (var = IRO_FirstVar; var; var = var->next) {
+ if (Bv_IsBitSet(var->index, IRO_VarKills))
+ var->xA = 0;
+ }
+ }
+
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+ }
+ }
+
+ IRO_DumpBits("Killed in loop: ", AllKills);
+
+ for (fnode = IRO_FirstNode, FirstInd = NULL; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
+ while (1) {
+ if (
+ (
+ nd->type == IROLinearOp2Arg &&
+ (nd->nodetype == EADDASS || nd->nodetype == ESUBASS || nd->nodetype == EASS)
+ )
+ ||
+ (
+ nd->type == IROLinearOp1Arg &&
+ (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC)
+ )
+ ) {
+ if ((var = IRO_FindAssigned(nd)) && var->xA == 2 && var->object->type->size <= 4) {
+ ind = oalloc(sizeof(IROLoopInd));
+ ind->fnode = fnode;
+ ind->var = var;
+ ind->nd = nd;
+ ind->next = FirstInd;
+ ind->addNode = NULL;
+ ind->addConst = 0;
+ ind->flags = 0;
+
+ if (nd->type == IROLinearOp2Arg) {
+ isUnsigned = IRO_IsUnsignedType(nd->rtype);
+ if (IRO_IsIntConstant(nd->u.diadic.right)) {
+ CInt64 val = nd->u.diadic.right->u.node->data.intval;
+ if (IS_LINEAR_DIADIC(nd, EADDASS) && CInt64_Less(val, cint64_zero)) {
+ nd->nodetype = ESUBASS;
+ nd->u.diadic.right->u.node->data.intval = CInt64_Neg(val);
+ }
+ if (isUnsigned) {
+ CInt64_ConvertUInt32(&nd->u.diadic.right->u.node->data.intval);
+ ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval);
+ } else {
+ CInt64_ConvertInt32(&nd->u.diadic.right->u.node->data.intval);
+ ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval);
+ }
+ ind->addNode = NULL;
+ } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) {
+ ind->addNode = nd->u.diadic.right;
+ } else if (nd->nodetype == EASS) {
+ ind->addNode = nd->u.diadic.right->u.diadic.right;
+ }
+ } else {
+ if (IS_TYPE_POINTER_ONLY(nd->rtype))
+ ind->addConst = TPTR_TARGET(nd->rtype)->size;
+ else
+ ind->addConst = 1;
+ ind->addNode = NULL;
+ }
+
+ FirstInd = ind;
+
+ if (IS_LINEAR_DIADIC_2(nd, EADDASS, ESUBASS)) {
+ if (nd->u.diadic.right->flags & IROLF_LoopInvariant)
+ IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name);
+ else
+ IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name);
+ } else if (nd->type == IROLinearOp2Arg && (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)) {
+ IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name);
+ } else {
+ IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name);
+ }
+ }
+ }
+
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+ }
+ }
+}
+
+static void IRO_ActUnmarkLoopInvariance(IROLinear *linear, Boolean isFirst) {
+ if (isFirst)
+ linear->flags &= ~IROLF_LoopInvariant;
+}
+
+static void UnmarkSubexpressionsOfInvariantExpressions(void) {
+ IROExpr *expr;
+
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (
+ Bv_IsBitSet(expr->node->index, InLoop) &&
+ !expr->notSubable &&
+ (!expr->couldError || expr->node->mustreach) &&
+ (expr->linear->flags & IROLF_LoopInvariant)
+ ) {
+ IRO_WalkTree(expr->linear, IRO_ActUnmarkLoopInvariance);
+ expr->linear->flags |= IROLF_LoopInvariant;
+ }
+ }
+}
+
+static void MyHandleLoop_Vector(IRONode *fnode) {
+ IRONode *pred;
+ UInt16 i;
+ IROExpr *expr;
+ IROExpr *removedExprs;
+ IROExpr *exprnext;
+ IROLoopInd *induction;
+ IROExpr *exprinner;
+ Boolean flag24;
+ IRONode *v2;
+ IRONode *node22;
+ int flag21;
+ IRONode *iter;
+ IROExpr *searchris;
+ IROLinear *reduceNd1;
+ VarRecord *var;
+ IROLinear *reduceNd2;
+
+ IRO_FirstExpr = NULL;
+ LoopNode = fnode;
+ FindMustReach();
+
+ for (var = IRO_FirstVar; var; var = var->next)
+ var->xA = 1;
+
+ ComputeLoopKills();
+ ComputeLoopInvariance();
+ ComputeLoopInduction();
+ LoopNode = fnode;
+ ConditionalHeaderAtBottom = 0;
+
+ v2 = NULL;
+ flag21 = 0;
+ node22 = NULL;
+ for (i = 0; i < LoopNode->numpred; i++) {
+ pred = IRO_NodeTable[LoopNode->pred[i]];
+ if (!Bv_IsBitSet(pred->index, InLoop)) {
+ if (flag21)
+ node22 = NULL;
+ else
+ node22 = pred;
+ flag21 = 1;
+ if (pred->nextnode == fnode) {
+#line 2880
+ CError_ASSERT(v2 == NULL || pred == v2);
+ v2 = pred;
+ }
+ }
+ }
+
+ if (!flag21) {
+ IRO_Dump("No predecessor outside the loop\n");
+ return;
+ }
+
+ if (!node22 || node22->last->type != IROLinearGoto)
+ node22 = CreatePreHeader(fnode, v2);
+ PredInt = node22->last;
+
+ if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) {
+ if (!KnownBounds || !Times) {
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
+ iter->mustreach = 0;
+ } else {
+ PredInt->u.label.label = LoopNode->first->u.label.label;
+ IRO_ComputeSuccPred();
+ }
+ }
+
+ if (copts.opt_loop_invariants || copts.opt_strength_reduction) {
+ MoveInvarianceInAddressExpr();
+ IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0);
+ IRO_FindExpressions(InLoop, 1);
+ IRO_DumpExprs();
+ }
+
+ if (copts.opt_loop_invariants)
+ UnmarkSubexpressionsOfInvariantExpressions();
+
+ if (!copts.optimize_for_size && copts.opt_strength_reduction) {
+ for (expr = IRO_FirstExpr; expr; expr = expr->next) {
+ if (
+ !(expr->x0 & 4) &&
+ Bv_IsBitSet(expr->node->index, InLoop) &&
+ !expr->notSubable &&
+ (!expr->couldError || expr->node->mustreach) &&
+ Reducable(expr->linear, &reduceNd1, &reduceNd2, &var)
+ ) {
+ IRO_WalkTree(expr->linear, IRO_ActUnmarkRISCandidate);
+ expr->linear->flags |= IROLF_Ris;
+ expr->x1A = reduceNd1;
+ expr->x1E = var;
+ expr->x22 = reduceNd2;
+ }
+ }
+ }
+
+ if (!copts.optimize_for_size && copts.opt_strength_reduction) {
+ RisList = NULL;
+ for (expr = IRO_FirstExpr; expr; expr = exprnext) {
+ exprnext = expr->next;
+ if (!(expr->x0 & 4) && (expr->linear->flags & IROLF_Ris)) {
+ reduceNd1 = expr->x1A;
+ var = expr->x1E;
+ reduceNd2 = expr->x22;
+
+ induction = FirstInd;
+ while (induction && induction->var != var)
+ induction = induction->next;
+#line 3529
+ CError_ASSERT(induction != NULL);
+
+ IRO_FindDepends(reduceNd1);
+ if (!Bv_BitsInCommon(IRO_Depends, AllKills)) {
+ IRO_Dump("Found reduction in strength: %d\n", expr->linear->index);
+ if (IS_LINEAR_DIADIC(expr->linear, ESHL)) {
+ expr->linear->nodetype = EMUL;
+ CInt64_SetULong(&reduceNd1->u.node->data.intval, 1 << CInt64_GetULong(&reduceNd1->u.node->data.intval));
+ reduceNd1->u.node->rtype = expr->linear->rtype;
+ }
+
+ searchris = RisList;
+ while (1) {
+ if (!searchris)
+ break;
+ if (IRO_ExprsSame(expr->linear, searchris->linear))
+ break;
+ searchris = searchris->next;
+ }
+
+ if (searchris) {
+ IRO_Dump("Using existing RIS: %d\n", searchris->linear->index);
+ IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action);
+ } else {
+ searchris = CreateRIS(expr, reduceNd2, reduceNd1, induction, 0);
+ }
+ IRO_ReplaceReference(expr->linear, searchris->x8, expr->linear);
+ IRO_ClipExpr(expr);
+ }
+ }
+ }
+ }
+
+ RisList = NULL;
+
+ expr = IRO_FirstExpr;
+ removedExprs = NULL;
+ if (copts.opt_loop_invariants) {
+ while (expr) {
+ exprnext = expr->next;
+ flag24 = 0;
+
+ if (
+ Bv_IsBitSet(expr->node->index, InLoop) &&
+ !expr->notSubable &&
+ (!expr->couldError || expr->node->mustreach) &&
+ (expr->linear->flags & IROLF_LoopInvariant) &&
+ !(expr->x0 & 4)
+ ) {
+ IRO_Dump("Found loop invariant: %d\n", expr->linear->index);
+
+ for (exprinner = removedExprs; exprinner; exprinner = exprinner->next) {
+ if (IRO_ExprsSame(exprinner->linear, expr->linear)) {
+ IRO_ReplaceReference(expr->linear, exprinner->x8, expr->linear);
+ IRO_NopOut(expr->linear);
+ IRO_Dump("Using already removed expr: %d\n", exprinner->linear->index);
+ IRO_RemoveExpr(expr);
+ flag24 = 1;
+ }
+ }
+
+ if (!flag24 && !expr->x8) {
+ IRO_GetTemp(expr);
+ IRO_ReplaceReference(expr->linear, expr->x8, expr->linear);
+ IRO_MoveExpression(expr, PredInt);
+ IRO_AssignToTemp(expr);
+ IRO_RemoveExpr(expr);
+ expr->next = removedExprs;
+ removedExprs = expr;
+ }
+ }
+
+ expr = exprnext;
+ }
+ }
+}
+
+static void MyHandleLoop_Motion(IRONode *fnode) {
+ IROLoopMemRef *memref;
+ IRONode *pred;
+ UInt16 i;
+ IRONode *v2;
+ IRONode *node21;
+ Object *tempobj;
+ int flag20;
+ IRONode *iter;
+ IROLinear *ass;
+ VarRecord *var;
+ Boolean checkflag;
+ IROLoop *loop;
+ IROList list;
+ IROElmList *refiter;
+
+ IRO_FirstExpr = NULL;
+ LoopNode = fnode;
+ FindMustReach();
+
+ for (var = IRO_FirstVar; var; var = var->next)
+ var->xA = 1;
+
+ ComputeLoopKills();
+ ComputeLoopInvariance();
+ ComputeLoopInduction();
+ LoopNode = fnode;
+ ConditionalHeaderAtBottom = 0;
+
+ v2 = NULL;
+ flag20 = 0;
+ node21 = NULL;
+ for (i = 0; i < LoopNode->numpred; i++) {
+ pred = IRO_NodeTable[LoopNode->pred[i]];
+ if (!Bv_IsBitSet(pred->index, InLoop)) {
+ if (flag20)
+ node21 = NULL;
+ else
+ node21 = pred;
+ flag20 = 1;
+ if (pred->nextnode == fnode) {
+#line 3880
+ CError_ASSERT(v2 == NULL || pred == v2);
+ v2 = pred;
+ }
+ }
+ }
+
+ if (!flag20) {
+ IRO_Dump("No predecessor outside the loop\n");
+ return;
+ }
+
+ if (!node21 || node21->last->type != IROLinearGoto)
+ node21 = CreatePreHeader(fnode, v2);
+ PredInt = node21->last;
+
+ if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) {
+ if (!KnownBounds || !Times) {
+ for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
+ iter->mustreach = 0;
+ } else {
+ PredInt->u.label.label = LoopNode->first->u.label.label;
+ IRO_ComputeSuccPred();
+ }
+ }
+
+ if (copts.opt_loop_invariants || copts.opt_strength_reduction) {
+ MoveInvarianceInAddressExpr();
+ IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0);
+ IRO_FindExpressions(InLoop, 0);
+ IRO_DumpExprs();
+ }
+
+ if (copts.opt_loop_invariants)
+ UnmarkSubexpressionsOfInvariantExpressions();
+
+ checkflag = 1;
+ Bv_AllocVector(&InLoop_Exits, IRO_NumNodes + 1);
+ Bv_AllocVector(&InLoop_Tails, IRO_NumNodes + 1);
+ LoopExitNumber = 0;
+ LoopExitSuccessor = NULL;
+ LoopTailNum = 0;
+ LoopTail = NULL;
+ IRO_FindLoopTailsAndExits(fnode);
+ FindMustReach1(fnode);
+
+ loop = NULL;
+ if (LoopTailNum == 1) {
+ if (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot)
+ loop = ExtractLoopInfo(fnode);
+ else if (LoopTail->last->type == IROLinearIf || LoopTail->last->type == IROLinearIfNot)
+ loop = ExtractLoopInfo(LoopTail);
+ }
+
+ if (loop && !(loop->flags & LP_IFEXPR_NON_CANONICAL) && LoopExitNumber == 1) {
+ IRO_LoopMemRefFirst = NULL;
+ IRO_LoopMemRefCurrent = NULL;
+ CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag);
+ CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag);
+ if (checkflag) {
+ for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
+ if (memref->flags & LoopMemRef_10)
+ memref->flags |= LoopMemRef_8;
+ }
+
+ for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
+ IRO_Dump("Loop Motion Candidate:: Int= %d", memref->nd->index);
+ if (memref->flags & LoopMemRef_8)
+ IRO_Dump("<invalid>");
+ if (memref->flags & LoopMemRef_1)
+ IRO_Dump("<load>");
+ if (memref->flags & LoopMemRef_2)
+ IRO_Dump("<store>");
+ IRO_Dump("\n");
+
+ if (!(memref->flags & LoopMemRef_8)) {
+ tempobj = create_temp_object(memref->nd->rtype);
+ IRO_FindVar(tempobj, 1, 1);
+ if (IRO_FindVar(((IROLinear *) memref->rec->objRefs->element)->u.node->data.objref, 0, 1)) {
+ IRO_InitList(&list);
+ ass = IRO_NewLinear(IROLinearOp2Arg);
+ ass->index = ++IRO_NumLinear;
+ ass->rtype = memref->nd->rtype;
+ ass->nodetype = EASS;
+ ass->u.diadic.left = IRO_TempReference(tempobj, &list);
+ ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.right = IRO_DuplicateExpr(memref->nd, &list);
+ IRO_AddToList(ass, &list);
+ IRO_Paste(list.head, list.tail, PredInt);
+ } else {
+#line 4123
+ CError_FATAL();
+ }
+
+ if (LoopExitSuccessor->numpred != 1)
+ LoopExitSuccessor = CreateNewLoopExitSuccessor(LoopExitSuccessor);
+
+ IRO_InitList(&list);
+ ass = IRO_NewLinear(IROLinearOp2Arg);
+ ass->index = ++IRO_NumLinear;
+ ass->rtype = memref->nd->rtype;
+ ass->nodetype = EASS;
+ ass->u.diadic.left = IRO_DuplicateExpr(memref->nd, &list);
+ ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
+ ass->u.diadic.right = IRO_TempReference(tempobj, &list);
+ IRO_AddToList(ass, &list);
+
+ if (LoopExitSuccessor->first->type == IROLinearLabel)
+ IRO_PasteAfter(list.head, list.tail, LoopExitSuccessor->first);
+ else
+ IRO_Paste(list.head, list.tail, LoopExitSuccessor->first);
+
+ for (refiter = memref->list; refiter; refiter = refiter->next) {
+ IRO_Dump("Loop Motion Candidate Reference at Int= %d\n", ((IROLinear *) refiter->element)->index);
+ IRO_InitList(&list);
+ IRO_TempReference(tempobj, &list);
+ IRO_Paste(list.head, list.tail, refiter->element);
+ IRO_LocateFather_Cut_And_Paste(refiter->element, list.tail);
+ }
+ }
+ }
+ }
+ }
+
+ IRO_DumpAfterPhase("After Motion", 0);
+}
+
+static Boolean CheckLoopAddress(IROLinear *nd, Boolean mustreach1) {
+ IROLoopMemRef *memref;
+ IROAddrRecord *rec;
+ IROAddrRecord *otherrec;
+ IROLinear *inner;
+ IROElmList *list;
+ Boolean flag;
+
+ inner = nd->u.monadic;
+ rec = IRO_InitAddrRecordPointer(inner);
+ if (IS_LINEAR_ENODE(inner, EOBJREF)) {
+ rec->numObjRefs++;
+ IRO_AddElmToList(inner, &rec->objRefs);
+ } else if (IS_LINEAR_DIADIC(inner, EADD)) {
+ IRO_DecomposeAddressExpression(inner, rec);
+ } else {
+ return 0;
+ }
+
+ if (rec->numObjRefs != 1)
+ return 0;
+
+ flag = (nd->flags & IROLF_CouldError) || !(nd->flags & IROLF_Reffed);
+ if (!IRO_LoopMemRefFirst) {
+ MakeLoopEntry(nd, rec, mustreach1, flag);
+ } else {
+ for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
+ otherrec = memref->rec;
+ if (((IROLinear *) rec->objRefs->element)->u.node->data.objref == ((IROLinear *) otherrec->objRefs->element)->u.node->data.objref) {
+ if (IRO_ExprsSame(inner, otherrec->linear)) {
+ list = oalloc(sizeof(IROElmList));
+ list->element = nd;
+ list->next = NULL;
+ if (!memref->list) {
+ memref->list = list;
+ } else {
+ list->next = memref->list;
+ memref->list = list;
+ }
+ } else {
+ memref->flags |= LoopMemRef_8;
+ }
+
+ if (!mustreach1 && flag)
+ memref->flags |= LoopMemRef_8;
+ if (mustreach1 || flag)
+ memref->flags &= ~LoopMemRef_10;
+ break;
+ }
+ }
+
+ if (!memref)
+ MakeLoopEntry(nd, rec, mustreach1, flag);
+ }
+
+ return 1;
+}
+
+static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag) {
+ IROLinear *nd;
+ Boolean flag;
+
+ flag = *resultFlag;
+ while (fnode) {
+ if (Bv_IsBitSet(fnode->index, bv) && (nd = fnode->first)) {
+ while (flag) {
+ if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT)
+ flag = CheckLoopAddress(nd, fnode->mustreach1);
+ else if (nd->type == IROLinearFunccall)
+ flag = 0;
+
+ if (nd == fnode->last)
+ break;
+ nd = nd->next;
+ }
+
+ if (!flag)
+ break;
+ }
+ fnode = fnode->nextnode;
+ }
+ *resultFlag = flag;
+}
+
+static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2) {
+ IROElmList *list;
+
+ if (!IRO_IsRegable(((IROLinear *) rec->objRefs->element)->u.node->data.objref) &&
+ (nd->u.monadic->flags & IROLF_LoopInvariant) &&
+ !IRO_HasSideEffect(nd)) {
+ if (!IRO_LoopMemRefFirst) {
+ IRO_LoopMemRefCurrent = IRO_LoopMemRefFirst = oalloc(sizeof(IROLoopMemRef));
+ } else {
+ IRO_LoopMemRefCurrent->next = oalloc(sizeof(IROLoopMemRef));
+ IRO_LoopMemRefCurrent = IRO_LoopMemRefCurrent->next;
+ }
+ IRO_LoopMemRefCurrent->flags = LoopMemRef_10;
+ IRO_LoopMemRefCurrent->nd = nd;
+ IRO_LoopMemRefCurrent->rec = rec;
+ IRO_LoopMemRefCurrent->next = NULL;
+ IRO_LoopMemRefCurrent->list = NULL;
+
+ list = oalloc(sizeof(IROElmList));
+ list->element = nd;
+ list->next = NULL;
+ if (!IRO_LoopMemRefCurrent->list) {
+ IRO_LoopMemRefCurrent->list = list;
+ } else {
+ list->next = IRO_LoopMemRefCurrent->list;
+ IRO_LoopMemRefCurrent->list = list;
+ }
+
+ if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Assigned) {
+ IRO_LoopMemRefCurrent->flags |= LoopMemRef_2;
+ if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Used)
+ IRO_LoopMemRefCurrent->flags |= LoopMemRef_1;
+ } else {
+ IRO_LoopMemRefCurrent->flags |= LoopMemRef_1;
+ }
+
+ if (!mustreach1 && flag2)
+ IRO_LoopMemRefCurrent->flags |= LoopMemRef_8;
+
+ if (mustreach1 || flag2)
+ IRO_LoopMemRefCurrent->flags &= ~LoopMemRef_10;
+ }
+}
+
+void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode) {
+ IROLinear *nd;
+ UInt32 index;
+
+ if (!loop->induction) {
+ loop->nd14 = NULL;
+ } else {
+ index = loop->induction->var->index;
+ for (nd = fnode->first; nd; nd = nd->next) {
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(nd);
+ if (Bv_IsBitSet(index, IRO_VarKills))
+ loop->nd14 = nd;
+
+ if (nd == fnode->last)
+ break;
+ }
+
+ if (loop->nd14 && loop->nd14->type != IROLinearOp2Arg)
+ loop->nd14 = NULL;
+ }
+}
+
+static void ComputeIntWeight(IROLoop *loop, IROLinear *Int) {
+ loop->sizeBySomeMeasurement++;
+}
+
+static IROLinear *IsTypconVar(IROLinear *nd) {
+ if (IS_LINEAR_MONADIC(nd, ETYPCON) && IRO_IsVariable(nd->u.monadic))
+ return nd->u.monadic;
+ else
+ return NULL;
+}
+
+IROLoop *ExtractLoopInfo(IRONode *fnode) {
+ Boolean flag30;
+ Boolean flag29;
+ Boolean flag28;
+ UInt32 counter27;
+ IROLoopInd *ind23;
+ Object *obj;
+ IROLinear *nd21;
+ IRONode *scanfnode;
+ IROLinear *left19;
+ IROLinear *right18;
+ IROLinear *tmp18;
+ IROLinear *scannd;
+ IROLinear *tmp;
+ VarRecord *var;
+ IROLoopInd *scanind;
+ IROLinear *left;
+ IROLinear *right;
+ UInt32 counter2;
+ UInt32 i;
+ IROLoop *loop;
+
+ flag30 = 0;
+ flag29 = 0;
+ flag28 = 0;
+ counter27 = 0;
+ LoopNode = fnode;
+
+ loop = oalloc(sizeof(IROLoop));
+ loop->fnode = fnode;
+ nd21 = LoopNode->last->u.label.x4;
+ loop->nd18 = nd21;
+ loop->flags = 0;
+ loop->x8 = 0;
+ loop->nd14 = NULL;
+ loop->induction = NULL;
+ loop->index20 = -1;
+ loop->index24 = -1;
+ loop->sizeBySomeMeasurement = 0;
+
+ if (nd21->type == IROLinearOp2Arg && IS_TYPE_INT(nd21->rtype)) {
+ ind23 = NULL;
+ left19 = nd21->u.diadic.left;
+ right18 = nd21->u.diadic.right;
+ if (IRO_IsVariable(left19) || (left19 = IsTypconVar(left19))) {
+ if ((var = IRO_FindVar(left19->u.monadic->u.node->data.objref, 0, 1))) {
+ scanind = FirstInd;
+ while (scanind && scanind->var != var)
+ scanind = scanind->next;
+ if (scanind) {
+ ind23 = scanind;
+ loop->flags |= LoopFlags_1;
+ loop->induction = scanind;
+ }
+ }
+ }
+
+ if (IRO_IsVariable(right18) || (right18 = IsTypconVar(right18))) {
+ if ((var = IRO_FindVar(right18->u.monadic->u.node->data.objref, 0, 1))) {
+ scanind = FirstInd;
+ while (scanind && scanind->var != var)
+ scanind = scanind->next;
+ if (scanind) {
+ ind23 = scanind;
+ loop->flags &= ~LoopFlags_1;
+ loop->induction = scanind;
+ }
+ }
+ }
+
+ if (ind23 && ind23->addConst > 0) {
+ if (loop->flags & LoopFlags_1) {
+ if (
+ loop->nd18->type != IROLinearOp2Arg ||
+ !(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == ELESSEQU || loop->nd18->nodetype == EGREATEREQU) ||
+ !loop->nd18->u.diadic.left ||
+ !loop->nd18->u.diadic.left->rtype ||
+ !IS_TYPE_INT(loop->nd18->u.diadic.left->rtype) ||
+ !loop->nd18->u.diadic.right ||
+ !loop->nd18->u.diadic.right->rtype ||
+ !IS_TYPE_INT(loop->nd18->u.diadic.right->rtype)
+ ) {
+ loop->flags |= LP_IFEXPR_NON_CANONICAL;
+ return loop;
+ }
+ } else {
+ if (
+ loop->nd18->type == IROLinearOp2Arg &&
+ (loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == EGREATEREQU) &&
+ (left = loop->nd18->u.diadic.left) &&
+ left->rtype &&
+ IS_TYPE_INT(left->rtype) &&
+ (right = loop->nd18->u.diadic.right) &&
+ right->rtype &&
+ IS_TYPE_INT(right->rtype)
+ ) {
+ loop->nd18->u.diadic.left = right;
+ loop->nd18->u.diadic.right = left;
+ if (loop->nd18->nodetype == EGREATER)
+ loop->nd18->nodetype = ELESS;
+ else if (loop->nd18->nodetype == EGREATEREQU)
+ loop->nd18->nodetype = ELESSEQU;
+ loop->flags |= LoopFlags_1;
+ } else if (
+ loop->nd18->type == IROLinearOp2Arg &&
+ (loop->nd18->nodetype == ELESS || loop->nd18->nodetype == ELESSEQU) &&
+ (left = loop->nd18->u.diadic.left) &&
+ left->rtype &&
+ IS_TYPE_INT(left->rtype) &&
+ (right = loop->nd18->u.diadic.right) &&
+ right->rtype &&
+ IS_TYPE_INT(right->rtype)
+ ) {
+ loop->nd18->u.diadic.left = right;
+ loop->nd18->u.diadic.right = left;
+ if (loop->nd18->nodetype == ELESS)
+ loop->nd18->nodetype = EGREATER;
+ else if (loop->nd18->nodetype == ELESSEQU)
+ loop->nd18->nodetype = EGREATEREQU;
+ loop->flags |= LoopFlags_1;
+ } else {
+ loop->flags |= LP_IFEXPR_NON_CANONICAL;
+ return loop;
+ }
+ }
+ } else {
+ loop->flags |= LP_INDUCTION_NOT_FOUND;
+ return loop;
+ }
+ } else if (nd21->type == IROLinearOp1Arg && IS_TYPE_INT(nd21->rtype)) {
+ if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC || nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) {
+ if (IRO_IsVariable(nd21->u.monadic)) {
+ if ((var = IRO_FindVar(nd21->u.monadic->u.monadic->u.node->data.objref, 0, 1))) {
+ scanind = FirstInd;
+ while (scanind && scanind->var != var)
+ scanind = scanind->next;
+ if (scanind) {
+ ind23 = scanind;
+ loop->flags |= LoopFlags_10000;
+ loop->induction = scanind;
+ } else {
+ loop->flags |= LP_INDUCTION_NOT_FOUND;
+ return loop;
+ }
+ } else {
+ loop->flags |= LP_INDUCTION_NOT_FOUND;
+ return loop;
+ }
+ } else {
+ loop->flags |= LP_INDUCTION_NOT_FOUND;
+ return loop;
+ }
+ } else {
+ loop->flags |= LP_INDUCTION_NOT_FOUND;
+ return loop;
+ }
+ } else {
+ loop->flags |= LP_IFEXPR_NON_CANONICAL;
+ return loop;
+ }
+
+ counter2 = 0;
+ scanind = FirstInd;
+ while (scanind) {
+ scanind = scanind->next;
+ counter2++;
+ }
+
+ if (counter2 > 1)
+ loop->flags |= LP_HAS_MULTIPLE_INDUCTIONS;
+
+ if ((scanind = loop->induction)) {
+ nd21 = scanind->nd;
+ if (nd21->type == IROLinearOp2Arg) {
+ if (IS_LINEAR_DIADIC_2(loop->nd18, ELESS, ELESSEQU)) {
+ if (nd21->nodetype == EADDASS) {
+ if (scanind->addConst == 1)
+ loop->flags |= LoopFlags_100;
+ if (scanind->addConst > 0)
+ loop->flags |= LP_LOOP_STEP_ISPOS;
+ } else if (nd21->nodetype == EASS &&
+ IS_LINEAR_DIADIC(nd21->u.diadic.right, EADD) &&
+ IRO_IsIntConstant(tmp18 = nd21->u.diadic.right->u.diadic.right) &&
+ CTool_EndianReadWord32(&tmp18->u.node->data.intval.hi) == 0) {
+ if (CInt64_GetULong(&tmp18->u.node->data.intval) == 1)
+ loop->flags |= LoopFlags_100;
+ if (CInt64_GetULong(&tmp18->u.node->data.intval) > 0)
+ loop->flags |= LP_LOOP_STEP_ISPOS;
+ }
+ }
+ } else if (nd21->type == IROLinearOp1Arg) {
+ if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC) {
+ if (scanind->addConst == 1)
+ loop->flags |= LoopFlags_100;
+ if (scanind->addConst > 0)
+ loop->flags |= LP_LOOP_STEP_ISPOS;
+ }
+ if (nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) {
+ if (scanind->addConst == 1)
+ loop->flags |= LoopFlags_2000;
+ if (scanind->addConst > 0)
+ loop->flags |= LP_LOOP_STEP_ISNEG;
+ }
+ }
+ loop->index24 = nd21->index;
+ loop->index20 = IRO_FindStart(nd21)->index;
+ }
+
+ if (ind23) {
+ tmp = IRO_FindStart(fnode->last->u.diadic.right);
+ loop->flags |= LoopFlags_200;
+ if (loop->flags & LoopFlags_10000) {
+ for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next) {
+ if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
+ loop->flags &= ~LoopFlags_200;
+ }
+ } else {
+ for (scannd = ind23->nd->next; scannd && scannd != tmp; scannd = scannd->next){
+ if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
+ loop->flags &= ~LoopFlags_200;
+ }
+ for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next){
+ if ((scannd->index < loop->index20 || scannd->index > loop->index24) && scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
+ loop->flags &= ~LoopFlags_200;
+ }
+ }
+ }
+
+ for (scanfnode = IRO_FirstNode; scanfnode; scanfnode = scanfnode->nextnode) {
+ if (Bv_IsBitSet(scanfnode->index, InLoop) && scanfnode != fnode && (scannd = scanfnode->first)) {
+ while (1) {
+ if (scannd->type == IROLinearFunccall)
+ flag30 = 1;
+ if (scannd->type == IROLinearGoto)
+ flag28++;
+ if (flag28 >= 1)
+ flag29 = 1;
+ if (scannd->type == IROLinearIf || scannd->type == IROLinearIfNot || scannd->type == IROLinearSwitch || scannd->type == IROLinearReturn)
+ flag29 = 1;
+
+ if (scannd->type == IROLinearAsm)
+ loop->flags |= LP_LOOP_HAS_ASM;
+
+ if (!(scannd->flags & IROLF_Reffed) && scannd->type != IROLinearNop && scannd->type != IROLinearLabel) {
+ if (!IRO_IsAssignOp[scannd->nodetype]) {
+ loop->flags |= LoopFlags_8;
+ } else if (scannd->index < loop->index20 || scannd->index > loop->index24) {
+ counter27++;
+ if (IsAssignmentReductionCandidate(scannd) && counter27 == 1)
+ loop->flags |= LoopFlags_40000;
+ if (counter27 > 1)
+ loop->flags &= ~LoopFlags_40000;
+ }
+ }
+
+ if (scannd->index < loop->index20 || scannd->index > loop->index24) {
+ if (IS_LINEAR_ENODE(scannd, EOBJREF)) {
+ obj = scannd->u.node->data.objref;
+ if ((scannd->flags & IROLF_Ind) && obj && obj == loop->induction->var->object) {
+ if (!(scannd->flags & IROLF_Assigned) && (scannd->flags & IROLF_Used)) {
+ IRO_Dump("Induction Used in loop\n");
+ loop->flags |= LoopFlags_800;
+ }
+ }
+ }
+
+ if (IS_LINEAR_DIADIC(scannd, ESHR) &&
+ (obj = IRO_IsVariable(scannd->u.diadic.left)) &&
+ IRO_IsConstant(scannd->u.diadic.right)) {
+ for (scanind = FirstInd; scanind; scanind = scanind->next) {
+ if (scanind->var->object == obj) {
+ IRO_Dump("Induction has DIV: %s\n", obj->name->name);
+ scanind->flags |= LoopInd_2;
+ }
+ }
+ }
+
+ if (IS_LINEAR_DIADIC(scannd, EAND) &&
+ (obj = IRO_IsVariable(scannd->u.diadic.left)) &&
+ IRO_IsConstant(scannd->u.diadic.right)) {
+ for (scanind = FirstInd; scanind && obj; scanind = scanind->next) {
+ if (scanind->var->object == obj) {
+ IRO_Dump("Induction has MOD: %s\n", obj->name->name);
+ scanind->flags |= LoopInd_1;
+ }
+ }
+ }
+ }
+
+ ComputeIntWeight(loop, scannd);
+ if (scannd == scanfnode->last)
+ break;
+ scannd = scannd->next;
+ }
+ }
+
+ if (flag30)
+ loop->flags |= LP_LOOP_HAS_CALLS;
+ if (flag29)
+ loop->flags |= LP_LOOP_HAS_CNTRLFLOW;
+
+ for (i = 0; i < scanfnode->numsucc && scanfnode != fnode; i++) {
+ if (Bv_IsBitSet(scanfnode->index, InLoop) && !Bv_IsBitSet(scanfnode->succ[i], InLoop)) {
+ IRO_Dump("Node %d has an out of loop successor %d\n", scanfnode->index, scanfnode->succ[i]);
+ IRO_DumpBits("Loop includes: ", InLoop);
+ IRO_Dump("loop has multiple exits\n");
+ loop->flags |= LoopFlags_1000;
+ }
+ }
+ }
+
+ return loop;
+}
+
+CLabel *BuildLabel(IROList *list) {
+ IROLinear *nd;
+
+ nd = IRO_NewLinear(IROLinearLabel);
+ nd->index = IRO_NumLinear++;
+ nd->u.label.label = IRO_NewLabel();
+ nd->flags |= IROLF_1;
+ IRO_AddToList(nd, list);
+ return nd->u.label.label;
+}
+
+static void MoveInvarianceInAddressExpr(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+ IROLinear *start;
+ IROList list;
+
+ IRO_FirstExpr = IRO_LastExpr = NULL;
+ IRO_NumExprs = 0;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (Bv_IsBitSet(fnode->index, InLoop)) {
+ for (nd = fnode->first; nd; nd = nd->next) {
+ if (nd->type == IROLinearOp1Arg &&
+ (nd->nodetype == EINDIRECT || nd->nodetype == EINDIRECT) &&
+ IS_LINEAR_DIADIC(nd->u.monadic, EADD)) {
+ RearrangeInvarianceInAddressExpr(nd->u.monadic, &list);
+ start = IRO_FindStart(nd->u.monadic);
+ IRO_LocateFather_Cut_And_Paste(nd->u.monadic, list.tail);
+ IRO_Paste(list.head, list.tail, start);
+ }
+
+ if (nd == fnode->last)
+ break;
+ }
+ }
+ }
+
+ IRO_UpdateFlagsOnInts();
+}
+
+static void AddAddendLinear(IROLinear *nd) {
+ IROElmList *list;
+
+ if (IS_LINEAR_DIADIC(nd, EADD)) {
+ AddAddendLinear(nd->u.diadic.left);
+ AddAddendLinear(nd->u.diadic.right);
+ } else {
+ list = oalloc(sizeof(IROElmList));
+ list->element = nd;
+ list->next = NULL;
+ if (FirstAddendLinear)
+ LastAddendLinear->next = list;
+ else
+ FirstAddendLinear = list;
+ LastAddendLinear = list;
+ }
+}
+
+static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list) {
+ IROLinear *result;
+ IROElmList *scanlist;
+ IROElmList *elist;
+ IROLinear *scannd;
+
+ IRO_InitList(list);
+ FirstAddendLinear = LastAddendLinear = NULL;
+ AddAddendLinear(nd->u.diadic.left);
+ AddAddendLinear(nd->u.diadic.right);
+
+ elist = NULL;
+ result = NULL;
+ for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) {
+ scannd = scanlist->element;
+ if (!IRO_IsIntConstant(scannd) && (scannd->flags & IROLF_LoopInvariant)) {
+ if (result) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
+ tmp->index = ++IRO_NumLinear;
+ tmp->nodetype = EADD;
+ tmp->u.diadic.left = result;
+ tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
+ IRO_AddToList(tmp, list);
+ tmp->flags |= IROLF_LoopInvariant;
+ tmp->flags |= IROLF_Reffed;
+ tmp->rtype = result->rtype;
+ result = tmp;
+ } else {
+ result = IRO_DuplicateExpr(scannd, list);
+ }
+
+ if (elist)
+ elist->next = scanlist->next;
+ else
+ FirstAddendLinear = scanlist->next;
+ } else {
+ elist = scanlist;
+ }
+ }
+
+ for (scanlist = FirstAddendLinear, elist = NULL; scanlist; scanlist = scanlist->next) {
+ scannd = scanlist->element;
+ if (!IRO_IsIntConstant(scannd)) {
+ if (result) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
+ tmp->index = ++IRO_NumLinear;
+ tmp->nodetype = EADD;
+ tmp->u.diadic.left = result;
+ tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
+ IRO_AddToList(tmp, list);
+ tmp->flags |= IROLF_Reffed;
+ tmp->rtype = result->rtype;
+ result = tmp;
+ } else {
+ result = IRO_DuplicateExpr(scannd, list);
+ }
+
+ if (elist)
+ elist->next = scanlist->next;
+ else
+ FirstAddendLinear = scanlist->next;
+ } else {
+ elist = scanlist;
+ }
+ }
+
+ for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) {
+ scannd = scanlist->element;
+ if (result) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
+ tmp->index = ++IRO_NumLinear;
+ tmp->nodetype = EADD;
+ tmp->u.diadic.left = result;
+ tmp->u.diadic.right = scannd;
+ tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
+ IRO_AddToList(tmp, list);
+ tmp->flags |= IROLF_Reffed;
+ tmp->rtype = result->rtype;
+ result = tmp;
+ } else {
+ result = IRO_DuplicateExpr(scannd, list);
+ }
+ }
+
+ return result;
+}
+
+static IROLinear *FindAddendForReductionPattern(IROLinear *a, IROLinear *b, Boolean *resultFlag) {
+ IROLinear *left;
+ IROLinear *right;
+ IROLinear *node28;
+ Boolean subflag;
+
+ left = b->u.diadic.left;
+ right = b->u.diadic.right;
+ if (b->nodetype == EADD || b->nodetype == ESUB) {
+ node28 = left;
+ while (IS_LINEAR_MONADIC(node28, ETYPCON))
+ node28 = node28->u.monadic;
+
+ if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) {
+ *resultFlag = 1;
+ return left;
+ }
+
+ if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) {
+ if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) {
+ *resultFlag = 1;
+ return node28;
+ }
+ }
+ }
+
+ *resultFlag = 0;
+ if (b->nodetype == EADD) {
+ node28 = right;
+ while (IS_LINEAR_MONADIC(node28, ETYPCON))
+ node28 = node28->u.monadic;
+
+ if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) {
+ return right;
+ }
+
+ if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) {
+ if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) {
+ return node28;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void ReorderOperandsForReductionPattern(IROLinear *a, IROLinear *b) {
+ IROLinear *left;
+ IROLinear *right;
+ IROLinear *addend;
+ IROLinear *tmp;
+ Boolean flag;
+
+ left = b->u.diadic.left;
+ right = b->u.diadic.right;
+
+ if (b->nodetype == EADD && (addend = FindAddendForReductionPattern(a, b, &flag)) && addend != left) {
+ if (flag && IS_LINEAR_DIADIC_2(left, EADD, ESUB) && addend->rtype == right->rtype) {
+ tmp = left;
+ b->u.diadic.left = right;
+ left = right;
+ b->u.diadic.right = tmp;
+ right = tmp;
+ flag = 0;
+ }
+
+ if (!flag && IS_LINEAR_DIADIC_2(right, EADD, ESUB) && addend->rtype == left->rtype) {
+ if (IRO_LocateFather_Cut_And_Paste_Without_Nopping(addend, left))
+ b->u.diadic.left = addend;
+ }
+ }
+}
+
+static UInt32 IsAssignmentReductionCandidate(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ IROLinear *tmp;
+
+ if (nd->type == IROLinearOp2Arg) {
+ if (nd->nodetype == EASS) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_LINEAR_MONADIC(left, EINDIRECT) && (left->u.monadic->flags & IROLF_LoopInvariant)) {
+ if (IS_LINEAR_MONADIC(right, ETYPCON) &&
+ right->rtype->type == right->u.monadic->rtype->type &&
+ IS_TYPE_INT(right->rtype) &&
+ right->rtype->size < right->u.monadic->rtype->size)
+ right = right->u.monadic;
+
+ if (IS_LINEAR_DIADIC_2(right, EADD, ESUB)) {
+ ReorderOperandsForReductionPattern(left, right);
+ tmp = right->u.diadic.left;
+ if (IS_LINEAR_MONADIC(tmp, ETYPCON))
+ tmp = tmp->u.monadic;
+ if (IS_LINEAR_MONADIC(tmp, EINDIRECT) &&
+ (tmp->u.monadic->flags & IROLF_LoopInvariant) &&
+ IRO_ExprsSame(left, tmp) &&
+ right->u.diadic.right->type == IROLinearOp2Arg) {
+ if (right->u.diadic.right->nodetype == EADD)
+ return 1;
+ if (right->u.diadic.right->nodetype == ESUB)
+ return 1;
+ if (right->u.diadic.right->nodetype == EMUL)
+ return 1;
+ if (right->u.diadic.right->nodetype == EDIV)
+ return 1;
+ }
+ }
+ }
+ } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+
+ if (IS_LINEAR_MONADIC(right, ETYPCON) &&
+ right->rtype->type == right->u.monadic->rtype->type &&
+ IS_TYPE_INT(right->rtype) &&
+ right->rtype->size < right->u.monadic->rtype->size)
+ right = right->u.monadic;
+
+ if (IS_LINEAR_MONADIC(left, EINDIRECT) &&
+ (left->u.monadic->flags & IROLF_LoopInvariant) &&
+ right->type == IROLinearOp2Arg) {
+ if (right->nodetype == EADD)
+ return 1;
+ if (right->nodetype == ESUB)
+ return 1;
+ if (right->nodetype == EMUL)
+ return 1;
+ if (right->nodetype == EDIV)
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/compiler_and_linker/unsorted/IroMalloc.c b/compiler_and_linker/unsorted/IroMalloc.c
index e69de29..8928ba9 100644
--- a/compiler_and_linker/unsorted/IroMalloc.c
+++ b/compiler_and_linker/unsorted/IroMalloc.c
@@ -0,0 +1,564 @@
+#include "compiler/IroMalloc.h"
+#include "compiler/CompilerTools.h"
+
+#define FLAGMASK 0xF
+
+typedef struct Block {
+ struct Block *prev;
+ struct Block *next;
+ void *x8;
+ void *xC;
+ size_t remain;
+ size_t x14;
+} Block;
+
+typedef struct SubBlockBase {
+ size_t x0;
+ Block *block;
+} SubBlockBase;
+
+typedef struct SubBlock {
+ size_t x0;
+ Block *block;
+ struct SubBlock *x8;
+ struct SubBlock *xC;
+} SubBlock;
+
+typedef struct SubBlockTail {
+ size_t x0copy;
+} SubBlockTail;
+
+typedef struct BlockTail {
+ size_t x14copy;
+ SubBlock *unk;
+} BlockTail;
+
+typedef struct FixStart {
+ struct FixBlock *a;
+ struct FixSubBlock *b;
+ long count;
+} FixStart;
+
+typedef struct FixBlock {
+ struct FixBlock *prev;
+ struct FixBlock *next;
+ size_t entrysize;
+} FixBlock;
+
+typedef struct FixSubBlockBase {
+ FixBlock *fixblock;
+} FixSubBlockBase;
+
+typedef struct FixSubBlock {
+ FixBlock *fixblock;
+ struct FixSubBlock *next;
+} FixSubBlock;
+
+static const size_t fix_pool_sizes[] = {0xC, 0x1C, 0x2C, 0x4C};
+static Block *start_;
+static FixStart fix_start[4];
+static int initialized;
+
+// forward decls
+static void Block_link(Block *block, SubBlock *subblock);
+static void Block_unlink(Block *block, SubBlock *subblock);
+static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2);
+static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos);
+static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr);
+static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr);
+
+#define BLOCK_TAIL(block) ((BlockTail *) ((long) (block) + ((block)->x14 & ~FLAGMASK) - sizeof(BlockTail)))
+
+#define BUF_LOCATOR(buf) (*((size_t *) ((long) (buf) - sizeof(size_t))))
+#define SBB_BLOCK(sbb) ((Block *) ((long) ((sbb)->block) & ~1))
+
+#define BUF_IS_VAR(buf) (BUF_LOCATOR(buf) & 1)
+#define VARBUF_SBB(buf) ((SubBlockBase *) ((long) (buf) - sizeof(SubBlockBase)))
+#define VARBUF_SB(buf) ((SubBlock *) ((long) (buf) - sizeof(SubBlockBase)))
+#define VARBUF_BLOCKSIZE(buf) (VARBUF_SBB(buf)->x0 & ~FLAGMASK)
+#define VARBUF_SIZE(buf) (((VARBUF_SBB(buf)->x0 & ~FLAGMASK) - sizeof(SubBlockBase)))
+#define VARBUF_BLOCK(buf) SBB_BLOCK(VARBUF_SBB(buf))
+#define FIXBUF_SIZE(buf) (((FixBlock *) BUF_LOCATOR(buf))->entrysize)
+
+#define BUF_SIZE(buf) BUF_IS_VAR(buf) ? VARBUF_SIZE(buf) : FIXBUF_SIZE(buf)
+
+static void Block_construct(Block *block, size_t size) {
+ SubBlock *subblock;
+
+ block->x14 = size | 3;
+ ((BlockTail *) ((long) block + size - sizeof(BlockTail)))->x14copy = block->x14;
+
+ subblock = (SubBlock *) (block + 1);
+ SubBlock_construct(subblock, size - sizeof(Block) - sizeof(BlockTail), block, 0, 0);
+
+ block->remain = size - sizeof(Block) - sizeof(BlockTail);
+ BLOCK_TAIL(block)->unk = NULL;
+
+ Block_link(block, subblock);
+}
+
+static SubBlock *Block_subBlock(Block *block, size_t size) {
+ SubBlock *subblock;
+ size_t check;
+ size_t best;
+
+ if (!BLOCK_TAIL(block)->unk)
+ return NULL;
+
+ subblock = BLOCK_TAIL(block)->unk;
+ best = subblock->x0 & ~FLAGMASK;
+ check = subblock->x0 & ~FLAGMASK;
+ while (check < size) {
+ subblock = subblock->xC;
+ check = subblock->x0 & ~FLAGMASK;
+ if (best < check)
+ best = check;
+ if (subblock == BLOCK_TAIL(block)->unk) {
+ block->remain = best;
+ return NULL;
+ }
+ }
+
+ if ((check - size) >= 0x60)
+ SubBlock_split(subblock, size);
+
+ BLOCK_TAIL(block)->unk = subblock->xC;
+ Block_unlink(block, subblock);
+ return subblock;
+}
+
+static void Block_link(Block *block, SubBlock *subblock) {
+ size_t size;
+ SubBlock **sbptr;
+
+ size = subblock->x0 & ~FLAGMASK;
+ subblock->x0 &= ~2;
+ ((SubBlock *) ((long) subblock + size))->x0 &= ~4;
+ ((SubBlockTail *) ((long) subblock + size - sizeof(SubBlockTail)))->x0copy = size;
+
+ sbptr = &BLOCK_TAIL(block)->unk;
+ if (*sbptr) {
+ subblock->x8 = (*sbptr)->x8;
+ subblock->x8->xC = subblock;
+ subblock->xC = *sbptr;
+ (*sbptr)->x8 = subblock;
+ *sbptr = subblock;
+ *sbptr = SubBlock_merge_prev(*sbptr, sbptr);
+ SubBlock_merge_next(*sbptr, sbptr);
+ } else {
+ *sbptr = subblock;
+ subblock->x8 = subblock;
+ subblock->xC = subblock;
+ }
+
+ if (block->remain < ((*sbptr)->x0 & ~FLAGMASK))
+ block->remain = (*sbptr)->x0 & ~FLAGMASK;
+}
+
+static void Block_unlink(Block *block, SubBlock *subblock) {
+ size_t size;
+ SubBlock **sbptr;
+
+ size = subblock->x0 & ~FLAGMASK;
+ subblock->x0 |= 2;
+ ((SubBlock *) ((long) subblock + size))->x0 |= 4;
+
+ sbptr = &BLOCK_TAIL(block)->unk;
+ if (*sbptr == subblock)
+ *sbptr = subblock->xC;
+
+ if (*sbptr == subblock) {
+ *sbptr = NULL;
+ block->remain = 0;
+ } else {
+ subblock->xC->x8 = subblock->x8;
+ subblock->x8->xC = subblock->xC;
+ }
+}
+
+static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2) {
+ subblock->block = (Block *) ((long) block | 1);
+ subblock->x0 = size;
+ if (flag1)
+ subblock->x0 |= 4;
+ if (flag2) {
+ subblock->x0 |= 2;
+ ((SubBlock *) (((long) subblock) + size))->x0 |= 4;
+ } else {
+ ((SubBlockTail *) (((long) subblock) + size - sizeof(SubBlockTail)))->x0copy = size;
+ }
+}
+
+static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos) {
+ size_t oldsize;
+ int flag;
+ SubBlock *splitright;
+ Block *block;
+
+ oldsize = subblock->x0 & ~FLAGMASK;
+ flag = !(subblock->x0 & 2);
+ splitright = (SubBlock *) ((long) subblock + pos);
+ block = (Block *) ((long) subblock->block & ~1);
+ SubBlock_construct(subblock, pos, block, subblock->x0 & 4, !flag);
+ SubBlock_construct(splitright, oldsize - pos, block, !flag, !flag);
+ if (flag) {
+ splitright->xC = subblock->xC;
+ splitright->xC->x8 = splitright;
+ splitright->x8 = subblock;
+ subblock->xC = splitright;
+ }
+
+ return splitright;
+}
+
+static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr) {
+ size_t prevsize;
+ SubBlock *prevblock;
+
+ if (!(subblock->x0 & 4)) {
+ prevsize = ((SubBlockTail *) ((long) subblock - sizeof(SubBlockTail)))->x0copy;
+ if (prevsize & 2)
+ return subblock;
+
+ prevblock = (SubBlock *) ((long) subblock - prevsize);
+ prevblock->x0 = prevblock->x0 & FLAGMASK;
+ prevblock->x0 |= (prevsize + (subblock->x0 & ~FLAGMASK)) & ~FLAGMASK;
+ if (!(prevblock->x0 & 2))
+ ((SubBlockTail *) ((long) prevblock + prevsize + (subblock->x0 & ~FLAGMASK) - sizeof(SubBlockTail)))->x0copy = prevsize + (subblock->x0 & ~FLAGMASK);
+
+ if (*sbptr == subblock)
+ *sbptr = (*sbptr)->xC;
+
+ subblock->xC->x8 = subblock->x8;
+ subblock->xC->x8->xC = subblock->xC;
+ return prevblock;
+ }
+
+ return subblock;
+}
+
+static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr) {
+ SubBlock *nextblock;
+ size_t nextsize;
+
+ nextblock = (SubBlock *) ((long) subblock + (subblock->x0 & ~FLAGMASK));
+ if (!(nextblock->x0 & 2)) {
+ nextsize = (subblock->x0 & ~FLAGMASK) + (nextblock->x0 & ~FLAGMASK);
+ subblock->x0 = subblock->x0 & FLAGMASK;
+ subblock->x0 |= nextsize & ~FLAGMASK;
+
+ if (!(subblock->x0 & 2))
+ ((SubBlockTail *) ((long) subblock + nextsize - sizeof(SubBlockTail)))->x0copy = nextsize;
+
+ if (!(subblock->x0 & 2))
+ ((SubBlock *) ((long) subblock + nextsize))->x0 &= ~4;
+ else
+ ((SubBlock *) ((long) subblock + nextsize))->x0 |= 4;
+
+ if (*sbptr == nextblock)
+ *sbptr = (*sbptr)->xC;
+ if (*sbptr == nextblock)
+ *sbptr = NULL;
+
+ nextblock->xC->x8 = nextblock->x8;
+ nextblock->x8->xC = nextblock->xC;
+ }
+}
+
+static void link_block(Block *block) {
+ if (start_) {
+ block->prev = start_->prev;
+ block->prev->next = block;
+ block->next = start_;
+
+ start_->prev = block;
+ start_ = block;
+ } else {
+ start_ = block;
+ block->prev = block;
+ block->next = block;
+ }
+}
+
+static Block *unlink_block(Block *block) {
+ Block *newblock;
+
+ newblock = block->next;
+ if (newblock == block)
+ newblock = NULL;
+
+ if (start_ == block)
+ start_ = newblock;
+
+ if (newblock) {
+ newblock->prev = block->prev;
+ newblock->prev->next = newblock;
+ }
+
+ block->prev = block->next = NULL;
+ return newblock;
+}
+
+static Block *link_new_block(size_t size) {
+ Block *block;
+
+ size = (size + 0x1000 + sizeof(Block) + sizeof(BlockTail) - 1) & ~0xFFF;
+ if (size < 0x10000)
+ size = 0x10000;
+
+ if (!(block = galloc(size)))
+ return NULL;
+
+ Block_construct(block, size);
+ link_block(block);
+ return block;
+}
+
+static void *allocate_from_var_pools(size_t size) {
+ Block *block;
+ SubBlock *subblock;
+
+ size = (size + sizeof(Block) - 1) & ~0xF;
+ if (size < 0x60)
+ size = 0x60;
+
+ block = start_ ? start_ : link_new_block(size);
+ if (!block)
+ return NULL;
+
+ do {
+ if (size <= block->remain) {
+ if ((subblock = Block_subBlock(block, size))) {
+ start_ = block;
+ goto allocated;
+ }
+ }
+ } while ((block = block->next) != start_);
+
+ block = link_new_block(size);
+ if (!block)
+ return NULL;
+ subblock = Block_subBlock(block, size);
+allocated:
+ return (SubBlockBase *) subblock + 1;
+}
+
+static void deallocate_from_var_pools(void *buf) {
+ Block *block;
+ SubBlock *subblock;
+ int flag;
+
+ subblock = (SubBlock *) ((long) buf - sizeof(SubBlockBase));
+ block = (Block *) ((long) subblock->block & ~1);
+ Block_link(block, subblock);
+
+ flag = 0;
+ subblock = (SubBlock *) (block + 1);
+ if (!(subblock->x0 & 2)) {
+ if ((subblock->x0 & ~FLAGMASK) == ((block->x14 & ~FLAGMASK) - sizeof(Block) - sizeof(BlockTail)))
+ flag = 1;
+ }
+
+ if (flag)
+ unlink_block(block);
+}
+
+static void FixBlock_construct(FixBlock *fixblock, FixBlock *prev, FixBlock *next, int poolIndex, void *buffer, size_t buffersize) {
+ size_t entrysize;
+ size_t entrycount;
+ size_t i;
+ FixSubBlock *fsb;
+ FixSubBlock *fsbnext;
+
+ fixblock->prev = prev;
+ fixblock->next = next;
+ fixblock->entrysize = fix_pool_sizes[poolIndex];
+
+ entrysize = fix_pool_sizes[poolIndex] + sizeof(void *);
+ entrycount = (buffersize / entrysize);
+ fsb = buffer;
+ for (i = 0; i < (entrycount - 1); i++) {
+ fsbnext = (FixSubBlock *) ((long) fsb + entrysize);
+ fsb->fixblock = fixblock;
+ fsb->next = fsbnext;
+ fsb = fsbnext;
+ }
+
+ fsb->fixblock = fixblock;
+ fsb->next = fix_start[poolIndex].b;
+ fix_start[poolIndex].b = buffer;
+}
+
+static void *allocate_from_fixed_pools(size_t size) {
+ int poolIndex;
+ FixSubBlock *fsb;
+
+ poolIndex = 0;
+ while (size > fix_pool_sizes[poolIndex])
+ poolIndex++;
+
+ if (!fix_start[poolIndex].b) {
+ void *buf;
+ size_t bufsize;
+
+ buf = allocate_from_var_pools(4000);
+ if (!buf)
+ return NULL;
+
+ bufsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
+ FixBlock_construct(
+ buf, NULL, fix_start[poolIndex].a, poolIndex,
+ ((FixBlock *) buf) + 1,
+ bufsize - sizeof(FixBlock)
+ );
+ fix_start[poolIndex].a = buf;
+ }
+
+ fsb = fix_start[poolIndex].b;
+ fix_start[poolIndex].b = fsb->next;
+ fix_start[poolIndex].count++;
+ return ((FixSubBlockBase *) fsb) + 1;
+}
+
+static void deallocate_from_fixed_pools(void *buf, size_t size) {
+ int poolIndex;
+ FixBlock *fixblock;
+ FixBlock *nextfb;
+ FixSubBlock *fsb;
+
+ poolIndex = 0;
+ while (size > fix_pool_sizes[poolIndex])
+ poolIndex++;
+
+ fsb = (FixSubBlock *) ((long) buf - sizeof(FixSubBlockBase));
+ fsb->next = fix_start[poolIndex].b;
+ fix_start[poolIndex].b = fsb;
+ if (--fix_start[poolIndex].count == 0) {
+ fixblock = fix_start[poolIndex].a;
+ while (fixblock) {
+ nextfb = fixblock->next;
+ deallocate_from_var_pools(fixblock);
+ fixblock = nextfb;
+ }
+ fix_start[poolIndex].a = NULL;
+ fix_start[poolIndex].b = NULL;
+ }
+}
+
+size_t IRO_msize(void *buf) {
+ return BUF_SIZE(buf);
+}
+
+void *IRO_malloc(size_t size) {
+ if (!size)
+ return NULL;
+
+ if (size <= 0x4C)
+ return allocate_from_fixed_pools(size);
+ else
+ return allocate_from_var_pools(size);
+}
+
+void IRO_free(void *buf) {
+ if (buf) {
+ size_t size = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
+
+ if (size <= 0x4C)
+ deallocate_from_fixed_pools(buf, size);
+ else
+ deallocate_from_var_pools(buf);
+ }
+}
+
+void *IRO_realloc(void *buf, size_t newsize) {
+ size_t oldsize;
+ size_t newblocksize;
+ void *newbuf;
+
+ if (!buf)
+ return IRO_malloc(newsize);
+
+ if (!newsize) {
+ IRO_free(buf);
+ return NULL;
+ }
+
+ oldsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf);
+ if (newsize > oldsize) {
+ if (BUF_IS_VAR(buf)) {
+ newblocksize = (newsize + sizeof(Block) - 1) & ~FLAGMASK;
+ if (newblocksize < 0x60)
+ newblocksize = 0x60;
+ SubBlock_merge_next(VARBUF_SB(buf), &BLOCK_TAIL(VARBUF_BLOCK(buf))->unk);
+ if (VARBUF_BLOCKSIZE(buf) >= newblocksize) {
+ if ((VARBUF_BLOCKSIZE(buf) - newblocksize) >= 0x60) {
+ Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newblocksize));
+ }
+ return buf;
+ }
+ }
+
+ newbuf = IRO_malloc(newsize);
+ if (!newbuf)
+ return NULL;
+
+ memcpy(newbuf, buf, oldsize);
+ IRO_free(buf);
+ return newbuf;
+ }
+
+ if (BUF_IS_VAR(buf)) {
+ newsize = (newsize + sizeof(Block) - 1) & ~FLAGMASK;
+ if (newsize < 0x60)
+ newsize = 0x60;
+ if ((VARBUF_BLOCKSIZE(buf) - newsize) >= 0x60) {
+ Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newsize));
+ }
+ }
+
+ return buf;
+}
+
+void *IRO_calloc(size_t a, size_t b) {
+ void *buf;
+ size_t len = b * a;
+ buf = IRO_malloc(len);
+ if (buf)
+ memset(buf, 0, len);
+ return buf;
+}
+
+void IRO_pool_free_all(void) {
+ int i;
+ Block *block;
+ if ((block = start_)) {
+ do {
+ block = block->next;
+ } while (block != start_);
+ start_ = NULL;
+
+ for (i = 0; i < 4; i++) {
+ fix_start[i].a = NULL;
+ fix_start[i].b = NULL;
+ fix_start[i].count = 0;
+ }
+ }
+}
+
+void IRO_InitializeAllocator(void) {
+ if (!initialized) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ fix_start[i].a = NULL;
+ fix_start[i].b = NULL;
+ fix_start[i].count = 0;
+ }
+ start_ = NULL;
+ initialized = 1;
+ }
+}
+
+void IRO_TerminateAllocator(void) {
+ initialized = 0;
+}
+
diff --git a/compiler_and_linker/unsorted/IroPointerAnalysis.c b/compiler_and_linker/unsorted/IroPointerAnalysis.c
index e69de29..a47d544 100644
--- a/compiler_and_linker/unsorted/IroPointerAnalysis.c
+++ b/compiler_and_linker/unsorted/IroPointerAnalysis.c
@@ -0,0 +1,5912 @@
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroEval.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CDecl.h"
+#include "compiler/CExpr.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/InlineAsmPPC.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler_and_linker/unsorted/IroPointerAnalysisADTs.c"
+
+// forward decls
+static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag);
+static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag);
+static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo);
+static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype);
+static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result);
+static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode);
+static ObjectList *FunctionArguments(Object *proc);
+static IRONode **FunctionNodeTable(Object *proc);
+static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag);
+static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit);
+static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj);
+static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj);
+static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf);
+static void FindGlobalObjectAction(Object *object, void *refcon);
+
+static Boolean ObjectIsRestrictQualified(Object *obj) {
+ return (CParser_GetTypeQualifiers(obj->type, obj->qual) & Q_RESTRICT) != 0;
+}
+
+static Boolean LocationIsVolatile(LocationSet *loc, Object *proc) {
+ Boolean result;
+ Type *rtype;
+
+#line 932
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ result = 0;
+
+ if ((rtype = LocationSet_rtype(loc))) {
+ UInt32 qual;
+ switch (rtype->type) {
+ case TYPEARRAY:
+ qual = TYPE_POINTER(rtype)->qual;
+ break;
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(rtype)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(rtype)->qual;
+ break;
+ default:
+ qual = 0;
+ }
+ if (qual & Q_VOLATILE)
+ result = 1;
+ }
+
+ if (!result && !LocationSet_IsUnknown(loc)) {
+ Object *obj = NULL;
+ PAMemoryBlock *block = LocationSet_block(loc);
+
+ switch (PAMemoryBlock_kind(block)) {
+ case PAMEMORYBLOCKKIND_LOCALVAR: {
+ PALocalVar *local = PAMemoryBlock_thing(block);
+ if (local)
+ obj = GetLocalObject(local, proc, 0);
+ break;
+ }
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM: {
+ ExtendedParam *ep = PAMemoryBlock_thing(block);
+ if (ep) {
+ ObjectSet *objSet = ExtendedParam_objectSet(ep);
+ if (objSet) {
+ if (ObjectSet_Count(objSet) == 1)
+ obj = ObjectSet_FindFirst(objSet);
+ else
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ }
+ }
+ break;
+ }
+ }
+
+ if (obj && is_volatile_object(obj))
+ result = 1;
+ }
+
+ return result;
+}
+
+static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag) {
+ ObjectList *list;
+ Object *arg;
+ Object *obj;
+ char *name;
+
+#line 999
+ IRO_ASSERT(local != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ obj = PALocalVar_Get0_sub_4847E0(local);
+ name = PALocalVar_Get4_sub_4847D0(local);
+
+ if (proc != &stUnknown && !obj && name && name[0] && flag) {
+ for (list = FunctionArguments(proc); list && !obj; list = list->next) {
+ arg = list->object;
+ if (arg && arg != &stUnknown && arg->name && arg->name->name) {
+ if (!strcmp(arg->name->name, name))
+ obj = arg;
+ }
+ }
+ }
+
+ if (obj)
+ PALocalVar_SetSth_sub_4847C0(local, obj);
+
+ return obj;
+}
+
+static Boolean ObjectIsAnExtendedParamCandidate(Object *obj) {
+#line 1042
+ IRO_ASSERT(obj != NULL);
+
+ return Inline_IsObjectData(obj) ||
+ obj->datatype == DABSOLUTE ||
+ obj->datatype == DFUNC ||
+ obj->datatype == DVFUNC ||
+ obj->datatype == DINLINEFUNC;
+}
+
+static Boolean ObjectIsAFunction(Object *obj) {
+#line 1054
+ IRO_ASSERT(obj != NULL);
+
+ return obj->datatype == DFUNC ||
+ obj->datatype == DVFUNC ||
+ obj->datatype == DINLINEFUNC;
+}
+
+static Boolean LocationSetRepresentsSingleLocation(LocationSet *ls, Object *proc, PointsToFunction *pointsToFunc) {
+ Boolean result;
+ PAMemoryBlock *mb;
+ PAMemoryBlockKind kind;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+
+#line 1073
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(proc == NULL || proc != NULL);
+ IRO_ASSERT(pointsToFunc == NULL || pointsToFunc != NULL);
+
+ result = 1;
+ if (LocationSet_IsUnknown(ls) || LocationSet_stride(ls)) {
+ result = 0;
+ } else {
+ mb = LocationSet_block(ls);
+#line 1084
+ IRO_ASSERT(mb != NULL);
+
+ kind = PAMemoryBlock_kind(mb);
+ if (kind == PAMEMORYBLOCKKIND_HEAPBLOCK) {
+ result = 0;
+ } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ ep = PAMemoryBlock_thing(mb);
+ if (!ep) {
+ result = 0;
+ } else {
+ if ((objSet = ExtendedParam_objectSet(ep)) && ObjectSet_Count(objSet) > 1) {
+ Object *obj = NULL;
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+
+ if (!obj) {
+ LocationSetSet *lss;
+ LocationSet *tmp;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ GetActualLocsOfExtendedParam(lss, ls, NULL, &stCallingContextStack, NULL, 0);
+ if (
+ LocationSetSet_Count(lss) != 1 ||
+ !(tmp = LocationSetSet_FindFirst(lss)) ||
+ LocationSet_IsUnknown(tmp) ||
+ (!((mb = LocationSet_block(tmp)) && (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) && (ep = PAMemoryBlock_thing(mb)) && (objSet = ExtendedParam_objectSet(ep)) && (ObjectSet_Count(objSet) == 1) &&
+ ObjectIsAnExtendedParamCandidate(ObjectSet_FindFirst(objSet))) &&
+ !LocationSetRepresentsSingleLocation(tmp, proc, pointsToFunc))
+ )
+ result = 0;
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+static void EvalExprAction(LocationSet *ls, void *refcon) {
+ CInt64 value;
+ UInt32 stride;
+ PAMemoryBlock *mb;
+
+#line 1151
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+ IRO_ASSERT(refcon != NULL);
+
+ value = *((CInt64 *) refcon);
+ stride = LocationSet_stride(ls);
+ mb = LocationSet_block(ls);
+
+ if (mb && PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) {
+ Type *rtype = LocationSet_rtype(ls);
+ LocationSet_Term(ls);
+ value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb)));
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
+ LocationSet_InitKnown(ls, mb, cint64_zero, stride, rtype);
+ } else {
+ value = CInt64_Add(value, LocationSet_field(ls));
+ if (stride) {
+ CInt64 strideval;
+ CInt64_SetLong(&strideval, stride);
+ value = CInt64_Mod(value, strideval);
+ }
+ SetsLocationSetField_sub_4851B0(ls, value);
+ }
+}
+
+static void EvalExprAction2(LocationSet *ls, void *refcon) {
+ UInt32 value;
+
+#line 1188
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+ IRO_ASSERT(refcon != NULL);
+
+ value = CInt64_GetULong((CInt64 *) refcon);
+ if (value) {
+ SetsLocationSetField_sub_4851B0(ls, CInt64_Mod(LocationSet_field(ls), *((CInt64 *) refcon)));
+ }
+ SetsLocationSetStride_sub_4852D0(ls, value);
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalExprAction3Params {
+ LocationSetSet *set;
+ Stack **stackPtr;
+ Object *proc;
+ ParamMappingFunction *map;
+ PartialTransferFunction *ptf;
+ PointsToFunction *pointsToFunc;
+ Type *indRtype;
+ Boolean x1C;
+} EvalExprAction3Params;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalExprAction3(LocationSet *ls, void *refcon) {
+ EvalExprAction3Params *params;
+
+#line 1219
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+ params->x1C |= Lookup(
+ params->set,
+ params->stackPtr,
+ params->proc,
+ params->map,
+ params->ptf,
+ ls,
+ params->pointsToFunc,
+ 1,
+ params->indRtype
+ );
+}
+
+static void EvalExprAction4(LocationSet *ls, void *refcon) {
+ Type *type;
+ PAMemoryBlock *mb;
+
+#line 1235
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ type = refcon;
+
+ if (LocationSet_IsUnknown(ls)) {
+ LocationSet_SetRtype(ls, type);
+ } else if ((mb = LocationSet_block(ls))) {
+ if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) {
+ CInt64 value;
+ CInt64 field;
+ UInt32 stride;
+
+ value = *((CInt64 *) PAMemoryBlock_thing(mb));
+ IRO_TruncateValueToType(&value, type);
+ field = LocationSet_field(ls);
+ IRO_TruncateValueToType(&field, type);
+ stride = LocationSet_stride(ls);
+ LocationSet_Term(ls);
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
+
+ LocationSet_InitKnown(ls, mb, field, stride, type);
+ }
+ LocationSet_SetRtype(ls, type);
+ }
+}
+
+static Boolean EvalExpr(LocationSetSet *set, Object *proc, IROLinear *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ Boolean result;
+ LocationSetSet *lss;
+ LocationSetSet *lss2;
+ IROLinear *indirect;
+ EvalExprAction3Params params;
+ IROLinear *originalInt;
+
+#line 1284
+ IRO_ASSERT(set == NULL || set != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(Int != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+
+ result = 0;
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+
+ originalInt = Int;
+ while (Int && Int->type == IROLinearOp1Arg && Int->nodetype == ETYPCON)
+ Int = Int->u.monadic;
+
+#line 1302
+ IRO_ASSERT(Int != NULL);
+
+ if (IRO_IsAssignment(Int)) {
+ if (Int->type == IROLinearOp1Arg)
+ indirect = Int->u.monadic;
+ else
+ indirect = Int->u.diadic.left;
+#line 1310
+ IRO_ASSERT(indirect->type == IROLinearOp1Arg && indirect->nodetype == EINDIRECT);
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalExpr(lss2, proc, indirect->u.monadic, stackPtr, map, ptf);
+
+ memset(&params, 0, sizeof(params));
+ params.set = lss;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ if (Int->nodetype == EPOSTINC || Int->nodetype == EPOSTDEC)
+ params.pointsToFunc = indirect->pointsToFunction;
+ else
+ params.pointsToFunc = Int->pointsToFunction;
+ params.indRtype = indirect->rtype;
+ params.x1C = 0;
+ LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
+ result |= params.x1C;
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else if (Int->type == IROLinearFunccall) {
+#line 1338
+ IRO_ASSERT(Int->u.funccall.returnedLocs != NULL);
+ LocationSetSet_AddSet(lss, Int->u.funccall.returnedLocs);
+ } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT) {
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf);
+
+ memset(&params, 0, sizeof(params));
+ params.set = lss;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ params.pointsToFunc = Int->pointsToFunction;
+ params.indRtype = Int->rtype;
+ params.x1C = 0;
+ LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
+ result |= params.x1C;
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else if (Int->type == IROLinearOp2Arg && Int->nodetype == EADD) {
+ IROAddrRecord *addr = IRO_InitAddrRecordPointer(Int);
+ IRO_DecomposeAddressExpression(Int, addr);
+ if (addr->numObjRefs > 1) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ } else {
+ CInt64 value;
+ CInt64 max;
+ CInt64 work;
+ Boolean flag1;
+ Boolean flag2;
+
+ CInt64_SetLong(&value, 0);
+ flag1 = 0;
+ flag2 = 0;
+ if (addr->numObjRefs == 1) {
+ Object *obj;
+#line 1383
+ IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand);
+ IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF);
+ obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref;
+#line 1387
+ IRO_ASSERT(obj != NULL);
+ result |= EvalExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf);
+ flag2 = 1;
+ }
+
+ if (addr->numMisc != 0) {
+ IROElmList *list;
+ IROLinear *nd;
+ max = cint64_max;
+
+ for (list = addr->misc; list; list = list->next) {
+ nd = list->element;
+ while (nd && nd->type == IROLinearOp1Arg && nd->nodetype == ETYPCON)
+ nd = nd->u.monadic;
+
+ if (nd) {
+ if (nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) {
+ if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) {
+ if (IRO_IsUnsignedType(nd->rtype))
+ work = CInt64_MulU(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
+ else
+ work = CInt64_Mul(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
+ IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
+ value = CInt64_Add(value, work);
+ } else if (IRO_IsIntConstant(nd->u.diadic.left)) {
+ work = nd->u.diadic.left->u.node->data.intval;
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else if (IRO_IsIntConstant(nd->u.diadic.right)) {
+ work = nd->u.diadic.right->u.node->data.intval;
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else {
+ max = cint64_one;
+ }
+ } else if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) {
+ if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) {
+ work = CInt64_Shl(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
+ IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
+ value = CInt64_Add(value, work);
+ } else if (IRO_IsIntConstant(nd->u.diadic.right)) {
+ work = CInt64_Shl(cint64_one, nd->u.diadic.right->u.node->data.intval);
+ IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else {
+ max = cint64_one;
+ }
+ } else {
+ LocationSet *tmp;
+ PAMemoryBlock *mb;
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalExpr(lss2, proc, nd, stackPtr, map, ptf);
+
+ if (LocationSetSet_FindUnknown(lss2)) {
+ max = cint64_one;
+ } else if (
+ LocationSetSet_Count(lss2) == 1 &&
+ (tmp = LocationSetSet_FindFirst(lss2)) &&
+ (LocationSet_stride(tmp) == 0) &&
+ (mb = LocationSet_block(tmp)) &&
+ (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT)
+ ) {
+ value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb)));
+ } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) {
+ if (flag1) {
+ LocationSetSet_RemoveAll(lss);
+ max = cint64_one;
+ }
+ LocationSetSet_AddSet(lss, lss2);
+ flag2 = 1;
+ } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ } else if (!flag1) {
+ LocationSetSet_AddSet(lss, lss2);
+ flag1 = 1;
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ }
+ }
+ }
+
+ if (IS_TYPE_POINTER(Int->rtype))
+ CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size);
+ else if (IS_TYPE_MEMBERPOINTER(Int->rtype))
+ CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size);
+ else
+ work = cint64_zero;
+
+ if (CInt64_GreaterU(work, max))
+ max = work;
+ }
+
+ if (addr->numInts != 0) {
+ IROElmList *list;
+ IROLinear *addend;
+
+ for (list = addr->ints; list; list = list->next) {
+ addend = list->element;
+
+ if (addend) {
+#line 1536
+ IRO_ASSERT(IRO_IsIntConstant(addend));
+
+ value = CInt64_Add(value, addend->u.node->data.intval);
+ }
+ }
+ }
+
+ IRO_TruncateValueToType(&value, Int->rtype);
+
+ if (LocationSetSet_Count(lss) == 0) {
+ if (CInt64_Equal(max, cint64_max)) {
+ PAMemoryBlock *mb;
+ LocationSet *ls;
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
+
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
+ LocationSetSet_Add(lss, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+ } else {
+ if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value))
+ LocationSetSet_ForEach(lss, EvalExprAction, &value);
+ }
+
+ if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max))
+ LocationSetSet_ForEach(lss, EvalExprAction2, &max);
+ }
+ } else if (Int->type == IROLinearOperand) {
+ Object *obj;
+ void *thing;
+ PAMemoryBlockKind kind;
+
+ thing = NULL;
+ if (IRO_IsIntConstant(Int)) {
+ kind = PAMEMORYBLOCKKIND_INT;
+ thing = &Int->u.node->data.intval;
+ } else if (Int->u.node->type == ESTRINGCONST) {
+ kind = PAMEMORYBLOCKKIND_6;
+ thing = Int->u.node;
+ } else if (Int->u.node->type == EOBJREF) {
+ obj = Int->u.node->data.objref;
+#line 1597
+ IRO_ASSERT(obj != NULL);
+ if (ObjectIsAnExtendedParamCandidate(obj)) {
+ kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
+ thing = CreateExtendedParam(stackPtr, map, obj, &result);
+ } else {
+ kind = PAMEMORYBLOCKKIND_LOCALVAR;
+ thing = PALocalVar_New();
+ if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj))
+ PALocalVar_InitByName(thing, obj->name->name);
+ else
+ PALocalVar_InitByObject(thing, obj);
+ }
+ }
+
+ if (thing) {
+ PAMemoryBlock *mb;
+ LocationSet *ls;
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, kind, thing);
+
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
+ LocationSetSet_Add(lss, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ }
+ } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EBITFIELD) {
+ LocationSet *ls;
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf);
+
+ if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, ls);
+ } else {
+#line 1643
+ CError_FATAL();
+ }
+
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+
+ LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype);
+
+ if (set && lss)
+ LocationSetSet_AddSet(set, lss);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+
+ return result;
+}
+
+static IROAddrRecord *IRO_InitENodeAddrRecordPointer(ENode *enode) {
+ IROAddrRecord *addr = IRO_malloc(sizeof(IROAddrRecord));
+
+ addr->numObjRefs = 0;
+ addr->objRefs = NULL;
+ addr->numMisc = 0;
+ addr->misc = NULL;
+ addr->numInts = 0;
+ addr->ints = NULL;
+ addr->x16 = 0;
+ addr->linear = (IROLinear *) enode;
+
+ return addr;
+}
+
+static void IRO_AddENodeElmToList(ENode *linear, IROElmList **list) {
+ IROElmList *elmlist = IRO_malloc(sizeof(IROElmList));
+ elmlist->element = linear;
+ elmlist->next = NULL;
+ if (!*list) {
+ *list = elmlist;
+ } else {
+ elmlist->next = *list;
+ *list = elmlist;
+ }
+}
+
+static void IRO_DecomposeENodeAddressExpression(ENode *node, IROAddrRecord *addr) {
+ if (node->data.diadic.left->type == EADD) {
+ IRO_DecomposeENodeAddressExpression(node->data.diadic.left, addr);
+ } else if (node->data.diadic.left->type == EINTCONST) {
+ addr->numInts++;
+ IRO_AddENodeElmToList(node->data.diadic.left, &addr->ints);
+ } else if (node->data.diadic.left->type == EOBJREF) {
+ addr->numObjRefs++;
+ IRO_AddENodeElmToList(node->data.diadic.left, &addr->objRefs);
+ } else {
+ addr->numMisc++;
+ IRO_AddENodeElmToList(node->data.diadic.left, &addr->misc);
+ }
+
+ if (node->data.diadic.right->type == EADD) {
+ IRO_DecomposeENodeAddressExpression(node->data.diadic.right, addr);
+ } else if (node->data.diadic.right->type == EINTCONST) {
+ addr->numInts++;
+ IRO_AddENodeElmToList(node->data.diadic.right, &addr->ints);
+ } else if (node->data.diadic.right->type == EOBJREF) {
+ addr->numObjRefs++;
+ IRO_AddENodeElmToList(node->data.diadic.right, &addr->objRefs);
+ } else {
+ addr->numMisc++;
+ IRO_AddENodeElmToList(node->data.diadic.right, &addr->misc);
+ }
+}
+
+static Boolean EvalENodeExpr(LocationSetSet *set, Object *proc, ENode *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ Boolean result;
+ LocationSetSet *lss;
+ LocationSetSet *lss2;
+ ENode *indirect;
+ EvalExprAction3Params params;
+ ENode *originalInt;
+
+ IRO_ASSERT(set == NULL || set != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(Int != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+
+ result = 0;
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+
+ originalInt = Int;
+ while (Int && Int->type == ETYPCON)
+ Int = Int->data.monadic;
+
+ IRO_ASSERT(Int != NULL);
+
+ if (IRO_IsAssignOp[Int->type]) {
+ if (Int->type == EPOSTINC || Int->type == EPOSTDEC || Int->type == EPREINC || Int->type == EPREDEC)
+ indirect = Int->data.monadic;
+ else
+ indirect = Int->data.diadic.left;
+ IRO_ASSERT(indirect->type == EINDIRECT);
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalENodeExpr(lss2, proc, indirect->data.monadic, stackPtr, map, ptf);
+
+ memset(&params, 0, sizeof(params));
+ params.set = lss;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ if (Int->type == EPOSTINC || Int->type == EPOSTDEC)
+ params.pointsToFunc = indirect->pointsTo;
+ else
+ params.pointsToFunc = Int->pointsTo;
+ params.indRtype = indirect->rtype;
+ params.x1C = 0;
+ LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
+ result |= params.x1C;
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else if (Int->type == EINDIRECT) {
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf);
+
+ memset(&params, 0, sizeof(params));
+ params.set = lss;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ params.pointsToFunc = Int->pointsTo;
+ params.indRtype = Int->rtype;
+ params.x1C = 0;
+ LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
+ result |= params.x1C;
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else if (Int->type == EADD) {
+ IROAddrRecord *addr = IRO_InitENodeAddrRecordPointer(Int);
+ IRO_DecomposeENodeAddressExpression(Int, addr);
+ if (addr->numObjRefs > 1) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ } else {
+ CInt64 value;
+ CInt64 max;
+ CInt64 work;
+ Boolean flag1;
+ Boolean flag2;
+
+ CInt64_SetLong(&value, 0);
+ flag1 = 0;
+ flag2 = 0;
+ if (addr->numObjRefs == 1) {
+ Object *obj;
+ // IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand);
+ // IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF);
+ obj = ((ENode *) addr->objRefs->element)->data.objref;
+ IRO_ASSERT(obj != NULL);
+ result |= EvalENodeExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf);
+ flag2 = 1;
+ }
+
+ if (addr->numMisc != 0) {
+ IROElmList *list;
+ ENode *nd;
+ max = cint64_max;
+
+ for (list = addr->misc; list; list = list->next) {
+ nd = list->element;
+ while (nd && nd->type == ETYPCON)
+ nd = nd->data.monadic;
+
+ if (nd) {
+ if (nd->type == EMUL) {
+ if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) {
+ if (IRO_IsUnsignedType(nd->rtype))
+ work = CInt64_MulU(nd->data.diadic.left->data.intval,
+ nd->data.diadic.right->data.intval);
+ else
+ work = CInt64_Mul(nd->data.diadic.left->data.intval,
+ nd->data.diadic.right->data.intval);
+ IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
+ value = CInt64_Add(value, work);
+ } else if (nd->data.diadic.left->type == EINTCONST) {
+ work = nd->data.diadic.left->data.intval;
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else if (nd->data.diadic.right->type == EINTCONST) {
+ work = nd->data.diadic.right->data.intval;
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else {
+ max = cint64_one;
+ }
+ } else if (nd->type == ESHL) {
+ if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) {
+ work = CInt64_Shl(nd->data.diadic.left->data.intval,
+ nd->data.diadic.right->data.intval);
+ IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
+ value = CInt64_Add(value, work);
+ } else if (nd->data.diadic.right->type == EINTCONST) {
+ work = CInt64_Shl(cint64_one, nd->data.diadic.right->data.intval);
+ IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
+ if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
+ max = work;
+ } else {
+ max = cint64_one;
+ }
+ } else {
+ LocationSet *tmp;
+ PAMemoryBlock *mb;
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalENodeExpr(lss2, proc, nd, stackPtr, map, ptf);
+
+ if (LocationSetSet_FindUnknown(lss2)) {
+ max = cint64_one;
+ } else if (
+ LocationSetSet_Count(lss2) == 1 &&
+ (tmp = LocationSetSet_FindFirst(lss2)) &&
+ (LocationSet_stride(tmp) == 0) &&
+ (mb = LocationSet_block(tmp)) &&
+ (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT)
+ ) {
+ value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb)));
+ } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) {
+ if (flag1) {
+ LocationSetSet_RemoveAll(lss);
+ max = cint64_one;
+ }
+ LocationSetSet_AddSet(lss, lss2);
+ flag2 = 1;
+ } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ } else if (!flag1) {
+ LocationSetSet_AddSet(lss, lss2);
+ flag1 = 1;
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ }
+ }
+ }
+
+ if (IS_TYPE_POINTER(Int->rtype))
+ CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size);
+ else if (IS_TYPE_MEMBERPOINTER(Int->rtype))
+ CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size);
+ else
+ work = cint64_zero;
+
+ if (CInt64_GreaterU(work, max))
+ max = work;
+ }
+
+ if (addr->numInts != 0) {
+ IROElmList *list;
+ ENode *addend;
+
+ for (list = addr->ints; list; list = list->next) {
+ addend = list->element;
+
+ if (addend) {
+ IRO_ASSERT(addend->type == EINTCONST);
+
+ value = CInt64_Add(value, addend->data.intval);
+ }
+ }
+ }
+
+ IRO_TruncateValueToType(&value, Int->rtype);
+
+ if (LocationSetSet_Count(lss) == 0) {
+ if (CInt64_Equal(max, cint64_max)) {
+ PAMemoryBlock *mb;
+ LocationSet *ls;
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
+
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
+ LocationSetSet_Add(lss, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+ } else {
+ if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value))
+ LocationSetSet_ForEach(lss, EvalExprAction, &value);
+ }
+
+ if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max))
+ LocationSetSet_ForEach(lss, EvalExprAction2, &max);
+ }
+ } else if (Int->type == EOBJREF || Int->type == EINTCONST || Int->type == ESTRINGCONST) {
+ Object *obj;
+ void *thing;
+ PAMemoryBlockKind kind;
+
+ thing = NULL;
+ if (Int->type == EINTCONST) {
+ kind = PAMEMORYBLOCKKIND_INT;
+ thing = &Int->data.intval;
+ } else if (Int->type == ESTRINGCONST) {
+ kind = PAMEMORYBLOCKKIND_6;
+ thing = Int;
+ } else if (Int->type == EOBJREF) {
+ obj = Int->data.objref;
+ IRO_ASSERT(obj != NULL);
+ if (ObjectIsAnExtendedParamCandidate(obj)) {
+ kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
+ thing = CreateExtendedParam(stackPtr, map, obj, &result);
+ } else {
+ kind = PAMEMORYBLOCKKIND_LOCALVAR;
+ thing = PALocalVar_New();
+ if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj))
+ PALocalVar_InitByName(thing, obj->name->name);
+ else
+ PALocalVar_InitByObject(thing, obj);
+ }
+ }
+
+ if (thing) {
+ PAMemoryBlock *mb;
+ LocationSet *ls;
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, kind, thing);
+
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
+ LocationSetSet_Add(lss, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ }
+ } else if (Int->type == EBITFIELD) {
+ LocationSet *ls;
+
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf);
+
+ if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, ls);
+ } else {
+#line 2146
+ CError_FATAL();
+ }
+
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ } else {
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ }
+
+ LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype);
+
+ if (set && lss)
+ LocationSetSet_AddSet(set, lss);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+
+ return result;
+}
+
+static Boolean EvalVarAddr(LocationSetSet *set, Object *proc, VarRecord *var, Stack **stackPtr, ParamMappingFunction *map) {
+ Boolean result;
+ PAMemoryBlockKind kind;
+ void *thing;
+ Object *obj;
+ PAMemoryBlock *block;
+ LocationSet *loc;
+
+ result = 0;
+ obj = var->object;
+
+ if (ObjectIsAnExtendedParamCandidate(obj)) {
+ kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
+ thing = CreateExtendedParam(stackPtr, map, obj, &result);
+ } else {
+ kind = PAMEMORYBLOCKKIND_LOCALVAR;
+ thing = PALocalVar_New();
+ if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj))
+ PALocalVar_InitByName(thing, obj->name->name);
+ else
+ PALocalVar_InitByObject(thing, obj);
+ }
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, kind, thing);
+
+ loc = LocationSet_New();
+ LocationSet_InitKnown(loc, block, cint64_zero, 0, CDecl_NewPointerType(obj->type));
+ LocationSetSet_Add(set, loc);
+ LocationSet_Term(loc);
+ LocationSet_Delete(loc);
+
+ return result;
+}
+
+static Boolean EvalVariable(LocationSetSet *set, Object *proc, VarRecord *var, PointsToFunction *pointsToFunc, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ LocationSetSet *locs;
+ Boolean result;
+ EvalExprAction3Params params;
+
+ locs = LocationSetSet_New();
+ LocationSetSet_Init(locs);
+ result = EvalVarAddr(locs, proc, var, stackPtr, map);
+
+ memset(&params, 0, sizeof(params));
+ params.set = set;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ params.pointsToFunc = pointsToFunc;
+ params.indRtype = var->object->type;
+ params.x1C = 0;
+ LocationSetSet_ForEach(locs, EvalExprAction3, &params);
+
+ result |= params.x1C;
+ LocationSetSet_Term(locs);
+ LocationSetSet_Delete(locs);
+
+ return result;
+}
+
+static void StoreReturnedLocationsAction(LocationSet *loc, void *refcon) {
+#line 2275
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ if (!LocationSet_IsUnknown(loc)) {
+ if (PAMemoryBlock_kind(LocationSet_block(loc)) == PAMEMORYBLOCKKIND_HEAPBLOCK) {
+ PAHeapBlock *hb;
+ PAMemoryBlock *mb;
+ CInt64 field;
+ UInt32 stride;
+ Type *rtype;
+
+ hb = CreateUniqueHeapAlloc_sub_486420();
+ InitUniqueHeapAlloc_sub_486410(hb, refcon);
+
+ mb = PAMemoryBlock_New();
+ PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_HEAPBLOCK, hb);
+
+ field = LocationSet_field(loc);
+ stride = LocationSet_stride(loc);
+ rtype = LocationSet_rtype(loc);
+ LocationSet_Term(loc);
+ LocationSet_InitKnown(loc, mb, field, stride, rtype);
+ }
+ }
+}
+
+static void StoreReturnedLocations(IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map) {
+ LocationSet *retLoc;
+ LocationSetSet *retLocs;
+
+#line 2307
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(nd->type == IROLinearFunccall);
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(map != NULL);
+
+ retLoc = PartialTransferFunction_returnLocation(ptf);
+ retLocs = nd->u.funccall.returnedLocs;
+ if (!retLocs) {
+ LocationSetSet_Init(retLocs = nd->u.funccall.returnedLocs = LocationSetSet_New());
+ } else {
+ LocationSetSet_RemoveAll(retLocs);
+ }
+
+ Lookup(retLocs, NULL, NULL, NULL, NULL, retLoc, PartialTransferFunction_finalPointsToFn(ptf), 0, NULL);
+ ExpandLocationSetSetToActuals(&stCallingContextStack, map, retLocs);
+ LocationSetSet_ForEach(retLocs, StoreReturnedLocationsAction, nd);
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EPParams {
+ ParamMappingFunction *map;
+ ExtendedParam *ep;
+ Object *proc;
+ Object *var;
+ unsigned char x10;
+ unsigned char x11;
+} EPParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void FillInAppropriateMappingsWithExtParamAction(Object *obj, void *refcon) {
+ EPParams *params;
+ ParamMapping *mapping;
+
+#line 2352
+ IRO_ASSERT(obj != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 2357
+ IRO_ASSERT(params->map != NULL);
+ IRO_ASSERT(params->ep != NULL);
+ IRO_ASSERT(params->proc == NULL || params->proc != NULL);
+ IRO_ASSERT(params->proc != &stUnknown);
+ IRO_ASSERT(params->var == NULL || params->var != NULL);
+ IRO_ASSERT(params->var != &stUnknown);
+
+ mapping = ParamMappingFunction_FindMappingByFormal(params->map, obj);
+ if (!mapping) {
+ if (ObjectIsAnExtendedParamCandidate(obj) || !params->proc || ObjectIsAFunctionArgument(params->proc, obj)) {
+ mapping = ParamMapping_New();
+ ParamMapping_Init_PROBABLY(mapping, NULL, obj, params->ep);
+ Pmf_Add_sub_486610(params->map, mapping);
+ ParamMapping_Term(mapping);
+ ParamMapping_Delete(mapping);
+ params->x11 = 1;
+ }
+ } else {
+ if (ParamMapping_extended(mapping) != params->ep) {
+ ParamMapping_SetExtended(mapping, params->ep);
+ params->x11 = 1;
+ }
+ }
+
+ if (obj == params->var)
+ params->x10 = 1;
+}
+
+static Boolean FillInAppropriateMappingsWithExtParam(ParamMappingFunction *map, Object *var, ExtendedParam *ep, Object *proc) {
+ EPParams params;
+ ObjectSet *objSet;
+
+#line 2398
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(var == NULL || var != NULL);
+ IRO_ASSERT(var != &stUnknown);
+ IRO_ASSERT(ep != NULL);
+ IRO_ASSERT(proc == NULL || proc != NULL);
+ IRO_ASSERT(proc != &stUnknown);
+
+ memset(&params, 0, sizeof(params));
+ params.map = map;
+ params.ep = ep;
+ params.proc = proc;
+ params.var = var;
+ params.x10 = 0;
+ params.x11 = 0;
+
+ if ((objSet = ExtendedParam_objectSet(ep)))
+ ObjectSet_ForEach(objSet, FillInAppropriateMappingsWithExtParamAction, &params);
+
+ if (var && !params.x10) {
+ ExtendedParam_sub_4867B0(ep, var);
+ FillInAppropriateMappingsWithExtParamAction(var, &params);
+ }
+
+ return params.x11;
+}
+
+static void MatchPTFHelper(LocationSet *loc, LocationSetSet *locs, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ PointsToFunction *initial;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+ Object *obj;
+
+#line 2448
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+ IRO_ASSERT(locs != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ initial = PartialTransferFunction_initialPointsToFn(ptf);
+#line 2456
+ IRO_ASSERT(initial != NULL);
+
+#line 2458
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ block = LocationSet_block(loc);
+#line 2460
+ IRO_ASSERT(block != NULL);
+
+ kind = PAMemoryBlock_kind(block);
+
+ if (kind == PAMEMORYBLOCKKIND_LOCALVAR) {
+ PALocalVar *local;
+
+ local = PAMemoryBlock_thing(block);
+#line 2466
+ IRO_ASSERT(local != NULL);
+
+ obj = GetLocalObject(local, proc, 1);
+ if (obj && ObjectIsAFunctionArgument(proc, obj)) {
+ if (LocationSetSet_Count(locs) == 1) {
+ LocationSet *ls;
+ ls = LocationSetSet_FindFirst(locs);
+ if (ls && !LocationSet_IsUnknown(ls)) {
+ if ((block = LocationSet_block(ls))) {
+ if (PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ ExtendedParam *ep;
+ if ((ep = PAMemoryBlock_thing(block))) {
+ ExtendedParam_sub_4867B0(ep, obj);
+ if (stExtParamSet)
+ ExtParamSet_sub_487630(stExtParamSet, ep);
+ FillInAppropriateMappingsWithExtParam(map, obj, ep, proc);
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ void *ep = PAMemoryBlock_thing(block);
+#line 2489
+ IRO_ASSERT(ep != NULL);
+
+ obj = NULL;
+ ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj);
+ if (obj && obj != &stUnknown)
+ FillInAppropriateMappingsWithExtParam(map, obj, ep, proc);
+ } else {
+#line 2500
+ CError_FATAL();
+ }
+
+ if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, loc)) {
+ PointsToEntry *pte = PointsToEntry_New();
+ PointsToEntry_Init(pte, loc, locs);
+ PointsToFunction_AddWithoutChecking(initial, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct MatchPTFActionParams {
+ Object *proc;
+ PartialTransferFunction *ptfCopy;
+ ParamMappingFunction *mapCopy;
+ Stack **stackPtr;
+} MatchPTFActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void MatchPTFAction1(PointsToEntry *tgtPTE, void *refcon) {
+ MatchPTFActionParams *params;
+ LocationSet *loc;
+ LocationSetSet *locs;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+
+#line 2525
+ IRO_ASSERT(tgtPTE != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 2530
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->ptfCopy != NULL);
+ IRO_ASSERT(params->mapCopy != NULL);
+
+ if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) {
+ if ((block = LocationSet_block(loc))) {
+ kind = PAMemoryBlock_kind(block);
+ if (kind == PAMEMORYBLOCKKIND_LOCALVAR) {
+ MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy);
+ } else if (kind != PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+#line 2547
+ CError_FATAL();
+ }
+ }
+ }
+}
+
+static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) {
+ MatchPTFActionParams *params;
+ LocationSet *loc;
+ LocationSetSet *locs;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+
+#line 2561
+ IRO_ASSERT(tgtPTE != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 2566
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->ptfCopy != NULL);
+ IRO_ASSERT(params->mapCopy != NULL);
+
+ if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) {
+ if ((block = LocationSet_block(loc))) {
+ kind = PAMemoryBlock_kind(block);
+ if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy);
+ }
+ }
+ }
+}
+
+static Boolean MatchPTF(PartialTransferFunction *tgtPTF, Object *proc, ParamMappingFunction *map, IROLinear *nd, PartialTransferFunction *ptf) {
+ Boolean result;
+ PartialTransferFunction *ptfCopy;
+ ParamMappingFunction *mapCopy;
+ PointsToFunction *initial;
+ MatchPTFActionParams params;
+
+#line 2593
+ IRO_ASSERT(tgtPTF != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ ptfCopy = PartialTransferFunction_New();
+ PartialTransferFunction_Copy(ptfCopy, ptf);
+
+ mapCopy = ParamMappingFunction_New();
+ ParamMappingFunction_Copy(mapCopy, map);
+
+ initial = PartialTransferFunction_initialPointsToFn(tgtPTF);
+ PointsToFunction_SortByExtendedParamNum(initial);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptfCopy = ptfCopy;
+ params.mapCopy = mapCopy;
+ params.stackPtr = &stCallingContextStack;
+
+ PointsToFunction_ForEach(initial, MatchPTFAction1, &params);
+ PointsToFunction_ForEach(initial, MatchPTFAction2, &params);
+
+ result = PointsToFunctions_Match(initial, PartialTransferFunction_initialPointsToFn(ptfCopy));
+ if (result) {
+ PartialTransferFunction_Term(ptf);
+ PartialTransferFunction_Copy(ptf, ptfCopy);
+
+ ParamMappingFunction_Term(map);
+ ParamMappingFunction_Copy(map, mapCopy);
+ }
+
+ PartialTransferFunction_Term(ptfCopy);
+ PartialTransferFunction_Delete(ptfCopy);
+
+ ParamMappingFunction_Term(mapCopy);
+ ParamMappingFunction_Delete(mapCopy);
+
+ return result;
+}
+
+static void FindCallTargetsAction2(Object *obj, void *refcon) {
+ ObjectSet *procList;
+
+#line 2650
+ IRO_ASSERT(obj != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ procList = refcon;
+
+ if (obj == &stUnknown || ObjectIsAFunction(obj))
+ ObjectSet_sub_4867D0(procList, obj);
+}
+
+static void FindCallTargetsAction(LocationSet *ls, void *refcon) {
+ ObjectSet *procList;
+
+#line 2669
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ procList = refcon;
+
+ if (!LocationSet_IsUnknown(ls)) {
+ PAMemoryBlock *mb = LocationSet_block(ls);
+ if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ ExtendedParam *ep = PAMemoryBlock_thing(mb);
+ ObjectSet *objSet = ExtendedParam_objectSet(ep);
+ ObjectSet_ForEach(objSet, FindCallTargetsAction2, procList);
+ }
+ } else {
+ FindCallTargetsAction2(&stUnknown, procList);
+ }
+}
+
+static int FindCallTargets(ObjectSet *procList, Object *proc, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ LocationSetSet *set;
+ int evalResult;
+ int result;
+
+#line 2696
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(nd->type == IROLinearFunccall);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ evalResult = EvalExpr(set, proc, nd->u.funccall.linear8, &stCallingContextStack, map, ptf);
+ result = evalResult | ExpandLocationSetSetToActuals(&stCallingContextStack, map, set);
+ LocationSetSet_ForEach(set, FindCallTargetsAction, procList);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+
+ return result;
+}
+
+static int LookupParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, Boolean unkflag) {
+ Boolean result;
+ ExtendedParam *ep;
+
+#line 2728
+ IRO_ASSERT(set == NULL || set != NULL);
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(var != NULL);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(ptf == NULL || ptf != NULL);
+
+ result = 0;
+
+ ep = ExtendedParam_FindByObject(var);
+ if (!ep)
+ ep = CreateExtendedParam(stackPtr, map, var, &result);
+
+#line 2741
+ IRO_ASSERT(ep != NULL);
+
+ if (ep) {
+ PAMemoryBlock *block;
+ LocationSet *newLS;
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep);
+
+ newLS = LocationSet_New();
+ LocationSet_InitKnown(newLS, block, LocationSet_field(ls), LocationSet_stride(ls), LocationSet_rtype(ls));
+ if (set)
+ LocationSetSet_Add(set, newLS);
+
+ if (unkflag) {
+ if (map)
+ result |= FillInAppropriateMappingsWithExtParam(map, var, ep, proc);
+
+ if (ptf) {
+ PointsToFunction *initial;
+
+ initial = PartialTransferFunction_initialPointsToFn(ptf);
+ if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, ls)) {
+ LocationSet_Term(newLS);
+ LocationSet_InitKnown(newLS, LocationSet_block(ls), cint64_zero, 0, LocationSet_rtype(ls));
+ if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, newLS)) {
+ LocationSet *newLS2;
+ LocationSetSet *newSet;
+ PointsToEntry *newPTE;
+
+ newLS2 = LocationSet_New();
+ LocationSet_InitKnown(newLS2, block, cint64_zero, 0, LocationSet_rtype(ls));
+
+ newSet = LocationSetSet_New();
+ LocationSetSet_Init(newSet);
+ LocationSetSet_Add(newSet, newLS2);
+
+ newPTE = PointsToEntry_New();
+ PointsToEntry_Init(newPTE, newLS, newSet);
+ result |= PointsToFunction_Add(initial, newPTE);
+ PointsToEntry_Term(newPTE);
+ PointsToEntry_Delete(newPTE);
+
+ LocationSetSet_Term(newSet);
+ LocationSetSet_Delete(newSet);
+
+ LocationSet_Term(newLS2);
+ LocationSet_Delete(newLS2);
+ }
+ }
+ }
+ }
+
+ LocationSet_Term(newLS);
+ LocationSet_Delete(newLS);
+ }
+
+ return result;
+}
+
+static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag) {
+ Boolean result;
+ PAMemoryBlock *block;
+ IROLinear *nd;
+ ExtendedParam *ep;
+ ParamMapping *mapping;
+ Type *savedRtype;
+ CInt64 savedField;
+ UInt32 savedStride;
+ LocationSetSet *newSet;
+
+#line 2821
+ IRO_ASSERT(set == NULL || set != NULL);
+ IRO_ASSERT((ls != NULL && var == NULL) || (ls == NULL && var != NULL));
+ IRO_ASSERT(ls == NULL || !LocationSet_IsUnknown(ls));
+ IRO_ASSERT(var != &stUnknown);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+
+ result = 0;
+ block = NULL;
+ nd = 0;
+ ep = NULL;
+ mapping = NULL;
+
+ if (ls) {
+ block = LocationSet_block(ls);
+#line 2838
+ IRO_ASSERT(block != NULL);
+ IRO_ASSERT(PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ ep = PAMemoryBlock_thing(block);
+#line 2842
+ IRO_ASSERT(ep != NULL);
+
+ savedField = LocationSet_field(ls);
+ savedStride = LocationSet_stride(ls);
+ savedRtype = LocationSet_rtype(ls);
+ }
+
+#line 2848
+ IRO_ASSERT(ep == NULL || ep != NULL);
+
+ if (stackPtr && *stackPtr) {
+ StackElement *element = Stack_Top(stackPtr);
+ if (element && !map)
+ map = StackElement_map(element);
+ }
+
+#line 2859
+ IRO_ASSERT(map == NULL || map != NULL);
+
+ if (ep) {
+#line 2863
+ IRO_ASSERT(var == NULL);
+ ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var);
+ if (!var)
+ var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep));
+ if (!var)
+ var = &stUnknown;
+ }
+
+#line 2870
+ IRO_ASSERT(var != NULL);
+
+ if (map && var != &stUnknown) {
+ if (flag)
+ result |= FillInAppropriateMappingsWithExtParam(map, var, ep, NULL);
+ mapping = ParamMappingFunction_FindMappingByFormal(map, var);
+ }
+
+ newSet = LocationSetSet_New();
+ LocationSetSet_Init(newSet);
+
+#line 2884
+ IRO_ASSERT(mapping == NULL || mapping != NULL);
+
+ if (mapping)
+ nd = ParamMapping_actual(mapping);
+
+ if (!nd) {
+ if (!ls) {
+#line 2893
+ IRO_ASSERT(var != NULL);
+ IRO_ASSERT(ep == NULL);
+
+ if (var != &stUnknown) {
+ ep = CreateExtendedParam(stackPtr, NULL, var, &result);
+ if (flag && mapping && ParamMapping_extended(mapping) != ep) {
+ ParamMapping_SetExtended(mapping, ep);
+ result = 1;
+ }
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep);
+ savedField = cint64_zero;
+ savedStride = 0;
+ savedRtype = CDecl_NewPointerType(var->type);
+ } else {
+ block = LocationSet_block(stUnknownLs);
+ savedRtype = NULL;
+ }
+ } else if (var == &stUnknown || !ObjectIsAnExtendedParamCandidate(var)) {
+ block = LocationSet_block(stUnknownLs);
+ savedRtype = NULL;
+ }
+
+#line 2925
+ IRO_ASSERT(block != NULL);
+
+ if (block == LocationSet_block(stUnknownLs)) {
+ LocationSetSet_AddUnknown(newSet, savedRtype, NULL, NULL);
+ } else {
+ LocationSet *tmp = LocationSet_New();
+ LocationSet_InitKnown(tmp, block, savedField, savedStride, savedRtype);
+ LocationSetSet_Add(newSet, tmp);
+ LocationSet_Term(tmp);
+ LocationSet_Delete(tmp);
+ }
+ } else {
+ Stack *next;
+ StackElement *element;
+ if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) {
+ if (ls) {
+ if (!savedStride && !CInt64_IsZero(&savedField)) {
+ IROLinear *ic;
+ IROLinear *d;
+ ic = IRO_NewIntConst(savedField, TYPE(&stunsignedlong));
+ d = IRO_NewLinear(IROLinearOp2Arg);
+ d->index = ++IRO_NumLinear;
+ d->rtype = nd->rtype;
+ d->u.diadic.left = nd;
+ d->u.diadic.right = ic;
+ nd = d;
+ }
+ if (savedStride) {
+ IROLinear *call;
+ IROLinear *d;
+ call = IRO_NewLinear(IROLinearFunccall);
+ call->u.funccall.returnedLocs = LocationSetSet_New();
+ LocationSetSet_Init(call->u.funccall.returnedLocs);
+ LocationSetSet_AddUnknown(call->u.funccall.returnedLocs, NULL, NULL, NULL);
+ d = IRO_NewLinear(IROLinearOp2Arg);
+ d->index = ++IRO_NumLinear;
+ d->rtype = nd->rtype;
+ d->u.diadic.left = nd;
+ d->u.diadic.right = call;
+ nd = d;
+ }
+ }
+ EvalExpr(newSet, StackElement_proc(element), nd, &next, StackElement_map(element), StackElement_ptf(element));
+ } else {
+ LocationSetSet_AddUnknown(newSet, NULL, NULL, NULL);
+ }
+ }
+
+ if (set)
+ LocationSetSet_AddSet(set, newSet);
+
+ LocationSetSet_Term(newSet);
+ LocationSetSet_Delete(newSet);
+
+ return result;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct ExpandLocationSetSetActionParams {
+ LocationSetSet *toBeRemoved;
+ LocationSetSet *toBeAdded;
+ Stack **stackPtr;
+ ParamMappingFunction *map;
+ Boolean x10;
+} ExpandLocationSetSetActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void ExpandLocationSetSetToActualsAction(LocationSet *ls, void *refcon) {
+ ExpandLocationSetSetActionParams *params;
+
+#line 3021
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 3026
+ IRO_ASSERT(params->toBeRemoved != NULL);
+ IRO_ASSERT(params->toBeAdded != NULL);
+ IRO_ASSERT(params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL);
+ IRO_ASSERT(params->map == NULL || params->map != NULL);
+
+ if (!LocationSet_IsUnknown(ls)) {
+ PAMemoryBlock *block = LocationSet_block(ls);
+ if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ ExtendedParam *ep = PAMemoryBlock_thing(block);
+ if (ep) {
+ ObjectSet *objSet = ExtendedParam_objectSet(ep);
+ Object *obj = NULL;
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ if (!obj) {
+ LocationSetSet_Add(params->toBeRemoved, ls);
+ params->x10 |= GetActualLocsOfExtendedParam(params->toBeAdded, ls, NULL, params->stackPtr, params->map, 0);
+ }
+ }
+ }
+ }
+}
+
+static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo) {
+ LocationSetSet *toBeRemoved;
+ LocationSetSet *toBeAdded;
+ ExpandLocationSetSetActionParams params;
+ Boolean result;
+
+#line 3063
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(thingsPointedTo != NULL);
+
+ toBeRemoved = LocationSetSet_New();
+ LocationSetSet_Init(toBeRemoved);
+
+ toBeAdded = LocationSetSet_New();
+ LocationSetSet_Init(toBeAdded);
+
+ memset(&params, 0, sizeof(params));
+ params.toBeRemoved = toBeRemoved;
+ params.toBeAdded = toBeAdded;
+ params.stackPtr = stackPtr;
+ params.map = map;
+ params.x10 = 0;
+
+ LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, &params);
+
+ result = params.x10;
+ LocationSetSet_sub_488700(thingsPointedTo, toBeRemoved);
+ LocationSetSet_AddSet(thingsPointedTo, toBeAdded);
+
+ LocationSetSet_Term(toBeRemoved);
+ LocationSetSet_Delete(toBeRemoved);
+
+ LocationSetSet_Term(toBeAdded);
+ LocationSetSet_Delete(toBeAdded);
+
+ return result;
+}
+
+static void EvaluatePartialAbsolute(LocationSetSet *set, LocationSetSet *thingsPointedTo, LocationSet *dst, Type *indRtype) {
+ LocationSet *absLoc;
+ Type *absLocRtype;
+ PAMemoryBlock *block;
+
+#line 3108
+ IRO_ASSERT(set != NULL);
+ IRO_ASSERT(thingsPointedTo != NULL);
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(indRtype != NULL);
+
+ absLoc = LocationSetSet_FindFirst(thingsPointedTo);
+#line 3114
+ IRO_ASSERT(absLoc != NULL);
+
+ if (!LocationSet_IsUnknown(absLoc))
+ absLocRtype = LocationSet_rtype(absLoc);
+
+ if (!LocationSet_IsUnknown(absLoc) && indRtype->size == absLocRtype->size) {
+ LocationSetSet_AddSet(set, thingsPointedTo);
+ } else if (
+ !LocationSet_IsUnknown(absLoc) &&
+ !LocationSet_stride(absLoc) &&
+ LocationSetSet_Count(thingsPointedTo) == 1 &&
+ (block = LocationSet_block(absLoc)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT &&
+ absLocRtype->size <= stsignedlonglong.size &&
+ indRtype->size < absLocRtype->size
+ ) {
+ CInt64 val2;
+ CInt64 val8;
+ CInt64 val4;
+ CInt64 val5;
+ CInt64 val1;
+ CInt64 val3;
+ CInt64 val7;
+ CInt64 val6;
+ LocationSet *ls;
+
+ val1 = LocationSet_field(absLoc);
+ val2 = *((CInt64 *) PAMemoryBlock_thing(block));
+ CInt64_SetLong(&val3, 8);
+ val4 = cint64_zero;
+ CInt64_SetLong(&val5, stsignedlonglong.size - absLocRtype->size);
+ val6 = CInt64_Sub(LocationSet_field(dst), val1);
+ CInt64_SetLong(&val7, absLocRtype->size - indRtype->size);
+ val5 = CInt64_Add(val5, val6);
+ val4 = CInt64_Add(val4, val7);
+ val4 = CInt64_Sub(val4, val6);
+ val5 = CInt64_MulU(val5, val3);
+ val4 = CInt64_MulU(val4, val3);
+ val8 = cint64_negone;
+ val8 = CInt64_Shl(val8, val5);
+ val8 = CInt64_ShrU(val8, val5);
+ val2 = CInt64_And(val2, val8);
+ val2 = CInt64_ShrU(val2, val4);
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &val2);
+
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, block, cint64_zero, 0, indRtype);
+ LocationSetSet_Add(set, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ } else {
+ LocationSetSet_AddUnknown(set, indRtype, NULL, NULL);
+ }
+}
+
+static Boolean AddToInitialPointsToFunc(Boolean flag, PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *set) {
+ Boolean result;
+ LocationSet *ls;
+ PointsToFunction *initial;
+ PointsToEntry *pte;
+
+#line 3192
+ IRO_ASSERT(ptf == NULL || ptf != NULL);
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(set != NULL);
+
+ result = 0;
+
+ if (flag && ptf) {
+ ls = LocationSetSet_FindUnknown(set);
+ if (!ls || LocationSet_rtype(ls)) {
+ initial = PartialTransferFunction_initialPointsToFn(ptf);
+ if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, dst)) {
+#line 3208
+ IRO_ASSERT(dst != NULL);
+
+ pte = PointsToEntry_New();
+ PointsToEntry_Init(pte, dst, set);
+ result = PointsToFunction_AddWithoutChecking(initial, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ }
+ }
+ }
+
+ return result;
+}
+
+static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype) {
+ Boolean result;
+ LocationSetSet *mySet;
+ LocationSetSet *set2;
+ PAMemoryBlock *block;
+ ExtendedParam *ep;
+ PALocalVar *local;
+ ObjectSet *objSet;
+ Object *obj;
+
+#line 3245
+ IRO_ASSERT(set == NULL || set != NULL);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(proc == NULL || proc != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(ptf == NULL || ptf != NULL);
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(pointsToFunc == NULL || pointsToFunc != NULL);
+ IRO_ASSERT(indRtype == NULL || indRtype != NULL);
+
+ result = 0;
+
+ set2 = NULL;
+
+ mySet = LocationSetSet_New();
+ LocationSetSet_Init(mySet);
+
+ if (proc) {
+ if (LocationIsVolatile(dst, proc))
+ LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
+ }
+
+ if (pointsToFunc && !LocationSet_IsUnknown(dst)) {
+ PointsToEntry *pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst);
+ if (pte) {
+ set2 = PointsToEntry_locs(pte);
+ } else if (indRtype) {
+ pte = PointsToFunction_FindContainingLocationSet(pointsToFunc, dst, indRtype);
+ if (pte)
+ set2 = PointsToEntry_locs(pte);
+ }
+ }
+
+ if (set2) {
+ if (indRtype)
+ EvaluatePartialAbsolute(mySet, set2, dst, indRtype);
+ else
+ LocationSetSet_AddSet(mySet, set2);
+ } else if (!set2) {
+ block = NULL;
+ if (!LocationSet_IsUnknown(dst))
+ block = LocationSet_block(dst);
+
+ if (!LocationSet_IsUnknown(dst) && LocationSet_stride(dst)) {
+ LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
+ } else if (
+ block &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
+ (ep = PAMemoryBlock_thing(block)) &&
+ (objSet = ExtendedParam_objectSet(ep))
+ ) {
+ obj = NULL;
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ if (!obj) {
+ LocationSetSet *lss3;
+ LocationSet *tmp;
+ // Boolean result1;
+ EvalExprAction3Params params;
+
+ lss3 = LocationSetSet_New();
+ LocationSetSet_Init(lss3);
+ result = GetActualLocsOfExtendedParam(lss3, dst, NULL, stackPtr, map, unk);
+
+ memset(&params, 0, sizeof(params));
+ params.set = mySet;
+ params.stackPtr = stackPtr;
+ params.proc = proc;
+ params.map = map;
+ params.ptf = ptf;
+ params.pointsToFunc = pointsToFunc;
+ params.indRtype = indRtype;
+ params.x1C = 0;
+ LocationSetSet_ForEach(lss3, EvalExprAction3, &params);
+ result |= params.x1C;
+
+ LocationSetSet_Term(lss3);
+ LocationSetSet_Delete(lss3);
+
+ if ((tmp = LocationSetSet_FindUnknown(mySet))) {
+ if (!LocationSet_restriction(tmp) && ObjectSet_Count(objSet) == 1) {
+ if ((obj = ObjectSet_FindFirst(objSet))) {
+ if (ObjectIsRestrictQualified(obj)) {
+ LocationSet_Term(tmp);
+ LocationSet_InitUnknown(tmp, indRtype, block, NULL);
+ }
+ }
+ }
+ }
+
+ result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet);
+ } else {
+ // Boolean result1;
+ Stack *next;
+ StackElement *element;
+
+ result = GetActualLocsOfExtendedParam(NULL, dst, NULL, stackPtr, map, unk);
+ if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) {
+ result |= Lookup(mySet, &next, StackElement_proc(element), StackElement_map(element),
+ StackElement_ptf(element), dst, StackElement_funcCall(element)->pointsToFunction, unk, indRtype);
+ } else {
+ LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
+ }
+
+ result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet);
+ }
+ } else if (
+ block &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
+ (local = PAMemoryBlock_thing(block)) &&
+ proc &&
+ (obj = GetLocalObject(local, proc, 1)) &&
+ ObjectIsAFunctionArgument(proc, obj)
+ ) {
+ result = LookupParam(mySet, dst, obj, stackPtr, proc, map, ptf, unk);
+ } else {
+ LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
+ }
+ }
+
+ if (set)
+ LocationSetSet_AddSet(set, mySet);
+
+ LocationSetSet_Term(mySet);
+ LocationSetSet_Delete(mySet);
+
+ return result;
+}
+
+static Boolean InputsHaveNewPointerValues(PartialTransferFunction *tgtPTF, PartialTransferFunction *ptf) {
+#line 3393
+ IRO_ASSERT(tgtPTF != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ return 0;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct CreateEPActionParams {
+ ParamMapping *last;
+ ParamMapping *lowest;
+} CreateEPActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void CreateExtendedParamAction(ParamMapping *mapping, void *refcon) {
+ CreateEPActionParams *params;
+ ExtendedParam *ep;
+ uint32 value;
+ ExtendedParam *lowestEP;
+ uint32 lowestValue;
+ ExtendedParam *lastEP;
+ uint32 lastValue;
+
+#line 3417
+ IRO_ASSERT(mapping != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(params->last == NULL || params->last != NULL);
+ IRO_ASSERT(params->lowest == NULL || params->lowest != NULL);
+
+ if ((ep = ParamMapping_extended(mapping))) {
+ value = ExtendedParam_sub_489110(ep);
+
+ if (params->lowest) {
+ lowestEP = ParamMapping_extended(params->lowest);
+ lowestValue = ExtendedParam_sub_489110(lowestEP);
+ if (params->last) {
+ lastEP = ParamMapping_extended(params->last);
+ lastValue = ExtendedParam_sub_489110(lastEP);
+ if (value > lastValue && value < lowestValue)
+ params->lowest = mapping;
+ } else if (value < lowestValue) {
+ params->lowest = mapping;
+ }
+ } else if (params->last) {
+ lastEP = ParamMapping_extended(params->last);
+ lastValue = ExtendedParam_sub_489110(lastEP);
+ if (value > lastValue)
+ params->lowest = mapping;
+ } else {
+ params->lowest = mapping;
+ }
+ }
+}
+
+static ExtendedParam *FindMatchingExtendedParam(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *lss, ParamMapping *lowest, Boolean *result) {
+ ExtendedParam *ep;
+ ExtendedParam *lowestEP;
+
+#line 3473
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(lowest != NULL);
+
+ ep = NULL;
+ if ((lowestEP = ParamMapping_extended(lowest))) {
+ PAMemoryBlock *block;
+ LocationSet *lowestLS;
+ LocationSetSet *lowestLSS;
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, lowestEP);
+
+ lowestLS = LocationSet_New();
+ LocationSet_InitKnown(lowestLS, block, cint64_zero, 0, TYPE(&void_ptr));
+
+ lowestLSS = LocationSetSet_New();
+ LocationSetSet_Init(lowestLSS);
+
+ *result |= GetActualLocsOfExtendedParam(lowestLSS, lowestLS, NULL, stackPtr, map, 0);
+ if (LocationSetSets_Equal(lowestLSS, lss))
+ ep = lowestEP;
+
+ LocationSetSet_Term(lowestLSS);
+ LocationSetSet_Delete(lowestLSS);
+
+ LocationSet_Term(lowestLS);
+ LocationSet_Delete(lowestLS);
+ }
+
+ return ep;
+}
+
+static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result) {
+ ExtendedParam *ep;
+ ParamMapping *mapping;
+ LocationSetSet *lss;
+ CreateEPActionParams params;
+
+#line 3518
+ IRO_ASSERT(map == NULL || map != NULL);
+ IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(var != NULL);
+
+ mapping = NULL;
+ if (map)
+ mapping = ParamMappingFunction_FindMappingByFormal(map, var);
+
+ ep = ExtendedParam_FindByObject(var);
+ if (ep) {
+ if (mapping) {
+#line 3535
+ IRO_ASSERT(ep == ParamMapping_extended(mapping) || ParamMapping_extended(mapping) == NULL);
+ }
+ } else if (map && !ObjectIsRestrictQualified(var)) {
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ *result |= GetActualLocsOfExtendedParam(lss, NULL, var, stackPtr, map, 0);
+
+ memset(&params, 0, sizeof(params));
+ params.last = NULL;
+ do {
+ params.lowest = NULL;
+ pmf_sub_487C70(map, CreateExtendedParamAction, &params);
+ if (params.lowest && params.lowest != mapping)
+ ep = FindMatchingExtendedParam(stackPtr, map, lss, params.lowest, result);
+ params.last = params.lowest;
+ } while (params.lowest && !ep);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+
+ if (!ep)
+ ep = ExtendedParam_FindByObject(var);
+
+ if (!ep) {
+ ep = ExtendedParam_New();
+ ExtendedParam_Init(ep, var);
+ } else {
+ ExtendedParam_sub_4867B0(ep, var);
+ }
+
+ if (stExtParamSet)
+ ExtParamSet_sub_487630(stExtParamSet, ep);
+
+#line 3583
+ IRO_ASSERT(ep != NULL);
+
+ return ep;
+}
+
+#ifdef IRO_DEBUG
+void __assertion_failed(char *expr, char *filename, int line) {
+#line 3605
+ CError_ASSERT(filename);
+ CError_Internal(filename, line);
+}
+#endif
+
+static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) {
+#line 3628
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(nd->type == IROLinearFunccall);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(map != NULL);
+
+ if (proc != &stUnknown) {
+ int i;
+ ObjectList *args;
+ Object *arg;
+
+ args = FunctionArguments(proc);
+ if (args)
+ arg = args->object;
+ else
+ arg = &stUnknown;
+
+ for (i = 0; i < nd->u.funccall.argCount; i++) {
+#line 3643
+ IRO_ASSERT(arg != NULL);
+
+ if (arg != &stUnknown) {
+ ParamMapping *mapping = ParamMapping_New();
+ ParamMapping_Init_PROBABLY(mapping, nd->u.funccall.args[i], arg, NULL);
+ Pmf_Add_sub_486610(map, mapping);
+ ParamMapping_Term(mapping);
+ ParamMapping_Delete(mapping);
+ }
+
+ if (args) {
+ args = args->next;
+ if (args)
+ arg = args->object;
+ else
+ arg = &stUnknown;
+ }
+ }
+ }
+}
+
+static Boolean IsAddressableLocation(LocationSet *loc, Object *proc, IRONode *fnode, IROLinear *nd) {
+#line 3676
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(nd != NULL);
+
+ if (!LocationSet_IsUnknown(loc)) {
+ PAMemoryBlock *block;
+ PALocalVar *local;
+ Object *obj;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+
+ block = LocationSet_block(loc);
+ if (
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
+ (local = PAMemoryBlock_thing(block)) &&
+ (obj = GetLocalObject(local, proc, 0)) &&
+ fnode->addressed &&
+ !ObjectSet_sub_485020(fnode->addressed, obj)
+ ) {
+ return 0;
+ }
+
+ if (
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
+ (ep = PAMemoryBlock_thing(block)) &&
+ (objSet = ExtendedParam_objectSet(ep)) &&
+ ObjectSet_Count(objSet) == 1 &&
+ (obj = ObjectSet_FindFirst(objSet)) &&
+ ObjectIsAFunctionArgument(proc, obj) &&
+ ObjectIsRestrictQualified(obj)
+ ) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static Boolean LocationSetsAlias(LocationSet *ls1, LocationSet *ls2) {
+#line 3719
+ IRO_ASSERT(ls1 != NULL);
+ IRO_ASSERT(ls2 != NULL);
+
+ return
+ (ls1 == ls2) ||
+ LocationSet_IsUnknown(ls1) ||
+ LocationSet_IsUnknown(ls2) ||
+ (
+ (LocationSet_stride(ls1) ||
+ LocationSet_stride(ls2) ||
+ CInt64_Equal(LocationSet_field(ls1), LocationSet_field(ls2))) &&
+ MemoryBlocks_Equal(LocationSet_block(ls1), LocationSet_block(ls2))
+ );
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct FindAliasingParams {
+ LocationSetSet *x0;
+ LocationSet *x4;
+ Boolean x8;
+} FindAliasingParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void FindAliasingAction2(LocationSet *ls, void *refcon) {
+ FindAliasingParams *params;
+
+ params = refcon;
+
+ if (!params->x8) {
+ if (LocationSetsAlias(params->x4, ls))
+ params->x8 = 1;
+ }
+}
+
+static void FindAliasingAction(LocationSet *ls, void *refcon) {
+ FindAliasingParams *params;
+
+#line 3751
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+ if (!params->x8) {
+ params->x4 = ls;
+ LocationSetSet_ForEach(params->x0, FindAliasingAction2, params);
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct KillLocationParams {
+ Object *proc;
+ IRONode *fnode;
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ PointsToFunction *toBeKilled;
+ LocationSet *dst;
+ Boolean x18;
+} KillLocationParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void KillAllAddressableLocationsAction(PointsToEntry *pte, void *refcon) {
+ KillLocationParams *params;
+ LocationSet *loc;
+
+#line 3779
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 3784
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->toBeKilled != NULL);
+ IRO_ASSERT(params->dst == NULL);
+
+ loc = PointsToEntry_loc(pte);
+#line 3793
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ if (IsAddressableLocation(loc, params->proc, params->fnode, params->nd))
+ PointsToFunction_Add(params->toBeKilled, pte);
+}
+
+static void KillAllAliasingExtParamLocsAction(PointsToEntry *pte, void *refcon) {
+ KillLocationParams *params;
+ LocationSet *loc;
+
+#line 3813
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 3818
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->toBeKilled != NULL);
+ IRO_ASSERT(params->dst != NULL);
+ IRO_ASSERT(LocationSet_block(params->dst) != NULL);
+ IRO_ASSERT(PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ loc = PointsToEntry_loc(pte);
+#line 3829
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ if (loc != params->dst) {
+ if (LocationSetsAlias(loc, params->dst)) {
+ PointsToFunction_Add(params->toBeKilled, pte);
+ } else {
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+ Object *obj;
+ PAMemoryBlock *block;
+
+ if (
+ (ep = PAMemoryBlock_thing(LocationSet_block(params->dst))) &&
+ (objSet = ExtendedParam_objectSet(ep)) &&
+ (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) &&
+ (block = LocationSet_block(loc)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
+ (ep = PAMemoryBlock_thing(block)) &&
+ (objSet = ExtendedParam_objectSet(ep)) &&
+ (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj))
+ ) {
+ LocationSetSet *lss1;
+ LocationSetSet *lss2;
+ Boolean changed;
+ FindAliasingParams aparams;
+
+ lss1 = LocationSetSet_New();
+ LocationSetSet_Init(lss1);
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+
+ changed = GetActualLocsOfExtendedParam(lss1, loc, NULL, &stCallingContextStack, NULL, 0);
+ changed |= GetActualLocsOfExtendedParam(lss2, params->dst, NULL, &stCallingContextStack, NULL, 0);
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.x8 = 0;
+ aparams.x0 = lss2;
+ LocationSetSet_ForEach(lss1, FindAliasingAction, &aparams);
+ if (aparams.x8)
+ PointsToFunction_Add(params->toBeKilled, pte);
+
+ LocationSetSet_Term(lss1);
+ LocationSetSet_Delete(lss1);
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+ }
+ }
+ }
+}
+
+static void KillLocationsAction(PointsToEntry *pte, void *refcon) {
+ KillLocationParams *params;
+ LocationSet *loc;
+ LocationSetSet *lss;
+
+#line 3886
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 3891
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->toBeKilled != NULL);
+ IRO_ASSERT(params->dst == NULL);
+
+ loc = PointsToEntry_loc(pte);
+#line 3900
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+
+ params->x18 |= Assign(params->ptf, loc, lss, params->proc, params->nd, params->fnode);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+}
+
+static Boolean KillAllAddressableLocations(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) {
+ Boolean result;
+ PointsToFunction *pointsToFunc;
+ PointsToFunction *pointsToFuncCopy;
+ PointsToFunction *toBeKilled;
+ KillLocationParams params;
+
+#line 3921
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode == NULL || fnode != NULL);
+ IRO_ASSERT(nd == NULL || nd != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ if (nd && nd->pointsToFunction)
+ pointsToFunc = nd->pointsToFunction;
+ else
+ pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
+
+ pointsToFuncCopy = PointsToFunction_New();
+ PointsToFunction_Copy(pointsToFuncCopy, pointsToFunc);
+
+ toBeKilled = PointsToFunction_New();
+ PointsToFunction_Init(toBeKilled);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.fnode = fnode;
+ params.nd = nd;
+ params.ptf = ptf;
+ params.toBeKilled = toBeKilled;
+ params.dst = NULL;
+ params.x18 = 0;
+
+ if (pointsToFunc) {
+ PointsToFunction_ForEach(pointsToFunc, KillAllAddressableLocationsAction, &params);
+ PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, &params);
+ }
+
+ PointsToFunction_Term(toBeKilled);
+ PointsToFunction_Delete(toBeKilled);
+
+ if (params.x18)
+ result = !PointsToFunctions_Equal(pointsToFuncCopy, pointsToFunc);
+ else
+ result = 0;
+
+ PointsToFunction_Term(pointsToFuncCopy);
+ PointsToFunction_Delete(pointsToFuncCopy);
+
+ return result;
+}
+
+static void KillAllAliasingExtParamLocs(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, LocationSet *dst) {
+ PointsToFunction *pointsToFunc;
+ PointsToFunction *toBeKilled;
+ KillLocationParams params;
+
+#line 3974
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode == NULL || fnode != NULL);
+ IRO_ASSERT(nd == NULL || nd != NULL);
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(dst != NULL);
+
+ if (!LocationSet_IsUnknown(dst) && LocationSet_block(dst)) {
+ if (PAMemoryBlock_kind(LocationSet_block(dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+
+ if (nd && nd->pointsToFunction)
+ pointsToFunc = nd->pointsToFunction;
+ else
+ pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
+
+ toBeKilled = PointsToFunction_New();
+ PointsToFunction_Init(toBeKilled);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.fnode = fnode;
+ params.nd = nd;
+ params.ptf = ptf;
+ params.toBeKilled = toBeKilled;
+ params.dst = dst;
+ params.x18 = 0;
+
+ if (pointsToFunc) {
+ PointsToFunction_ForEach(pointsToFunc, KillAllAliasingExtParamLocsAction, &params);
+ PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, &params);
+ }
+
+ PointsToFunction_Term(toBeKilled);
+ PointsToFunction_Delete(toBeKilled);
+ }
+ }
+}
+
+static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode) {
+ PointsToFunction *pointsToFunc;
+ Boolean result;
+ PointsToEntry *pte;
+ LocationSet *loc;
+ LocationSetSet *locs;
+ LocationSet *bitfieldOf;
+ LocationSetSet *lss;
+
+#line 4027
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(srcs != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(nd == NULL || nd != NULL);
+ IRO_ASSERT(fnode == NULL || fnode != NULL);
+
+ if (nd) {
+ if (!nd->pointsToFunction) {
+ nd->pointsToFunction = PointsToFunction_New();
+ PointsToFunction_Init(nd->pointsToFunction);
+ }
+ pointsToFunc = nd->pointsToFunction;
+ } else {
+ pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
+ }
+
+ pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst);
+ if (pte) {
+ loc = PointsToEntry_loc(pte);
+ locs = PointsToEntry_locs(pte);
+#line 4056
+ IRO_ASSERT(!LocationSet_IsUnknown(dst));
+ IRO_ASSERT(LocationSet_stride(dst) == 0 || LocationSet_stride(loc) != 0);
+
+ result = !LocationSetSets_Equal(srcs, locs) || LocationSet_stride(dst) != LocationSet_stride(loc);
+
+ if (result) {
+ pte = PointsToEntry_New();
+ PointsToEntry_Init(pte, dst, srcs);
+ PointsToFunction_RemoveByLocationSet(pointsToFunc, loc);
+ PointsToFunction_AddWithoutChecking(pointsToFunc, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ }
+ } else if (!LocationSet_IsUnknown(dst)) {
+ KillAllAliasingExtParamLocs(proc, fnode, nd, ptf, dst);
+
+ pte = PointsToEntry_New();
+ PointsToEntry_Init(pte, dst, srcs);
+ result = PointsToFunction_AddWithoutChecking(pointsToFunc, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ } else if ((bitfieldOf = LocationSet_bitfieldOf(dst))) {
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
+ result = Assign(ptf, bitfieldOf, lss, proc, nd, fnode);
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ } else if (!LocationSet_restriction(dst)) {
+ result = KillAllAddressableLocations(proc, fnode, nd, ptf);
+ }
+
+ return result;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalMeetActionParams {
+ Object *proc;
+ IRONode *fnode;
+ IRONode *pred;
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ Boolean x14;
+ Boolean x15;
+} EvalMeetActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalMeetAction(PointsToEntry *pte, void *refcon) {
+ EvalMeetActionParams *params;
+ LocationSet *loc;
+ LocationSetSet *set;
+ UInt16 i;
+
+#line 4123
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 4128
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->pred != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+
+ loc = PointsToEntry_loc(pte);
+
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ LocationSetSet_AddSet(set, PointsToEntry_locs(pte));
+
+ for (i = 0; i < params->fnode->numpred; i++) {
+ IRONode *pred = FunctionNodeTable(params->proc)[params->fnode->pred[i]];
+ if (pred->x3C && pred != params->pred) {
+ params->x14 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, loc, pred->last->pointsToFunction, 0, NULL);
+ }
+ }
+
+ params->x15 |= Assign(params->ptf, loc, set, params->proc, params->nd, params->fnode);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+}
+
+static Boolean EvalMeet(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) {
+ PointsToFunction *pointsToFunc;
+ EvalMeetActionParams params;
+ int i;
+
+#line 4163
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ pointsToFunc = PointsToFunction_New();
+ if (nd->pointsToFunction)
+ PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
+ else
+ PointsToFunction_Init(pointsToFunc);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.fnode = fnode;
+ params.nd = nd;
+ params.ptf = ptf;
+ params.x14 = 0;
+ params.x15 = 0;
+
+ for (i = 0; i < fnode->numpred; i++) {
+ IRONode *pred = FunctionNodeTable(proc)[fnode->pred[i]];
+ params.pred = pred;
+ if (pred->x3C && pred->last->pointsToFunction) {
+ PointsToFunction_ForEach(pred->last->pointsToFunction, EvalMeetAction, &params);
+ }
+ }
+
+ if (!params.x14 && params.x15) {
+ if (nd->pointsToFunction)
+ params.x14 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
+ else
+ params.x14 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
+ }
+
+ PointsToFunction_Term(pointsToFunc);
+ PointsToFunction_Delete(pointsToFunc);
+
+ return params.x14;
+}
+
+static PartialTransferFunction *AllocatePTF(Object *proc, IROLinear *nd, PartialTransferFunction *ptf) {
+ PartialTransferFunction *newPTF;
+
+#line 4210
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(proc->u.func.ptfList != NULL);
+ IRO_ASSERT(nd == NULL || nd != NULL);
+ IRO_ASSERT(ptf == NULL || ptf != NULL);
+
+ newPTF = PartialTransferFunction_New();
+ PartialTransferFunction_Init(newPTF, nd, ptf);
+ PTFList_sub_48A050(proc->u.func.ptfList, newPTF);
+ return newPTF;
+}
+
+static Object *FindMainEntryPoint(Object *function) {
+#line 4229
+ IRO_ASSERT(function != NULL);
+
+ return function;
+}
+
+static ObjectList *FunctionArguments(Object *proc) {
+ Object *search;
+ ObjectList *scan;
+ ObjectList *list;
+ ObjectList *prev;
+ ExtendedParam *ep;
+ char *name;
+ VarInfo *vi;
+ Object *obj;
+ FuncArg *args;
+ Boolean notFound;
+
+#line 4252
+ IRO_ASSERT(proc != NULL);
+
+ if (proc == stCurrentProc) {
+ for (list = arguments; list; list = list->next) {
+ if ((obj = list->object) && obj->name && (name = obj->name->name) && name[0]) {
+ prev = NULL;
+ for (scan = proc->u.func.argList; scan; scan = scan->next) {
+ prev = scan;
+ if ((search = scan->object) && search->name && search->name->name) {
+ if (!strcmp(name, search->name->name))
+ break;
+ }
+ }
+
+ if (!scan)
+ search = NULL;
+
+ notFound = !search;
+
+ if (!search) {
+ search = IRO_malloc(sizeof(Object));
+ ep = NULL;
+ search->u.var.info = IRO_malloc(sizeof(VarInfo));
+ memset(search->u.var.info, 0, sizeof(VarInfo));
+ search->u.var.info->func = proc;
+ } else {
+ ep = search->extParam;
+ }
+
+ vi = search->u.var.info;
+ memcpy(search, obj, sizeof(Object));
+ search->extParam = ep;
+ search->u.var.info = vi;
+ search->u.var.realObj = obj;
+
+ if (notFound) {
+ scan = IRO_malloc(sizeof(ObjectList));
+ scan->next = NULL;
+ scan->object = search;
+ if (!prev)
+ proc->u.func.argList = scan;
+ else
+ prev->next = scan;
+ }
+ }
+ }
+ } else if (proc->type) {
+ for (args = TYPE_FUNC(proc->type)->args; args; args = args->next) {
+ if (args->name && (name = args->name->name) && name[0]) {
+ prev = NULL;
+ for (scan = proc->u.func.argList; scan; scan = scan->next) {
+ prev = scan;
+ if ((search = scan->object) && search->name && search->name->name) {
+ if (!strcmp(name, search->name->name))
+ break;
+ }
+ }
+
+ if (!scan)
+ search = NULL;
+
+ if (!search) {
+ search = IRO_malloc(sizeof(Object));
+ memset(search, 0, sizeof(Object));
+ search->datatype = DLOCAL;
+ search->extParam = NULL;
+ search->name = GetHashNameNodeExport(name);
+ search->type = args->type;
+ search->qual = args->qual;
+ search->u.var.info = IRO_malloc(sizeof(VarInfo));
+ memset(search->u.var.info, 0, sizeof(VarInfo));
+ search->u.var.info->func = proc;
+
+ scan = IRO_malloc(sizeof(ObjectList));
+ scan->next = NULL;
+ scan->object = search;
+ if (!prev)
+ proc->u.func.argList = scan;
+ else
+ prev->next = scan;
+ }
+ }
+ }
+ }
+
+ return proc->u.func.argList;
+}
+
+static IRONode **FunctionNodeTable(Object *proc) {
+#line 4383
+ IRO_ASSERT(proc != NULL);
+
+#line 4391
+ IRO_ASSERT(proc == stCurrentProc);
+
+ return IRO_NodeTable;
+}
+
+static IRONode *FunctionFirstNode(Object *proc) {
+#line 4401
+ IRO_ASSERT(proc != NULL);
+
+#line 4409
+ IRO_ASSERT(proc == stCurrentProc);
+
+ return IRO_FirstNode;
+}
+
+static void UpdatePTFDomain() {
+ // no idea what this would've done
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalCallActionParams {
+ Object *proc;
+ IRONode *fnode;
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ ParamMappingFunction *map;
+ int x14;
+ Boolean x18;
+ Boolean x19;
+ Boolean x1A;
+} EvalCallActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalCallAction(Object *proc, void *refcon) {
+ EvalCallActionParams *params;
+ ParamMappingFunction *pmf;
+ PartialTransferFunction *tgtPTF;
+ Boolean flag;
+ Boolean flag2;
+
+#line 4458
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 4463
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->map == NULL || params->map != NULL);
+
+ if (!params->x18) {
+ pmf = ParamMappingFunction_New();
+ ParamMappingFunction_Init(pmf);
+ RecordActuals(params->nd, proc, pmf);
+
+ flag = 0;
+ if (!Stack_sub_48A710(&stCallingContextStack, proc)) {
+ StackElement *element;
+
+ flag2 = 0;
+ tgtPTF = GetPTF(pmf, proc, params->nd, params->ptf, &flag2);
+
+ element = StackElement_New();
+ StackElement_Init(element, proc, tgtPTF, pmf, params->nd);
+ Stack_sub_48A660(&stCallingContextStack, element);
+ StackElement_Term(element);
+ StackElement_Delete(element);
+
+#line 4490
+ IRO_ASSERT(tgtPTF != NULL);
+
+ flag = 1;
+
+ if (stPTFList)
+ PTFList_sub_48A050(stPTFList, tgtPTF);
+ PartialTransferFunction_sub_48A610(tgtPTF, 0);
+
+ if (flag2 || params->x1A) {
+ if (params->x1A) {
+ params->x1A = 0;
+ EvalProc(proc, pmf, tgtPTF);
+ } else {
+ tgtPTF = stUnknownPTF;
+ }
+ }
+ } else {
+ tgtPTF = stUnknownPTF;
+ }
+
+ if (params->map)
+ params->x19 |= ApplySummary(tgtPTF, pmf, params->proc, params->fnode, params->nd, params->ptf, params->map, params->x14 == 1);
+
+ if (flag) {
+ StackElement *element = Stack_sub_48A5B0(&stCallingContextStack);
+ StackElement_Term(element);
+ StackElement_Delete(element);
+ }
+
+ ParamMappingFunction_Term(pmf);
+ ParamMappingFunction_Delete(pmf);
+ }
+}
+
+static Boolean EvalCall(Object *proc, IRONode *fnode, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ EvalCallActionParams params;
+ ObjectSet *objSet;
+
+#line 4548
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.fnode = fnode;
+ params.nd = nd;
+ params.ptf = ptf;
+ params.map = map;
+ params.x18 = 0;
+ params.x19 = 0;
+ params.x1A = 0;
+
+ objSet = ObjectSet_New();
+ ObjectSet_Init(objSet);
+
+ params.x19 |= FindCallTargets(objSet, proc, nd, map, ptf);
+ params.x14 = ObjectSet_Count(objSet);
+ ObjectSet_ForEach(objSet, EvalCallAction, &params);
+
+ ObjectSet_Term(objSet);
+ ObjectSet_Delete(objSet);
+
+ return params.x19;
+}
+
+static void AdjustTypesForVolatilityAction(LocationSet *ls, void *refcon) {
+ Type *type;
+ Type *newtype;
+ UInt32 qual;
+
+ type = LocationSet_rtype(ls);
+ switch (type->type) {
+ case TYPEARRAY:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEPOINTER:
+ qual = TYPE_POINTER(type)->qual;
+ break;
+ case TYPEMEMBERPOINTER:
+ qual = TYPE_MEMBER_POINTER(type)->qual;
+ break;
+ default:
+#line 4604
+ CError_FATAL();
+ }
+
+ if (!(qual & Q_VOLATILE)) {
+ switch (type->type) {
+ case TYPEARRAY:
+ newtype = CDecl_NewArrayType(TYPE_POINTER(type)->target, type->size);
+ TYPE_POINTER(newtype)->qual |= Q_VOLATILE;
+ break;
+ case TYPEPOINTER:
+ newtype = CDecl_NewPointerType(TYPE_POINTER(type)->target);
+ TYPE_POINTER(newtype)->qual |= Q_VOLATILE;
+ break;
+ case TYPEMEMBERPOINTER:
+ newtype = galloc(sizeof(TypeMemberPointer));
+ memcpy(newtype, type, sizeof(TypeMemberPointer));
+ TYPE_MEMBER_POINTER(newtype)->qual |= Q_VOLATILE;
+ break;
+ }
+
+ LocationSet_SetRtype(ls, newtype);
+ }
+}
+
+static void AdjustTypesForVolatility(LocationSetSet *set, Object *proc, IROLinear *nd) {
+ if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS))
+ LocationSetSet_ForEach(set, AdjustTypesForVolatilityAction, NULL);
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalAssignAction2Params {
+ CInt64 x0;
+ IROLinear *nd;
+ Boolean xC;
+} EvalAssignAction2Params;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalAssignAction2(LocationSet *ls, void *refcon) {
+ EvalAssignAction2Params *params;
+ CInt64 value;
+ IROLinear *nd;
+ ENodeType oper;
+ UInt32 stride;
+ Type *rtype;
+ PAMemoryBlock *block;
+
+#line 4657
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+ if (!params->xC && !LocationSet_IsUnknown(ls)) {
+ value = params->x0;
+ nd = params->nd;
+#line 4665
+ IRO_ASSERT(nd != NULL);
+ oper = nd->nodetype;
+
+ stride = LocationSet_stride(ls);
+ rtype = LocationSet_rtype(ls);
+ block = LocationSet_block(ls);
+
+ if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT) {
+ LocationSet_Term(ls);
+
+ switch (oper) {
+ case EPOSTINC:
+ case EPREINC:
+ case EADDASS:
+ value = CInt64_Add(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EPOSTDEC:
+ case EPREDEC:
+ case ESUBASS:
+ value = CInt64_Sub(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EMULASS:
+ if (IRO_IsUnsignedType(nd->rtype))
+ value = CInt64_MulU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ else
+ value = CInt64_Mul(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EDIVASS:
+ if (CInt64_IsZero(&value)) {
+ if (nd->stmt->sourceoffset) {
+ TStreamElement *e = CPrep_CurStreamElement();
+ e->tokenoffset = nd->stmt->sourceoffset;
+ CError_SetErrorToken(e);
+ }
+ CError_Warning(CErrorStr139);
+ params->xC = 1;
+ } else {
+ if (IRO_IsUnsignedType(nd->rtype))
+ value = CInt64_DivU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ else
+ value = CInt64_Div(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ }
+ break;
+ case EMODASS:
+ if (CInt64_IsZero(&value)) {
+ if (nd->stmt->sourceoffset) {
+ TStreamElement *e = CPrep_CurStreamElement();
+ e->tokenoffset = nd->stmt->sourceoffset;
+ CError_SetErrorToken(e);
+ }
+ CError_Warning(CErrorStr139);
+ params->xC = 1;
+ } else {
+ if (IRO_IsUnsignedType(nd->rtype))
+ value = CInt64_ModU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ else
+ value = CInt64_Mod(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ }
+ break;
+ case ESHLASS:
+ value = CInt64_Shl(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case ESHRASS:
+ if (IRO_IsUnsignedType(nd->rtype))
+ value = CInt64_ShrU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ else
+ value = CInt64_Shr(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EANDASS:
+ value = CInt64_And(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EXORASS:
+ value = CInt64_Xor(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ case EORASS:
+ value = CInt64_Or(*((CInt64 *) PAMemoryBlock_thing(block)), value);
+ break;
+ default:
+#line 4746
+ CError_FATAL();
+ }
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &value);
+ LocationSet_InitKnown(ls, block, cint64_zero, stride, rtype);
+ } else {
+ if (oper == EPOSTDEC || oper == EPREDEC || oper == ESUBASS)
+ value = CInt64_Neg(value);
+
+ switch (oper) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EADDASS:
+ case ESUBASS:
+ value = CInt64_Add(LocationSet_field(ls), value);
+ if (stride) {
+ CInt64 tmp;
+ CInt64_SetLong(&tmp, stride);
+ value = CInt64_Mod(value, tmp);
+ }
+ SetsLocationSetField_sub_4851B0(ls, value);
+ break;
+ default:
+ params->xC = 1;
+ break;
+ }
+ }
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalAssignActionParams {
+ Object *proc;
+ PartialTransferFunction *ptf;
+ IROLinear *nd;
+ IRONode *fnode;
+ LocationSetSet *srcs;
+ Boolean x14;
+ Boolean x15;
+ Boolean x16;
+} EvalAssignActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalAssignAction(LocationSet *dst, void *refcon) {
+ EvalAssignActionParams *params;
+ LocationSetSet *srcs;
+
+#line 4797
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 4802
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->srcs != NULL);
+
+ srcs = params->srcs;
+ if (
+ !params->x14 ||
+ !LocationSetRepresentsSingleLocation(dst, params->proc, params->nd->pointsToFunction) ||
+ LocationIsVolatile(dst, params->proc) ||
+ LocationSet_sub_48AF30(dst)
+ ) {
+ LocationSetSet *set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ params->x15 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, params->nd->pointsToFunction, 0, params->nd->rtype);
+ LocationSetSet_AddSet(srcs, set);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+
+ params->x16 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode);
+}
+
+static Boolean EvalAssign(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ EvalAssignActionParams params;
+ EvalAssignAction2Params params2;
+ LocationSetSet *set;
+ LocationSet *tmp;
+ PAMemoryBlock *block;
+ Type *type;
+
+#line 4840
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptf = ptf;
+ params.nd = nd;
+ params.fnode = fnode;
+ params.x15 = 0;
+ params.x16 = 0;
+
+ set = LocationSetSet_New();
+ params.srcs = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ LocationSetSet_Init(params.srcs);
+
+ if (nd->type == IROLinearOp2Arg) {
+#line 4861
+ IRO_ASSERT(nd->u.diadic.left->type == IROLinearOp1Arg && nd->u.diadic.left->nodetype == EINDIRECT);
+
+ params.x15 |= EvalExpr(set, proc, nd->u.diadic.left->u.monadic, &stCallingContextStack, map, ptf);
+ AdjustTypesForVolatility(set, proc, nd->u.diadic.left);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.right, &stCallingContextStack, map, ptf);
+
+ if (nd->nodetype != EASS) {
+ switch (nd->nodetype) {
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ if (
+ LocationSetSet_Count(params.srcs) == 1 &&
+ (tmp = LocationSetSet_FindFirst(params.srcs)) &&
+ !LocationSet_IsUnknown(tmp) &&
+ !LocationSet_stride(tmp) &&
+ (block = LocationSet_block(tmp)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT
+ ) {
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
+
+ memset(&params2, 0, sizeof(params2));
+ params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block));
+ IRO_TruncateValueToType(&params2.x0, nd->u.diadic.right->rtype);
+ params2.nd = nd;
+ params2.xC = 0;
+
+ if (!CInt64_IsZero(&params2.x0)) {
+ LocationSetSet_ForEach(params.srcs, EvalAssignAction2, &params2);
+ if (params2.xC) {
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
+ if (!LocationSetSet_FindUnknown(params.srcs))
+ LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
+ }
+ }
+ } else {
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
+ if (!LocationSetSet_FindUnknown(params.srcs))
+ LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
+ }
+ break;
+ default:
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL);
+ break;
+ }
+ }
+ } else if (nd->type == IROLinearOp1Arg) {
+#line 4958
+ IRO_ASSERT(nd->u.monadic.left->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EINDIRECT);
+
+ params.x15 |= EvalExpr(set, proc, nd->u.monadic->u.monadic, &stCallingContextStack, map, ptf);
+ AdjustTypesForVolatility(set, proc, nd->u.monadic);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
+
+ switch (nd->nodetype) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ memset(&params2, 0, sizeof(params2));
+ params2.x0 = cint64_one;
+ params2.nd = nd;
+ params2.xC = 0;
+
+ type = NULL;
+ if (IS_TYPE_POINTER(nd->rtype))
+ type = TPTR_TARGET(nd->rtype);
+ else if (IS_TYPE_MEMBERPOINTER(nd->rtype))
+ type = TYPE_MEMBER_POINTER(nd->rtype)->ty1;
+
+ if (type)
+ CInt64_SetLong(&params2.x0, type->size);
+
+ if (!CInt64_IsZero(&params2.x0)) {
+ LocationSetSet_ForEach(params.srcs, EvalAssignAction2, &params2);
+ if (params2.xC) {
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
+ if (!LocationSetSet_FindUnknown(params.srcs))
+ LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
+ }
+ }
+ break;
+
+ default:
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Init(params.srcs);
+ LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL);
+ break;
+ }
+ } else {
+#line 5006
+ CError_FATAL();
+ }
+
+ if (LocationSetSet_Count(params.srcs) != 0) {
+ PointsToFunction *pointsToFunc;
+
+ pointsToFunc = PointsToFunction_New();
+ if (nd->pointsToFunction)
+ PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
+ else
+ PointsToFunction_Init(pointsToFunc);
+
+ params.x14 = LocationSetSet_Count(set) == 1;
+ LocationSetSet_ForEach(set, EvalAssignAction, &params);
+
+ if (!params.x15 && params.x16) {
+ if (nd->pointsToFunction)
+ params.x15 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
+ else
+ params.x15 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
+ }
+
+ PointsToFunction_Term(pointsToFunc);
+ PointsToFunction_Delete(pointsToFunc);
+ }
+
+ LocationSetSet_Term(set);
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Delete(set);
+ LocationSetSet_Delete(params.srcs);
+
+ return params.x15;
+}
+
+static Boolean EvalReturn(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ EvalAssignActionParams params;
+ LocationSet *loc;
+
+#line 5046
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(nd->type == IROLinearReturn);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptf = ptf;
+ params.nd = nd;
+ params.fnode = fnode;
+ params.x15 = 0;
+ params.x16 = 0;
+
+ if (nd->u.monadic) {
+ params.srcs = LocationSetSet_New();
+ LocationSetSet_Init(params.srcs);
+
+ loc = PartialTransferFunction_returnLocation(ptf);
+ params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
+
+ if (LocationSetSet_Count(params.srcs) != 0) {
+ params.x14 = 1;
+ EvalAssignAction(loc, &params);
+ params.x15 |= params.x16;
+ }
+
+ LocationSetSet_Term(params.srcs);
+ LocationSetSet_Delete(params.srcs);
+ }
+
+ return params.x15;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct ApplySummaryActionParams {
+ ParamMappingFunction *tgtMap;
+ Object *proc;
+ IRONode *fnode;
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ ParamMappingFunction *map;
+ LocationSet *loc;
+ LocationSetSet *locs;
+ Boolean x20;
+ Boolean x21;
+ Boolean x22;
+} ApplySummaryActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void ApplySummaryAction2(ParamMapping *mapping, void *refcon) {
+ ApplySummaryActionParams *params;
+ PAMemoryBlock *block;
+ ExtendedParam *ep;
+ IROLinear *nd;
+ LocationSetSet *set;
+ EvalAssignActionParams assignParams;
+
+#line 5108
+ IRO_ASSERT(mapping != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5113
+ IRO_ASSERT(params->tgtMap != NULL);
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->nd->type == IROLinearFunccall);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->map != NULL);
+ IRO_ASSERT(params->loc != NULL);
+ IRO_ASSERT(params->locs != NULL);
+
+ block = LocationSet_block(params->loc);
+
+#line 5124
+ IRO_ASSERT(block != NULL);
+ IRO_ASSERT(PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ ep = PAMemoryBlock_thing(block);
+
+#line 5127
+ IRO_ASSERT(ep != NULL);
+
+ if (ParamMapping_extended(mapping) == ep && (nd = ParamMapping_actual(mapping))) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ params->x21 |= EvalExpr(set, params->proc, nd, &stCallingContextStack, params->map, params->ptf);
+
+ if (!LocationSetSet_FindUnknown(set)) {
+ CInt64 stride64;
+ CInt64 value;
+
+ value = LocationSet_field(params->loc);
+ LocationSetSet_ForEach(set, EvalExprAction, &value);
+
+ CInt64_SetULong(&stride64, LocationSet_stride(params->loc));
+ LocationSetSet_ForEach(set, EvalExprAction2, &stride64);
+ }
+
+ memset(&assignParams, 0, sizeof(assignParams));
+ assignParams.proc = params->proc;
+ assignParams.ptf = params->ptf;
+ assignParams.nd = params->nd;
+ assignParams.fnode = params->fnode;
+ assignParams.srcs = params->locs;
+ assignParams.x14 = params->x20 && (LocationSetSet_Count(set) == 1);
+ assignParams.x15 = 0;
+ assignParams.x16 = 0;
+ LocationSetSet_ForEach(set, EvalAssignAction, &assignParams);
+
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+
+ params->x21 |= assignParams.x15;
+ params->x22 |= assignParams.x16;
+ }
+}
+
+static void ApplySummaryAction(PointsToEntry *pte, void *refcon) {
+ ApplySummaryActionParams *params;
+ LocationSet *loc;
+ PAMemoryBlock *block;
+
+#line 5175
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5180
+ IRO_ASSERT(params->tgtMap != NULL);
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->nd->type == IROLinearFunccall);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->map != NULL);
+
+ loc = PointsToEntry_loc(pte);
+
+#line 5189
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ block = LocationSet_block(loc);
+ if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ params->loc = loc;
+ params->locs = PointsToEntry_locs(pte);
+ pmf_sub_487C70(params->tgtMap, ApplySummaryAction2, params);
+ }
+}
+
+static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag) {
+ Boolean result;
+ ApplySummaryActionParams params;
+ PointsToFunction *pointsToFunc;
+
+#line 5208
+ IRO_ASSERT(tgtPTF != NULL);
+ IRO_ASSERT(tgtMap != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(nd->type == IROLinearFunccall);
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(map != NULL);
+
+ StoreReturnedLocations(nd, tgtPTF, tgtMap);
+ if (tgtPTF == stUnknownPTF) {
+ result = KillAllAddressableLocations(proc, fnode, nd, ptf);
+ } else {
+ pointsToFunc = PointsToFunction_New();
+ if (nd->pointsToFunction)
+ PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
+ else
+ PointsToFunction_Init(pointsToFunc);
+
+ memset(&params, 0, sizeof(params));
+ params.tgtMap = tgtMap;
+ params.proc = proc;
+ params.fnode = fnode;
+ params.nd = nd;
+ params.ptf = ptf;
+ params.map = map;
+ params.loc = NULL;
+ params.locs = NULL;
+ params.x20 = flag;
+ params.x21 = 0;
+ params.x22 = 0;
+
+ PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(tgtPTF), ApplySummaryAction, &params);
+
+ result = params.x21;
+ if (!params.x21 && params.x22) {
+ if (nd->pointsToFunction)
+ result = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
+ else
+ result = PointsToFunction_FindFirst(pointsToFunc) != NULL;
+ }
+ }
+
+ return result;
+}
+
+static void GetPTFAction2(ParamMapping *mapping, void *refcon) {
+#line 5331
+ IRO_ASSERT(mapping != NULL);
+
+ if (ParamMapping_extended(mapping))
+ ParamMapping_SetExtended(mapping, NULL);
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct GetPTFActionParams {
+ ParamMappingFunction *map;
+ Object *proc;
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ Boolean *needVisit;
+ PartialTransferFunction *x14;
+ PartialTransferFunction *x18;
+} GetPTFActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void GetPTFAction(PartialTransferFunction *tgtPTF, void *refcon) {
+ GetPTFActionParams *params;
+
+#line 5359
+ IRO_ASSERT(tgtPTF != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5364
+ IRO_ASSERT(params->map != NULL);
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->proc != &stUnknown);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->needVisit != NULL);
+
+ if (!params->x18) {
+ if (MatchPTF(tgtPTF, params->proc, params->map, params->nd, params->ptf)) {
+ if (InputsHaveNewPointerValues(tgtPTF, params->ptf))
+ *params->needVisit = 1;
+ params->x18 = tgtPTF;
+ } else {
+ pmf_sub_487C70(params->map, GetPTFAction2, NULL);
+ if (PTF_sub_48B980(tgtPTF) == params->nd && PTF_sub_48B970(tgtPTF) == params->ptf)
+ params->x14 = tgtPTF;
+ }
+ }
+}
+
+static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit) {
+ PartialTransferFunction *found;
+ PartialTransferFunction *result;
+ GetPTFActionParams params;
+
+#line 5396
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(nd != NULL);
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(needVisit != NULL);
+
+ if (proc == &stUnknown) {
+ result = stUnknownPTF;
+ } else {
+ memset(&params, 0, sizeof(params));
+ params.map = map;
+ params.proc = proc;
+ params.nd = nd;
+ params.ptf = PartialTransferFunction_New();
+ PartialTransferFunction_Init(params.ptf, nd, ptf);
+ params.needVisit = needVisit;
+ params.x14 = NULL;
+ params.x18 = NULL;
+
+ if (!proc->u.func.ptfList) {
+ proc->u.func.ptfList = PTFList_New();
+ PTFList_Init(proc->u.func.ptfList);
+ }
+
+ PTFList_ForEach(proc->u.func.ptfList, GetPTFAction, &params);
+
+ found = params.x18;
+ if (found && !*needVisit) {
+ PartialTransferFunction_Copy(result = PartialTransferFunction_New(), found);
+ } else {
+ result = stUnknownPTF;
+ }
+
+ PartialTransferFunction_Term(params.ptf);
+ PartialTransferFunction_Delete(params.ptf);
+ }
+
+ return result;
+}
+
+static Boolean IsMeetNode(IRONode *fnode, IROLinear *nd) {
+ return (fnode->numpred > 1) && (fnode->first == nd);
+}
+
+static Boolean IsExitNode(Object *proc, IRONode *fnode) {
+#line 5467
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+
+ return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom);
+}
+
+static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) {
+ UInt16 i;
+
+#line 5479
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+
+ for (i = 0; i < fnode->numpred; i++) {
+ if (FunctionNodeTable(proc)[fnode->pred[i]]->x3C)
+ return 1;
+ }
+
+ return 0;
+}
+
+static Boolean AllPredecessorsHaveBeenVisited(Object *proc, IRONode *fnode) {
+ UInt16 i;
+
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+
+ for (i = 0; i < fnode->numpred; i++) {
+ if (!FunctionNodeTable(proc)[fnode->pred[i]]->x3C)
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct EvalProcActionParams {
+ Object *proc;
+ IRONode *fnode;
+ PartialTransferFunction *ptf;
+} EvalProcActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalProcAction2(PointsToEntry *pte, void *refcon) {
+ EvalProcActionParams *params;
+ LocationSet *dst;
+ PAMemoryBlock *block;
+ LocationSetSet *set;
+ IRONode *node;
+
+#line 5525
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5530
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+
+ dst = PointsToEntry_loc(pte);
+
+#line 5535
+ IRO_ASSERT(dst != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(dst));
+
+ block = LocationSet_block(dst);
+
+ if (block && (LocationSet_sub_48AF30(dst) || PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM)) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ LocationSetSet_AddSet(set, PointsToEntry_locs(pte));
+
+ for (node = FunctionFirstNode(params->proc); node; node = node->nextnode) {
+ if (node->x3C && node != params->fnode && IsExitNode(params->proc, node)) {
+ if (node->last->pointsToFunction)
+ Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, node->last->pointsToFunction, 0, NULL);
+ }
+ }
+
+ Assign(params->ptf, dst, set, params->proc, NULL, NULL);
+
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct AssignEachInPointsToFunctionActionParams {
+ Object *proc;
+ IROLinear *nd;
+ IRONode *fnode;
+ PartialTransferFunction *ptf;
+ Boolean x10;
+} AssignEachInPointsToFunctionActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void AssignEachInPointsToFunctionAction(PointsToEntry *pte, void *refcon) {
+ AssignEachInPointsToFunctionActionParams *params;
+ LocationSet *dst;
+ LocationSetSet *srcs;
+
+#line 5577
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5582
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->nd != NULL);
+ IRO_ASSERT(params->fnode != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+
+ dst = PointsToEntry_loc(pte);
+
+ srcs = LocationSetSet_New();
+ LocationSetSet_Init(srcs);
+ LocationSetSet_AddSet(srcs, PointsToEntry_locs(pte));
+ params->x10 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode);
+ LocationSetSet_Term(srcs);
+ LocationSetSet_Delete(srcs);
+}
+
+static void AssignEachInPointsToFunction(PointsToFunction *pointsTo, void *refcon) {
+ AssignEachInPointsToFunctionActionParams *params;
+ PointsToFunction *pointsToFunc;
+
+#line 5602
+ IRO_ASSERT(pointsTo != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 5607
+ IRO_ASSERT(params->nd != NULL);
+
+ pointsToFunc = PointsToFunction_New();
+ if (params->nd->pointsToFunction)
+ PointsToFunction_Copy(pointsToFunc, params->nd->pointsToFunction);
+ else
+ PointsToFunction_Init(pointsToFunc);
+
+ if (PointsToFunction_FindFirst(pointsToFunc)) {
+ PointsToFunction_ForEach(pointsTo, AssignEachInPointsToFunctionAction, params);
+ } else {
+ if (!params->nd->pointsToFunction)
+ params->nd->pointsToFunction = PointsToFunction_New();
+ else
+ PointsToFunction_Term(params->nd->pointsToFunction);
+
+ PointsToFunction_Copy(params->nd->pointsToFunction, pointsTo);
+ params->x10 = 1;
+ }
+
+ if (params->x10) {
+ if (params->nd->pointsToFunction)
+ params->x10 = !PointsToFunctions_Equal(pointsToFunc, params->nd->pointsToFunction);
+ else
+ params->x10 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
+ }
+
+ PointsToFunction_Term(pointsToFunc);
+ PointsToFunction_Delete(pointsToFunc);
+}
+
+static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj) {
+ ObjectList *list;
+
+#line 5643
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(proc != &stUnknown);
+ IRO_ASSERT(obj != NULL);
+
+ if (obj->datatype == DLOCAL) {
+ for (list = FunctionArguments(proc); list; list = list->next) {
+ if (obj == list->object)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj) {
+ ObjectList *list;
+
+#line 5661
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(proc != &stUnknown);
+ IRO_ASSERT(obj != NULL);
+
+ if (obj->datatype == DLOCAL && proc == cscope_currentfunc) {
+ for (list = arguments; list; list = list->next) {
+ if (obj == list->object)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void AddLocalVarsAddressedByExceptionUses(Object *var) {
+#line 5699
+ IRO_ASSERT(var != NULL);
+ IRO_ASSERT(stExceptionFNode != NULL);
+ IRO_ASSERT(stExceptionFNode->addressed != NULL);
+
+ if (var->datatype == DLOCAL)
+ ObjectSet_sub_4867D0(stExceptionFNode->addressed, var);
+}
+
+static Boolean LinearNodeIsInFlowgraphNode(IROLinear *nd, IRONode *fnode) {
+ IROLinear *first;
+ IROLinear *last;
+ IROLinear *scan;
+
+ if (fnode && (first = fnode->first) && (last = fnode->last)) {
+ for (scan = first; scan && scan != last->next; scan = scan->next) {
+ if (scan == nd)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+static struct {
+ Object *proc;
+ IRONode *fnode;
+ ParamMappingFunction *map;
+ PartialTransferFunction *ptf;
+ PointsToFunction *pointsToFunc;
+ Boolean *changed;
+ Boolean x18;
+ Boolean x19;
+} stEvalProcActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void EvalProcAction(IROLinear *Int, Boolean flag) {
+ Boolean *changed;
+ Boolean result;
+ Object *proc;
+ PartialTransferFunction *ptf;
+ Boolean x18;
+ Boolean x19;
+ IRONode *fnode;
+ PointsToFunction *pointsToFunc;
+ ParamMappingFunction *map;
+ Object *obj;
+ AssignEachInPointsToFunctionActionParams params;
+
+ static int userBreakCounter;
+
+ if (!flag && !Int->x1E) {
+#line 5748
+ IRO_ASSERT(Int != NULL);
+ IRO_ASSERT(stEvalProcActionParams.changed != NULL);
+
+ proc = stEvalProcActionParams.proc;
+ fnode = stEvalProcActionParams.fnode;
+ map = stEvalProcActionParams.map;
+ ptf = stEvalProcActionParams.ptf;
+ pointsToFunc = stEvalProcActionParams.pointsToFunc;
+ changed = stEvalProcActionParams.changed;
+ x18 = stEvalProcActionParams.x18;
+ x19 = stEvalProcActionParams.x19;
+
+#line 5760
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(fnode != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ if (++userBreakCounter > 40) {
+ IRO_CheckForUserBreak();
+ userBreakCounter = 0;
+ }
+
+ result = 0;
+
+ if (x19 && Int->pointsToFunction) {
+ PointsToFunction_Term(Int->pointsToFunction);
+ PointsToFunction_Delete(Int->pointsToFunction);
+ Int->pointsToFunction = NULL;
+ }
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.nd = Int;
+ params.fnode = fnode;
+ params.ptf = ptf;
+ params.x10 = 0;
+
+ if (x18) {
+ PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf);
+ if (fnode == FunctionFirstNode(proc) && initial) {
+ AssignEachInPointsToFunction(initial, &params);
+ result |= params.x10;
+ }
+ result |= EvalMeet(proc, fnode, Int, ptf);
+ pointsToFunc = Int->pointsToFunction;
+ x18 = 0;
+ } else if (!Int->pointsToFunction) {
+ if (pointsToFunc)
+ AssignEachInPointsToFunction(pointsToFunc, &params);
+ result |= params.x10;
+ pointsToFunc = Int->pointsToFunction;
+ }
+
+ if (IRO_IsAssignment(Int)) {
+ if (Int->flags & IROLF_4000)
+ longjmp(stAbortPointerAnalysis, 1);
+ result |= EvalAssign(proc, Int, fnode, map, ptf);
+ pointsToFunc = Int->pointsToFunction;
+ } else if (Int->type == IROLinearReturn) {
+ result |= EvalReturn(proc, Int, fnode, map, ptf);
+ pointsToFunc = Int->pointsToFunction;
+ } else if (Int->type == IROLinearFunccall) {
+ if (Int->flags & IROLF_4000)
+ longjmp(stAbortPointerAnalysis, 1);
+ if (Int->stmt && IRO_FunctionCallMightThrowException(Int)) {
+ stExceptionFNode = fnode;
+ IRO_WalkExcActions(Int->stmt->dobjstack, AddLocalVarsAddressedByExceptionUses);
+ }
+ result |= EvalCall(proc, fnode, Int, map, ptf);
+ pointsToFunc = Int->pointsToFunction;
+ } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT && (!(Int->flags & IROLF_Assigned) || (Int->flags & IROLF_Used))) {
+ result |= EvalExpr(NULL, proc, Int, &stCallingContextStack, map, ptf);
+ } else if (Int->type == IROLinearOperand && !(Int->flags & IROLF_Ind) && Int->u.node->type == EOBJREF && (obj = Int->u.node->data.objref) && obj->datatype == DLOCAL) {
+ ObjectSet_sub_4867D0(fnode->addressed, obj);
+ } else if (Int->type == IROLinearAsm) {
+ IAEffects effects;
+ int i;
+ CodeGen_GetAsmEffects(Int->u.asm_stmt, &effects);
+ for (i = 0; i < effects.numoperands; i++) {
+ obj = effects.operands[i].object;
+ if (obj && obj->datatype == DLOCAL && effects.operands[i].type == IAEffect_3) {
+ ObjectSet_sub_4867D0(fnode->addressed, obj);
+ }
+ }
+ }
+
+ if (result && Int != fnode->last && fnode->last->pointsToFunction) {
+ PointsToFunction_Term(fnode->last->pointsToFunction);
+ PointsToFunction_Delete(fnode->last->pointsToFunction);
+ fnode->last->pointsToFunction = NULL;
+ }
+
+ *changed |= result;
+ x19 |= result;
+
+ stEvalProcActionParams.pointsToFunc = pointsToFunc;
+ stEvalProcActionParams.x18 = x18;
+ stEvalProcActionParams.x19 = x19;
+
+ Int->x1E = 1;
+
+ if (Int->type != IROLinearReturn) {
+ IROLinear *father = IRO_LocateFather(Int);
+ if (father && father->type == IROLinearReturn) {
+ if (LinearNodeIsInFlowgraphNode(father, fnode))
+ EvalProcAction(father, 0);
+ else
+ longjmp(stAbortPointerAnalysis, 1);
+ }
+ }
+ }
+}
+
+static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) {
+ IRONode *fnode;
+ IRONode *pred;
+ IROLinear *nd;
+ UInt32 passCount;
+ Boolean changed;
+ UInt16 i;
+ AssignEachInPointsToFunctionActionParams assignParams;
+ EvalProcActionParams params;
+
+#line 5964
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode)
+ fnode->x3C = 0;
+
+ passCount = 0;
+ do {
+ clock();
+ changed = 0;
+ for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
+ if (fnode->last && ((fnode->numpred == 0) || SomePredecessorHasBeenVisited(proc, fnode))) {
+ clock();
+ if (!fnode->addressed) {
+ fnode->addressed = ObjectSet_New();
+ ObjectSet_Init(fnode->addressed);
+ }
+
+ for (i = 0; i < fnode->numpred; i++) {
+ pred = FunctionNodeTable(proc)[fnode->pred[i]];
+ if (pred->addressed)
+ ObjectSet_sub_48C590(fnode->addressed, pred->addressed);
+ }
+
+ memset(&stEvalProcActionParams, 0, sizeof(stEvalProcActionParams));
+ stEvalProcActionParams.proc = proc;
+ stEvalProcActionParams.fnode = fnode;
+ stEvalProcActionParams.map = map;
+ stEvalProcActionParams.ptf = ptf;
+ stEvalProcActionParams.pointsToFunc = NULL;
+ stEvalProcActionParams.changed = &changed;
+ stEvalProcActionParams.x18 = 1;
+ stEvalProcActionParams.x19 = 0;
+
+ for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next)
+ nd->x1E = 0;
+ IRO_WalkInts(fnode->first, fnode->last, EvalProcAction);
+
+ if (stEvalProcActionParams.x18 || !fnode->last->pointsToFunction) {
+ memset(&assignParams, 0, sizeof(assignParams));
+ assignParams.proc = proc;
+ assignParams.nd = fnode->last;
+ assignParams.fnode = fnode;
+ assignParams.ptf = ptf;
+ assignParams.x10 = 0;
+ if (stEvalProcActionParams.x18) {
+ PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf);
+ if (fnode == FunctionFirstNode(proc) && initial) {
+ AssignEachInPointsToFunction(initial, &assignParams);
+ changed |= assignParams.x10;
+ }
+ changed |= EvalMeet(proc, fnode, fnode->last, ptf);
+ stEvalProcActionParams.x18 = 0;
+ } else {
+ if (stEvalProcActionParams.pointsToFunc)
+ AssignEachInPointsToFunction(stEvalProcActionParams.pointsToFunc, &assignParams);
+ changed |= assignParams.x10;
+ }
+ }
+
+ fnode->x3C = 1;
+ clock();
+ }
+ }
+
+ clock();
+ if (++passCount > 32) {
+#line 6072
+ CError_FATAL();
+ }
+ } while (changed);
+
+ if (passCount > stMaxPassCount)
+ stMaxPassCount = passCount;
+
+ PartialTransferFunction_sub_48A610(ptf, 1);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptf = ptf;
+ for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
+ if (fnode->x3C && IsExitNode(proc, fnode) && fnode->last->pointsToFunction) {
+ params.fnode = fnode;
+ PointsToFunction_ForEach(fnode->last->pointsToFunction, EvalProcAction2, &params);
+ }
+ }
+}
+
+static void PointerAnalysis_Init(void) {
+ stCallingContextStack = Stack_New();
+ Stack_Init(stCallingContextStack);
+
+ stUnknownPTF = PartialTransferFunction_New();
+ PartialTransferFunction_Init(stUnknownPTF, NULL, NULL);
+
+ stExtParamSet = AllocsExtParamSet_sub_4876C0();
+ InitsExtParamSet_sub_4876A0(stExtParamSet);
+
+ stPTFList = PTFList_New();
+ PTFList_Init(stPTFList);
+}
+
+static void CleanseLocationSet(LocationSet *loc, void *refcon) {
+ PAMemoryBlock *block;
+ PALocalVar *local;
+
+#line 6161
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(refcon == NULL);
+
+ if (
+ !LocationSet_IsUnknown(loc) &&
+ (block = LocationSet_block(loc)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
+ (local = PAMemoryBlock_thing(block))
+ ) {
+ PALocalVar_SetSth_sub_4847C0(local, NULL);
+ }
+}
+
+static void CleansePointsToEntry(PointsToEntry *pte, void *refcon) {
+#line 6177
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon == NULL);
+
+ CleanseLocationSet(PointsToEntry_loc(pte), NULL);
+ LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL);
+}
+
+static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) {
+#line 6187
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(refcon == NULL);
+
+ if (ptf != stUnknownPTF) {
+ PointsToFunction_ForEach(PartialTransferFunction_initialPointsToFn(ptf), CleansePointsToEntry, NULL);
+ PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(ptf), CleansePointsToEntry, NULL);
+ }
+}
+
+static void PointerAnalysis_TermAction3(ExtendedParam *ep) {
+ ExtendedParam_Term(ep);
+ ExtendedParam_Delete(ep);
+}
+
+static void PointerAnalysis_TermAction2(Object *obj, void *refcon) {
+ ObjectSet *objSet;
+ Object *proc;
+ ObjectList *list;
+
+ objSet = refcon;
+
+ if (!ObjectIsAnExtendedParamCandidate(obj)) {
+ if (
+ obj->datatype == DLOCAL &&
+ obj->u.var.info &&
+ (proc = obj->u.var.info->func) &&
+ ObjectIsAFunction(proc) &&
+ proc->u.func.argList
+ ) {
+ for (list = proc->u.func.argList; list; list = list->next) {
+ if (obj == list->object)
+ break;
+ }
+
+ if (!list)
+ ObjectSet_sub_4867D0(objSet, obj);
+ } else {
+ ObjectSet_sub_4867D0(objSet, obj);
+ }
+ }
+}
+
+static void PointerAnalysis_TermAction1(ExtendedParam *ep, void *refcon) {
+ ObjectSet *objSet;
+ ObjectSet *epObjSet;
+ Object *obj;
+
+ objSet = ObjectSet_New();
+ ObjectSet_Init(objSet);
+
+ epObjSet = ExtendedParam_objectSet(ep);
+ obj = NULL;
+ ObjectSet_ForEach(epObjSet, FindGlobalObjectAction, &obj);
+ if (obj) {
+ ObjectSet_ForEach(epObjSet, PointerAnalysis_TermAction2, objSet);
+ if (ObjectSet_FindFirst(objSet))
+ EP_sub_48C850(ep, objSet);
+ }
+
+ ObjectSet_Term(objSet);
+ ObjectSet_Delete(objSet);
+}
+
+static void PointerAnalysis_Term(void) {
+ if (stExtParamSet) {
+ MaybeWalkExtParamSet_sub_48CBE0(stExtParamSet, PointerAnalysis_TermAction1, NULL);
+ TermsExtParamSet_sub_48CB00(stExtParamSet);
+ FreesExtParamSet_sub_48CAE0(stExtParamSet);
+ stExtParamSet = NULL;
+ }
+
+ if (stPTFList) {
+ PTFList_ForEach(stPTFList, PointerAnalysis_TermAction4, NULL);
+ PTFList_Term(stPTFList);
+ PTFList_Delete(stPTFList);
+ stPTFList = NULL;
+ }
+
+ PartialTransferFunction_Term(stUnknownPTF);
+ PartialTransferFunction_Delete(stUnknownPTF);
+ stUnknownPTF = NULL;
+
+ Stack_Term(&stCallingContextStack);
+ Stack_Delete(stCallingContextStack);
+ stCallingContextStack = NULL;
+}
+
+static void InvalidatePointsToFunctions(Object *proc) {
+ IRONode *fnode;
+ IROLinear *nd;
+
+#line 6302
+ IRO_ASSERT(proc != NULL);
+
+ for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
+ if (fnode->last) {
+ if (fnode->addressed) {
+ ObjectSet_Term(fnode->addressed);
+ ObjectSet_Delete(fnode->addressed);
+ fnode->addressed = NULL;
+ }
+
+ for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) {
+ if (nd->pointsToFunction) {
+ PointsToFunction_Term(nd->pointsToFunction);
+ PointsToFunction_Delete(nd->pointsToFunction);
+ nd->pointsToFunction = NULL;
+ }
+ }
+ }
+ }
+}
+
+static void InitialSetup(void) {
+}
+
+static void PointerAnalysis_HeapErrorProc(void) {
+ longjmp(stAbortPointerAnalysis, 2);
+}
+
+void PointerAnalysis_Setup(void) {
+ IRO_InitializeAllocator();
+ stExtendedParamNum = 0;
+ stParamObjs = NULL;
+ stMaxPassCount = 0;
+}
+
+void PointerAnalysis_Cleanup(void) {
+ ObjectList *list;
+ ObjectList *next;
+
+ for (list = stParamObjs; list; list = next) {
+ IRO_free(list->object);
+ next = list->next;
+ IRO_free(list);
+ }
+ stParamObjs = NULL;
+ IRO_TerminateAllocator();
+}
+
+void IRO_AnalyzePointers(Object *function) {
+ EvalCallActionParams params;
+ IROLinear nd;
+ IRONode fnode;
+ int code;
+ volatile heaperror_t saveheaperror;
+
+#line 6393
+ IRO_ASSERT(function != NULL);
+
+ PointerAnalysis_Init();
+
+ memset(&params, 0, sizeof(params));
+ memset(&nd, 0, sizeof(nd));
+ nd.type = IROLinearFunccall;
+ memset(&fnode, 0, sizeof(fnode));
+ params.proc = &stUnknown;
+ params.fnode = &fnode;
+ params.nd = &nd;
+ params.ptf = stUnknownPTF;
+ params.map = NULL;
+ params.x18 = 0;
+ params.x19 = 0;
+ params.x1A = 1;
+
+ stCurrentProc = FindMainEntryPoint(function);
+
+ if ((code = setjmp(stAbortPointerAnalysis)) == 0) {
+ saveheaperror = getheaperror();
+ setheaperror(PointerAnalysis_HeapErrorProc);
+ InitialSetup();
+ EvalCallAction(stCurrentProc, &params);
+ PointerAnalysis_Term();
+ stCurrentProc = NULL;
+ setheaperror(saveheaperror);
+ } else {
+ setheaperror(saveheaperror);
+ InvalidatePointsToFunctions(stCurrentProc);
+ PointerAnalysis_Term();
+ stCurrentProc = NULL;
+ if (code == 2 && saveheaperror)
+ saveheaperror();
+ }
+}
+
+static void RemoveRestrictedExtendedParamsAction(LocationSet *ls, void *refcon) {
+ LocationSetSet *locs;
+ PAMemoryBlock *block;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+ Object *obj;
+
+ locs = refcon;
+
+ if (
+ !LocationSet_IsUnknown(ls) &&
+ (block = LocationSet_block(ls)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
+ (ep = PAMemoryBlock_thing(block))
+ ) {
+ objSet = ExtendedParam_objectSet(ep);
+ if (
+ ObjectSet_Count(objSet) == 1 &&
+ (obj = ObjectSet_FindFirst(objSet)) &&
+ ObjectIsRestrictQualified(obj)
+ ) {
+ LocationSetSet_Add(locs, ls);
+ }
+ }
+}
+
+static void RemoveRestrictedExtendedParams(LocationSetSet *locs) {
+ LocationSetSet *set;
+
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ LocationSetSet_ForEach(locs, RemoveRestrictedExtendedParamsAction, set);
+ LocationSetSet_sub_488700(locs, set);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+}
+
+Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2) {
+ LocationSetSet *lss1;
+ LocationSetSet *lss2;
+ PointsToFunction *pointsTo1;
+ PointsToFunction *pointsTo2;
+ PointsToFunction *savePointsTo1;
+ PointsToFunction *savePointsTo2;
+ FindAliasingParams params;
+
+ pointsTo1 = nd1->pointsToFunction;
+ pointsTo2 = nd2->pointsToFunction;
+ if (!pointsTo1)
+ pointsTo1 = pointsTo2;
+ if (!pointsTo2)
+ pointsTo2 = pointsTo1;
+
+ if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype))
+ return 0;
+ if (!pointsTo1 || !pointsTo2)
+ return 1;
+
+ lss1 = LocationSetSet_New();
+ LocationSetSet_Init(lss1);
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+
+ savePointsTo1 = nd1->pointsToFunction;
+ nd1->pointsToFunction = pointsTo1;
+ EvalExpr(lss1, proc, nd1, NULL, NULL, NULL);
+ nd1->pointsToFunction = savePointsTo1;
+
+ savePointsTo2 = nd2->pointsToFunction;
+ nd2->pointsToFunction = pointsTo2;
+ EvalExpr(lss2, proc, nd2, NULL, NULL, NULL);
+ nd2->pointsToFunction = savePointsTo2;
+
+ memset(&params, 0, sizeof(params));
+ params.x8 = 0;
+ params.x0 = lss2;
+ LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ params.x0 = lss1;
+ LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ RemoveRestrictedExtendedParams(lss1);
+ RemoveRestrictedExtendedParams(lss2);
+ ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1);
+ ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2);
+
+ params.x0 = lss2;
+ LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ params.x0 = lss1;
+ LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
+ }
+ }
+ }
+
+ LocationSetSet_Term(lss1);
+ LocationSetSet_Delete(lss1);
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+
+ return params.x8;
+}
+
+Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2) {
+ LocationSetSet *lss1;
+ LocationSetSet *lss2;
+ PointsToFunction *pointsTo1;
+ PointsToFunction *pointsTo2;
+ PointsToFunction *savePointsTo1;
+ PointsToFunction *savePointsTo2;
+ FindAliasingParams params;
+
+ pointsTo1 = nd1->pointsTo;
+ pointsTo2 = nd2->pointsTo;
+ if (!pointsTo1)
+ pointsTo1 = pointsTo2;
+ if (!pointsTo2)
+ pointsTo2 = pointsTo1;
+
+ if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype))
+ return 0;
+ if (!pointsTo1 || !pointsTo2)
+ return 1;
+
+ lss1 = LocationSetSet_New();
+ LocationSetSet_Init(lss1);
+ lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+
+ savePointsTo1 = nd1->pointsTo;
+ nd1->pointsTo = pointsTo1;
+ EvalENodeExpr(lss1, proc, nd1, NULL, NULL, NULL);
+ nd1->pointsTo = savePointsTo1;
+
+ savePointsTo2 = nd2->pointsTo;
+ nd2->pointsTo = pointsTo2;
+ EvalENodeExpr(lss2, proc, nd2, NULL, NULL, NULL);
+ nd2->pointsTo = savePointsTo2;
+
+ memset(&params, 0, sizeof(params));
+ params.x8 = 0;
+ params.x0 = lss2;
+ LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ params.x0 = lss1;
+ LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ RemoveRestrictedExtendedParams(lss1);
+ RemoveRestrictedExtendedParams(lss2);
+ ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1);
+ ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2);
+
+ params.x0 = lss2;
+ LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
+
+ if (!params.x8) {
+ params.x0 = lss1;
+ LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
+ }
+ }
+ }
+
+ LocationSetSet_Term(lss1);
+ LocationSetSet_Delete(lss1);
+ LocationSetSet_Term(lss2);
+ LocationSetSet_Delete(lss2);
+
+ return params.x8;
+}
+
+Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd) {
+ LocationSetSet *lss;
+ LocationSet *loc;
+ Boolean result;
+
+ if (!nd->pointsToFunction)
+ return 0;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ EvalExpr(lss, proc, nd, NULL, NULL, NULL);
+
+ result =
+ (LocationSetSet_Count(lss) == 1) &&
+ (loc = LocationSetSet_FindFirst(lss)) &&
+ LocationSetRepresentsSingleLocation(loc, NULL, NULL);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+
+ return result;
+}
+
+Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd) {
+ LocationSetSet *lss;
+ LocationSet *loc;
+ Boolean result;
+
+ if (!nd->pointsTo)
+ return 0;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ EvalENodeExpr(lss, proc, nd, NULL, NULL, NULL);
+
+ result =
+ (LocationSetSet_Count(lss) == 1) &&
+ (loc = LocationSetSet_FindFirst(lss)) &&
+ LocationSetRepresentsSingleLocation(loc, NULL, NULL);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+
+ return result;
+}
+
+Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo) {
+ LocationSetSet *lss;
+ LocationSet *loc;
+ Boolean result;
+
+ if (!pointsTo)
+ return 0;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ EvalVariable(lss, proc, var, pointsTo, NULL, NULL, NULL);
+
+ result =
+ (LocationSetSet_Count(lss) == 1) &&
+ (loc = LocationSetSet_FindFirst(lss)) &&
+ LocationSetRepresentsSingleLocation(loc, NULL, NULL);
+
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+
+ return result;
+}
+
+static void FindGlobalObjectAction(Object *object, void *refcon) {
+ if (ObjectIsAnExtendedParamCandidate(object)) {
+ Object **ptr = refcon;
+ *ptr = object;
+ }
+}
+
+static void GetDefiniteObjectOfExtendedParamLoc(LocationSet *loc, Object **resultObj, CInt64 *resultField) {
+ Object *obj;
+ CInt64 field;
+ PAMemoryBlock *block;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+ LocationSetSet *locs;
+ LocationSet *tmp;
+ PALocalVar *local;
+
+#line 6763
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(resultObj != NULL);
+ IRO_ASSERT(resultField != NULL);
+
+ obj = NULL;
+ field = LocationSet_field(loc);
+ block = LocationSet_block(loc);
+
+ if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) {
+#line 6777
+ IRO_ASSERT(obj == NULL);
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ }
+ }
+
+ if (!obj) {
+ locs = LocationSetSet_New();
+ LocationSetSet_Init(locs);
+ GetActualLocsOfExtendedParam(locs, loc, NULL, &stCallingContextStack, NULL, 0);
+
+ if (
+ LocationSetSet_Count(locs) == 1 &&
+ (tmp = LocationSetSet_FindFirst(locs)) &&
+ !LocationSet_IsUnknown(tmp))
+ {
+ field = CInt64_Add(field, LocationSet_field(tmp));
+ if (
+ (block = LocationSet_block(tmp)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
+ (ep = PAMemoryBlock_thing(block)) &&
+ (objSet = ExtendedParam_objectSet(ep))
+ )
+ {
+#line 6801
+ IRO_ASSERT(obj == NULL);
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ } else if (
+ (block = LocationSet_block(tmp)) &&
+ PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
+ (local = PAMemoryBlock_thing(block))
+ )
+ {
+ obj = GetLocalObject(local, &stUnknown, 0);
+ }
+ }
+
+ LocationSetSet_Term(locs);
+ LocationSetSet_Delete(locs);
+ }
+
+ *resultObj = obj;
+ *resultField = field;
+}
+
+static void CreateExpressionForLocationSet(LocationSet *loc, IROList *list, Type *rtype, Object *proc) {
+ CInt64 field;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+ void *thing;
+ IROLinear *nd;
+ Object *obj;
+
+#line 6833
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+ IRO_ASSERT(LocationSet_stride(loc) == 0);
+ IRO_ASSERT(list != NULL);
+ IRO_ASSERT(rtype != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ field = LocationSet_field(loc);
+ block = LocationSet_block(loc);
+ kind = PAMemoryBlock_kind(block);
+ thing = PAMemoryBlock_thing(block);
+ nd = NULL;
+
+ switch (kind) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field);
+ if (obj) {
+ nd = IRO_NewLinear(IROLinearOperand);
+ nd->u.node = create_objectrefnode(obj);
+ nd->rtype = rtype;
+ nd->index = ++IRO_NumLinear;
+ IRO_AddToList(nd, list);
+ }
+ break;
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ obj = GetLocalObject(thing, proc, 0);
+ if (obj) {
+ if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj)
+ obj = obj->u.var.realObj;
+ nd = IRO_NewLinear(IROLinearOperand);
+ nd->u.node = create_objectrefnode(obj);
+ nd->rtype = rtype;
+ nd->index = ++IRO_NumLinear;
+ IRO_AddToList(nd, list);
+ }
+ break;
+ case PAMEMORYBLOCKKIND_INT:
+ if (IS_TYPE_INT(rtype)) {
+ nd = IRO_NewIntConst(*((CInt64 *) thing), rtype);
+ IRO_AddToList(nd, list);
+ }
+ break;
+ case PAMEMORYBLOCKKIND_6:
+ break;
+ default:
+#line 6894
+ CError_FATAL();
+ }
+
+ if (nd && !CInt64_IsZero(&field)) {
+ IROLinear *nd2;
+ IROLinear *nd3;
+
+ nd2 = IRO_NewIntConst(field, TYPE(&stunsignedlong));
+ IRO_AddToList(nd2, list);
+
+ nd3 = IRO_NewLinear(IROLinearOp2Arg);
+ nd3->nodetype = EADD;
+ nd3->index = ++IRO_NumLinear;
+ nd3->rtype = rtype;
+ nd3->u.diadic.left = nd;
+ nd3->u.diadic.right = nd2;
+ IRO_AddToList(nd3, list);
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct LookupLinearExprActionParams {
+ Object *proc;
+ Type *indirectType;
+ IROListNode **list;
+} LookupLinearExprActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void LookupLinearExprAction(LocationSet *loc, void *refcon) {
+ LookupLinearExprActionParams *params;
+ IROListNode *list;
+
+#line 6926
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 6931
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->indirectType != NULL);
+ IRO_ASSERT(params->list != NULL);
+
+ list = *params->list = IRO_malloc(sizeof(IROListNode));
+ IRO_InitList(&list->list);
+ list->nextList = NULL;
+
+ if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL))
+ CreateExpressionForLocationSet(loc, &list->list, params->indirectType, params->proc);
+
+ params->list = &list->nextList;
+}
+
+void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list) {
+ LocationSetSet *set;
+ LookupLinearExprActionParams params;
+
+#line 6957
+ IRO_ASSERT(indirect != NULL);
+
+ if (indirect->pointsToFunction) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ EvalExpr(set, proc, indirect, NULL, NULL, NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.indirectType = indirect->rtype;
+ params.list = list;
+
+ LocationSetSet_ForEach(set, LookupLinearExprAction, &params);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+static void CreateENodeForLocationSet(LocationSet *loc, ENode **resultNode, Type *rtype, Object *proc) {
+ CInt64 field;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+ void *thing;
+ ENode *nd;
+ Object *obj;
+
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+ IRO_ASSERT(LocationSet_stride(loc) == 0);
+ IRO_ASSERT(resultNode != NULL);
+ IRO_ASSERT(rtype != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ field = LocationSet_field(loc);
+ block = LocationSet_block(loc);
+ kind = PAMemoryBlock_kind(block);
+ thing = PAMemoryBlock_thing(block);
+ nd = NULL;
+
+ switch (kind) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field);
+ if (obj) {
+ nd = create_objectrefnode(obj);
+ nd->rtype = rtype;
+ }
+ break;
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ obj = GetLocalObject(thing, proc, 0);
+ if (obj) {
+ if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj)
+ obj = obj->u.var.realObj;
+ nd = create_objectrefnode(obj);
+ nd->rtype = rtype;
+ }
+ break;
+ case PAMEMORYBLOCKKIND_INT:
+ if (IS_TYPE_INT(rtype)) {
+ nd = IRO_NewENode(EINTCONST);
+ nd->data.intval = *((CInt64 *) thing);
+ nd->rtype = rtype;
+ }
+ break;
+ case PAMEMORYBLOCKKIND_6:
+ break;
+ default:
+#line 7040
+ CError_FATAL();
+ }
+
+ if (nd && !CInt64_IsZero(&field)) {
+ ENode *nd2;
+ ENode *nd3;
+
+ nd2 = IRO_NewENode(EINTCONST);
+ nd2->data.intval = field;
+ nd2->rtype = TYPE(&stunsignedlong);
+
+ nd3 = IRO_NewENode(EADD);
+ nd3->data.diadic.left = nd;
+ nd3->data.diadic.right = nd2;
+ nd3->rtype = rtype;
+
+ *resultNode = nd3;
+ } else {
+ *resultNode = nd;
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct LookupENodeExprActionParams {
+ Object *proc;
+ Type *indirectType;
+ ENodeList **list;
+} LookupENodeExprActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void LookupENodeExprAction(LocationSet *loc, void *refcon) {
+ LookupENodeExprActionParams *params;
+ ENodeList *list;
+
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->indirectType != NULL);
+ IRO_ASSERT(params->list != NULL);
+
+ list = *params->list = IRO_malloc(sizeof(ENodeList));
+ list->node = NULL;
+ list->next = NULL;
+
+ if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL))
+ CreateENodeForLocationSet(loc, &list->node, params->indirectType, params->proc);
+
+ params->list = &list->next;
+}
+
+void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list) {
+ LocationSetSet *set;
+ LookupENodeExprActionParams params;
+
+ IRO_ASSERT(indirect != NULL);
+
+ if (indirect->pointsTo) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ EvalENodeExpr(set, proc, indirect, NULL, NULL, NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.indirectType = indirect->rtype;
+ params.list = list;
+
+ LocationSetSet_ForEach(set, LookupENodeExprAction, &params);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROList **list) {
+ LocationSetSet *set;
+ LookupLinearExprActionParams params;
+
+ if (pointsTo) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.indirectType = var->object->type;
+ params.list = list;
+
+ LocationSetSet_ForEach(set, LookupLinearExprAction, &params);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list) {
+ LocationSetSet *set;
+ LookupENodeExprActionParams params;
+
+ if (pointsTo) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL);
+
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.indirectType = var->object->type;
+ params.list = list;
+
+ LocationSetSet_ForEach(set, LookupENodeExprAction, &params);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct GetFunctionDepsOrKillsActionParams {
+ Object *proc;
+ PartialTransferFunction *ptf;
+ IROLinear *funccall;
+ ParamMappingFunction *map;
+ ObjectList **list;
+} GetFunctionDepsOrKillsActionParams;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void GetFunctionDepsOrKillsAction(LocationSet *ls, void *refcon) {
+ GetFunctionDepsOrKillsActionParams *params;
+ ObjectList *list;
+ PAMemoryBlock *block;
+ ExtendedParam *ep;
+ ObjectSet *objSet;
+ PALocalVar *local;
+ Object *obj;
+
+#line 7204
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 7209
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->funccall != NULL);
+ IRO_ASSERT(params->map == NULL || params->map != NULL);
+ IRO_ASSERT(params->list != NULL);
+
+ list = *params->list = IRO_malloc(sizeof(ObjectList));
+ list->object = NULL;
+ list->next = NULL;
+
+ if (!LocationSet_IsUnknown(ls) && (block = LocationSet_block(ls))) {
+ obj = NULL;
+ switch (PAMemoryBlock_kind(block)) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) {
+#line 7232
+ IRO_ASSERT(obj == NULL);
+ ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
+ }
+ break;
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ if ((local = PAMemoryBlock_thing(block))) {
+ obj = GetLocalObject(local, &stUnknown, 0);
+ if (ObjectIsAFunctionArgument(FunctionName, obj) && obj->u.var.realObj)
+ obj = obj->u.var.realObj;
+ }
+ break;
+ }
+
+ list->object = obj;
+ }
+
+ params->list = &list->next;
+}
+
+static void GetFunctionDepsOrKillsAction2(PointsToEntry *pte, void *refcon) {
+ GetFunctionDepsOrKillsActionParams *params;
+ LocationSet *loc;
+ PAMemoryBlock *block;
+ LocationSetSet *set;
+
+#line 7264
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ params = refcon;
+
+#line 7269
+ IRO_ASSERT(params->proc != NULL);
+ IRO_ASSERT(params->ptf != NULL);
+ IRO_ASSERT(params->funccall != NULL);
+ IRO_ASSERT(params->map != NULL);
+ IRO_ASSERT(params->list != NULL);
+
+ loc = PointsToEntry_loc(pte);
+
+#line 7277
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+
+ if ((block = LocationSet_block(loc)) && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
+ set = LocationSetSet_New();
+ LocationSetSet_Init(set);
+ GetActualLocsOfExtendedParam(set, loc, NULL, &stCallingContextStack, params->map, 0);
+ LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, params);
+ LocationSetSet_Term(set);
+ LocationSetSet_Delete(set);
+ }
+}
+
+static void CreateFalseContext(Object *proc, IROLinear *funccall, PartialTransferFunction **resultPTF, ParamMappingFunction **resultMap) {
+ IROLinear myFunccall;
+ Boolean needVisit;
+ ParamMappingFunction *map;
+ PartialTransferFunction *ptf;
+ StackElement *stackElement;
+ ParamMappingFunction *map2;
+ PartialTransferFunction *ptf2;
+ StackElement *stackElement2;
+
+ PointerAnalysis_Init();
+ memset(&myFunccall, 0, sizeof(myFunccall));
+ myFunccall.type = IROLinearFunccall;
+
+ map = ParamMappingFunction_New();
+ ParamMappingFunction_Init(map);
+ RecordActuals(&myFunccall, FunctionName, map);
+
+ needVisit = 0;
+ ptf = GetPTF(map, FunctionName, &myFunccall, stUnknownPTF, &needVisit);
+
+ stackElement = StackElement_New();
+ StackElement_Init(stackElement, FunctionName, ptf, map, &myFunccall);
+ Stack_sub_48A660(&stCallingContextStack, stackElement);
+ StackElement_Term(stackElement);
+ StackElement_Delete(stackElement);
+
+ map2 = ParamMappingFunction_New();
+ ParamMappingFunction_Init(map2);
+ RecordActuals(funccall, proc, map2);
+
+ if (FunctionName != proc) {
+ needVisit = 0;
+ ptf2 = GetPTF(map2, proc, funccall, ptf, &needVisit);
+
+ stackElement2 = StackElement_New();
+ StackElement_Init(stackElement2, proc, ptf2, map2, funccall);
+ Stack_sub_48A660(&stCallingContextStack, stackElement2);
+ StackElement_Term(stackElement2);
+ StackElement_Delete(stackElement2);
+ } else {
+ ptf2 = stUnknownPTF;
+ }
+
+ *resultPTF = ptf2;
+ *resultMap = map2;
+}
+
+static void DestroyFalseContext(Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map) {
+ StackElement *element;
+
+ if (FunctionName != proc) {
+ element = Stack_sub_48A5B0(&stCallingContextStack);
+ StackElement_Term(element);
+ StackElement_Delete(element);
+ }
+
+ ParamMappingFunction_Term(map);
+ ParamMappingFunction_Delete(map);
+
+ element = Stack_sub_48A5B0(&stCallingContextStack);
+ map = StackElement_map(element);
+ ParamMappingFunction_Term(map);
+ ParamMappingFunction_Delete(map);
+ StackElement_Term(element);
+ StackElement_Delete(element);
+
+ PointerAnalysis_Term();
+}
+
+void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list) {
+ Boolean fail;
+ PartialTransferFunction *ptf;
+ LocationSetSet *set;
+ GetFunctionDepsOrKillsActionParams params;
+
+#line 7398
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(funccall != NULL);
+ IRO_ASSERT(funccall->type == IROLinearFunccall);
+
+ if (!ObjectIsAFunction(proc))
+ return;
+
+ fail = !proc->u.func.ptfList || !(ptf = PTFList_FindFirst(proc->u.func.ptfList));
+ if (!fail) {
+ fail = !(set = PTF_sub_48D750(ptf));
+ if (!fail) {
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptf = ptf;
+ params.funccall = funccall;
+ params.map = NULL;
+ params.list = list;
+ LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, &params);
+ }
+ }
+
+ if (fail) {
+ *list = IRO_malloc(sizeof(ObjectList));
+ (*list)->object = NULL;
+ (*list)->next = NULL;
+ }
+}
+
+void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list) {
+ Boolean fail;
+ PartialTransferFunction *ptf;
+ ParamMappingFunction *map;
+ PointsToFunction *finalPointsTo;
+ GetFunctionDepsOrKillsActionParams params;
+
+#line 7446
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(funccall != NULL);
+ IRO_ASSERT(funccall->type == IROLinearFunccall);
+
+ if (!ObjectIsAFunction(proc))
+ return;
+
+ fail = !proc->u.func.ptfList || !PTFList_FindFirst(proc->u.func.ptfList);
+ if (!fail) {
+ CreateFalseContext(proc, funccall, &ptf, &map);
+ fail = !ptf || !map || !(finalPointsTo = PartialTransferFunction_finalPointsToFn(ptf));
+ if (!fail) {
+ memset(&params, 0, sizeof(params));
+ params.proc = proc;
+ params.ptf = ptf;
+ params.funccall = funccall;
+ params.map = map;
+ params.list = list;
+ PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, &params);
+ }
+ DestroyFalseContext(proc, ptf, map);
+ }
+
+ if (fail) {
+ *list = IRO_malloc(sizeof(ObjectList));
+ (*list)->object = NULL;
+ (*list)->next = NULL;
+ }
+}
+
+void PointerAnalysis_PragmaMode(void) {
+ if (cparamblkptr->isPreprocessing) {
+ skipendofline();
+ return;
+ }
+
+ if (notendofline()) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "addr")) {
+ copts.opt_pointer_analysis_mode = 0;
+ return;
+ }
+ if (!strcmp(tkidentifier->name, "ansi")) {
+ copts.opt_pointer_analysis_mode = 1;
+ return;
+ }
+ if (!strcmp(tkidentifier->name, "type")) {
+ copts.opt_pointer_analysis_mode = 2;
+ return;
+ }
+ }
+
+ CPrep_Warning(CErrorStr105);
+ skipendofline();
+ return;
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(CErrorStr186);
+ skipendofline();
+}
+
+typedef enum CreateNewParamObjects {
+ CREATE_NEW_PARAM_OBJECTS_FALSE,
+ CREATE_NEW_PARAM_OBJECTS_TRUE
+} CreateNewParamObjects;
+
+static void ParseLocationSet(LocationSet *loc, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean arg5, int arg6, Boolean *arg7, Boolean *resultFailed) {
+ CInt64 field;
+ UInt32 stride;
+ PAMemoryBlock *block;
+ PAMemoryBlock *restriction;
+ Boolean failed;
+ Boolean flag37;
+ Boolean epFlag;
+ Boolean anotherFlag;
+ Boolean isUnknown;
+
+#line 7552
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(rtype == NULL || rtype != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE);
+ IRO_ASSERT(resultFailed != NULL);
+ IRO_ASSERT(*resultFailed == false);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc));
+
+ failed = 0;
+ isUnknown = 0;
+ anotherFlag = 0;
+ field = cint64_zero;
+ stride = 0;
+
+ tk = lex();
+ if (tk == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "__unknown")) {
+ flag37 = 0;
+ isUnknown = 1;
+ tk = lookahead();
+ if (tk == '(') {
+ lex();
+ tk = lex();
+ if (tk != TK_IDENTIFIER) {
+ CError_Error(CErrorStr107);
+ failed = 1;
+ }
+ if (!failed) {
+ PALocalVar *local;
+ local = PALocalVar_New();
+ PALocalVar_InitByName(local, tkidentifier->name);
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, local);
+
+ tk = lex();
+ if (tk != ')') {
+ CError_Error(CErrorStr115);
+ failed = 1;
+ }
+ if (!failed) {
+ rtype = NULL;
+ restriction = block;
+ }
+ }
+ } else {
+ rtype = NULL;
+ restriction = NULL;
+ }
+ } else if (arg5 && !strcmp(tkidentifier->name, "__return_value")) {
+ flag37 = 0;
+ anotherFlag = 1;
+ } else if (!strcmp(tkidentifier->name, "__unique_heap_allocation")) {
+ PAHeapBlock *hb;
+
+ flag37 = 0;
+ hb = CreateUniqueHeapAlloc_sub_486420();
+ InitUniqueHeapAlloc_sub_486410(hb, NULL);
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_HEAPBLOCK, hb);
+ } else if (!strcmp(tkidentifier->name, "__parameter_representative")) {
+ flag37 = 1;
+ tk = lex();
+
+ if (tk == '(') {
+ tk = lex();
+ if (tk != TK_INTCONST) {
+ CError_Error(CErrorStr121);
+ failed = 1;
+ }
+ if (!failed) {
+ Object *obj;
+ ObjectList *list;
+ ExtendedParam *ep;
+ obj = NULL;
+ for (list = stParamObjs; list; list = list->next) {
+ if ((obj = list->object) && (obj->u.var.uid == CInt64_GetULong(&tkintconst)))
+ break;
+ }
+ if (!list)
+ obj = NULL;
+
+ if (!obj) {
+ if (createNewParamObjects) {
+ obj = IRO_malloc(sizeof(Object));
+ memset(obj, 0, sizeof(Object));
+ obj->datatype = DLOCAL;
+ obj->extParam = NULL;
+ obj->name = CParser_GetUniqueName();
+ obj->type = TYPE(&stunsignedlong);
+ obj->qual = 0;
+ obj->u.var.info = NULL;
+ obj->u.var.uid = CInt64_GetULong(&tkintconst);
+
+ list = IRO_malloc(sizeof(ObjectList));
+ list->next = stParamObjs;
+ list->object = obj;
+ stParamObjs = list;
+
+ ep = CreateExtendedParam(NULL, NULL, obj, &epFlag);
+ } else {
+ char buf[64];
+ sprintf(buf, "__parameter_representative(%ld)", obj->u.var.uid);
+ CError_Error(CErrorStr140, buf);
+ failed = 1;
+ }
+ } else {
+ ep = obj->extParam;
+#line 7687
+ IRO_ASSERT(ep != NULL);
+ }
+
+ if (!failed) {
+ tk = lex();
+ if (tk != ')') {
+ CError_Error(CErrorStr115);
+ failed = 1;
+ }
+ }
+ if (!failed) {
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep);
+ }
+ }
+ }
+ } else {
+ Object *obj;
+ NameSpace *nspace;
+
+ obj = NULL;
+ for (nspace = cscope_current; nspace; nspace = nspace->parent) {
+ NameSpaceObjectList *chk;
+ if ((chk = CScope_GetLocalObject(nspace, tkidentifier)) && chk->object->otype == OT_OBJECT) {
+ if (notendofline()) {
+ obj = OBJECT(chk->object);
+ break;
+ }
+ }
+ }
+
+ if (!obj) {
+ ObjectList *chk;
+ for (chk = FunctionArguments(proc); chk; chk = chk->next) {
+ if (chk->object && chk->object->name && chk->object->name->name && !strcmp(tkidentifier->name, chk->object->name->name)) {
+ obj = chk->object;
+ }
+ }
+ }
+
+ if (obj) {
+ PAMemoryBlockKind kind;
+ void *thing;
+
+ if (ObjectIsAnExtendedParamCandidate(obj)) {
+ kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
+ thing = CreateExtendedParam(NULL, NULL, obj, &epFlag);
+ } else {
+ kind = PAMEMORYBLOCKKIND_LOCALVAR;
+ thing = PALocalVar_New();
+ if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj))
+ PALocalVar_InitByName(thing, obj->name->name);
+ else
+ PALocalVar_InitByObject(thing, obj);
+ }
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, kind, thing);
+ rtype = CDecl_NewPointerType(obj->type);
+ } else {
+ CError_Error(CErrorStr140, tkidentifier->name);
+ failed = 1;
+ }
+ }
+ } else if (tk == TK_INTCONST) {
+ flag37 = 0;
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &tkintconst);
+ } else if (tk == '(') {
+ ParseLocationSet(loc, rtype, proc, createNewParamObjects, arg5, 1, &anotherFlag, &failed);
+ if (!failed) {
+ tk = plex();
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ failed = 1;
+ }
+ } else {
+ CError_Error(CErrorStr121);
+ failed = 1;
+ }
+
+ if (!failed && flag37) {
+ tk = lookahead();
+ if (tk == '[') {
+ lex();
+ if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_POINTER(TPTR_TARGET(rtype))) {
+ tk = lex();
+ if (tk == ']') {
+ if ((stride = rtype->size)) {
+ CInt64 tmp;
+ CInt64_SetLong(&tmp, stride);
+ field = CInt64_Mod(field, tmp);
+ }
+ rtype = TPTR_TARGET(rtype);
+ } else {
+ CError_Error(CErrorStr125);
+ }
+ } else {
+ CError_Error(CErrorStr148);
+ }
+ } else if (tk == '.') {
+ lex();
+ if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_STRUCT(TPTR_TARGET(rtype))) {
+ if (TPTR_TARGET(rtype)->size) {
+ tk = lex();
+ if (tk == TK_IDENTIFIER) {
+ StructMember *member;
+ if ((member = ismember(TYPE_STRUCT(TPTR_TARGET(rtype)), tkidentifier))) {
+ CInt64_SetLong(&field, member->offset);
+ rtype = CDecl_NewPointerType(member->type);
+ } else {
+ CError_Error(CErrorStr150, tkidentifier);
+ }
+ } else {
+ CError_Error(CErrorStr107);
+ }
+ } else {
+ CError_Error(CErrorStr136, TPTR_TARGET(rtype), 0);
+ }
+ } else {
+ CError_Error(CErrorStr149);
+ }
+ }
+ }
+
+ if (!failed && !anotherFlag) {
+ LocationSet_Term(loc);
+ if (!isUnknown)
+ LocationSet_InitKnown(loc, block, field, stride, rtype);
+ else
+ LocationSet_InitUnknown(loc, rtype, restriction, NULL);
+ }
+
+ *arg7 = anotherFlag;
+ *resultFailed = failed;
+}
+
+static void ParseLocationSetSet(LocationSetSet *locs, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean *resultFailed) {
+ Boolean failed;
+
+#line 7892
+ IRO_ASSERT(locs != NULL);
+ IRO_ASSERT(rtype == NULL || rtype != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE);
+ IRO_ASSERT(resultFailed != NULL);
+ IRO_ASSERT(*resultFailed == false);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc));
+
+ failed = 0;
+
+ tk = lex();
+ if (tk != '(') {
+ CError_Error(CErrorStr114);
+ failed = 1;
+ }
+
+ if (!failed) {
+ Boolean anotherFlag;
+
+ LocationSet *ls;
+ ls = LocationSet_New();
+ LocationSet_InitUnknown(ls, NULL, NULL, NULL);
+
+ tk = lookahead();
+ while (!failed && tk != ')') {
+ ParseLocationSet(ls, rtype, proc, createNewParamObjects, 0, 0, &anotherFlag, &failed);
+ if (!failed)
+ LocationSetSet_Add(locs, ls);
+
+ if (!failed) {
+ tk = lookahead();
+ if (tk == ',') {
+ lex();
+ tk = lookahead();
+ } else if (tk != ')') {
+ lex();
+ CError_Error(CErrorStr121);
+ failed = 1;
+ }
+ }
+ }
+
+ if (!failed)
+ lex();
+
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ }
+
+ *resultFailed = failed;
+}
+
+static Object *GetFunctionObjectFromDeclInfo(DeclInfo *di) {
+ Object *proc;
+
+#line 7953
+ IRO_ASSERT(di != NULL);
+
+ if (di->storageclass != TK_TYPEDEF && IS_TYPE_FUNC(di->thetype)) {
+ Boolean flag;
+ proc = CDecl_GetFunctionObject(di, NULL, &flag, 1);
+ if (flag)
+ di->fileoffsetinfo.is_inline = 1;
+ } else {
+ proc = NULL;
+ }
+
+ return proc;
+}
+
+void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di) {
+ Object *proc;
+ Boolean failed;
+ Boolean anotherFlag;
+
+#line 7982
+ IRO_ASSERT(di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+#line 7987
+ IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+#line 7996
+ IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"entry_points_to") == 0);
+
+ failed = 0;
+
+ tk = lex();
+ if (tk != '(') {
+ CError_Error(CErrorStr114);
+ failed = 1;
+ }
+
+ if (!failed) {
+ LocationSet *ls;
+ ls = LocationSet_New();
+ LocationSet_InitUnknown(ls, NULL, NULL, NULL);
+ ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 0, 0, &anotherFlag, &failed);
+ if (!failed) {
+ if ((tk = lex()) != ',') {
+ CError_Error(CErrorStr116);
+ failed = 1;
+ }
+ }
+ if (!failed) {
+ Type *type;
+ Type *innerType;
+ LocationSetSet *lss;
+
+ type = LocationSet_rtype(ls);
+ if (type && IS_TYPE_POINTER(type))
+ innerType = TPTR_TARGET(type);
+ else
+ innerType = NULL;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_TRUE, &failed);
+ if (!failed) {
+ if ((tk = lex()) != ')') {
+ CError_Error(CErrorStr115);
+ failed = 1;
+ }
+ }
+ if (!failed) {
+ PartialTransferFunction *ptf;
+ PointsToFunction *pointsToFunc;
+ PointsToEntry *pte;
+
+ if (!proc->u.func.ptfList) {
+ proc->u.func.ptfList = PTFList_New();
+ PTFList_Init(proc->u.func.ptfList);
+ }
+ ptf = PTFList_FindFirst(proc->u.func.ptfList);
+ if (!ptf)
+ ptf = AllocatePTF(proc, NULL, NULL);
+
+ pointsToFunc = PartialTransferFunction_initialPointsToFn(ptf);
+ pte = PointsToEntry_New();
+ PointsToEntry_Init(pte, ls, lss);
+ PointsToFunction_Add(pointsToFunc, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ }
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ }
+ }
+}
+
+void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di) {
+ Object *proc;
+ Boolean failed;
+ Boolean anotherFlag;
+
+#line 8097
+ IRO_ASSERT(di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+#line 8102
+ IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+#line 8111
+ IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"exit_points_to") == 0);
+
+ failed = 0;
+
+ tk = lex();
+ if (tk != '(') {
+ CError_Error(CErrorStr114);
+ failed = 1;
+ }
+
+ if (!failed) {
+ LocationSet *ls;
+ ls = LocationSet_New();
+ LocationSet_InitUnknown(ls, NULL, NULL, NULL);
+ ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 1, 0, &anotherFlag, &failed);
+ if (!failed) {
+ if ((tk = lex()) != ',') {
+ CError_Error(CErrorStr116);
+ failed = 1;
+ }
+ }
+ if (!failed) {
+ Type *type;
+ Type *innerType;
+ LocationSetSet *lss;
+
+ type = LocationSet_rtype(ls);
+ if (type && IS_TYPE_POINTER(type))
+ innerType = TPTR_TARGET(type);
+ else
+ innerType = NULL;
+
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed);
+ if (!failed) {
+ if ((tk = lex()) != ')') {
+ CError_Error(CErrorStr115);
+ failed = 1;
+ }
+ }
+ if (!failed) {
+ PartialTransferFunction *ptf;
+ PointsToFunction *pointsToFunc;
+ PointsToEntry *pte;
+
+ if (!proc->u.func.ptfList) {
+ proc->u.func.ptfList = PTFList_New();
+ PTFList_Init(proc->u.func.ptfList);
+ }
+ ptf = PTFList_FindFirst(proc->u.func.ptfList);
+ if (!ptf)
+ ptf = AllocatePTF(proc, NULL, NULL);
+
+ pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
+ pte = PointsToEntry_New();
+ if (anotherFlag)
+ PointsToEntry_Init(pte, PartialTransferFunction_returnLocation(ptf), lss);
+ else
+ PointsToEntry_Init(pte, ls, lss);
+ PointsToFunction_Add(pointsToFunc, pte);
+ PointsToEntry_Term(pte);
+ PointsToEntry_Delete(pte);
+ }
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+ }
+ }
+}
+
+void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di) {
+ Object *proc;
+ Boolean failed;
+ LocationSetSet *lss;
+ PartialTransferFunction *ptf;
+ LocationSetSet *ptfLSS;
+
+#line 8211
+ IRO_ASSERT(di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+#line 8216
+ IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+#line 8225
+ IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"function_modifies") == 0);
+
+ failed = 0;
+ lss = LocationSetSet_New();
+ LocationSetSet_Init(lss);
+ ParseLocationSetSet(lss, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed);
+ if (!failed) {
+ if (!proc->u.func.ptfList) {
+ proc->u.func.ptfList = PTFList_New();
+ PTFList_Init(proc->u.func.ptfList);
+ }
+ ptf = PTFList_FindFirst(proc->u.func.ptfList);
+ if (!ptf)
+ ptf = AllocatePTF(proc, NULL, NULL);
+ ptfLSS = PTF_sub_48D750(ptf);
+ LocationSetSet_RemoveAll(ptfLSS);
+ LocationSetSet_AddSet(ptfLSS, lss);
+ }
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+}
+
diff --git a/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c b/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c
new file mode 100644
index 0000000..baec435
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c
@@ -0,0 +1,2925 @@
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+
+// TODO: this should really be elsewhere (but where?)
+inline UInt32 gcd(UInt32 a, UInt32 b) {
+ UInt32 chk;
+
+ if (!a)
+ return b;
+ if (!b)
+ return a;
+
+ while (1) {
+ chk = a % b;
+ if (!chk)
+ return b;
+ a = b;
+ b = chk;
+ }
+}
+
+// #define IRO_DEBUG
+
+typedef struct ExtendedParamSet ExtendedParamSet;
+typedef struct LocationSet LocationSet;
+typedef struct LocationSetSet LocationSetSet;
+typedef struct ObjectSet ObjectSet;
+typedef struct PAHeapBlock PAHeapBlock;
+typedef struct PALocalVar PALocalVar;
+typedef struct PAMemoryBlock PAMemoryBlock;
+typedef struct ParamMapping ParamMapping;
+typedef struct ParamMappingFunction ParamMappingFunction;
+typedef struct PartialTransferFunction PartialTransferFunction;
+typedef struct PointsToEntry PointsToEntry;
+// typedef struct PointsToFunction PointsToFunction;
+typedef struct Stack Stack;
+typedef struct StackElement StackElement;
+
+typedef UInt32 uint32;
+
+void __assertion_failed(char *expr, char *filename, int line);
+
+#ifdef IRO_DEBUG
+#define IRO_ASSERT(expr) \
+ do { \
+ if (!(expr)) { \
+ __assertion_failed(#expr, __FILE__, __LINE__); \
+ } \
+ } while (0);
+
+#define IRO_DEBUG_CLEAR(obj, type) \
+ memset((obj), 0xFF, sizeof(type))
+#else
+#define IRO_ASSERT(expr) ((void) 0)
+#define IRO_DEBUG_CLEAR(obj, type) ((void) 0)
+#endif
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+struct StackElement {
+ Object *proc;
+ PartialTransferFunction *ptf;
+ ParamMappingFunction *map;
+ IROLinear *funcCall;
+};
+
+struct Stack {
+ StackElement *top;
+ Stack *next;
+};
+
+struct ObjectSet {
+ Object *proc;
+ ObjectSet *otherProcs;
+};
+
+struct ExtendedParam {
+ ObjectSet *objectSet;
+ uint32 x4;
+};
+
+struct ExtendedParamSet {
+ ExtendedParam *ep;
+ ExtendedParamSet *otherEps;
+};
+
+struct PAHeapBlock {
+ IROLinear *x0;
+};
+
+struct PALocalVar {
+ Object *x0;
+ char *x4;
+};
+
+typedef enum {
+ PAMEMORYBLOCKKIND_INVALID,
+ PAMEMORYBLOCKKIND_1,
+ PAMEMORYBLOCKKIND_EXTENDEDPARAM,
+ PAMEMORYBLOCKKIND_LOCALVAR,
+ PAMEMORYBLOCKKIND_HEAPBLOCK,
+ PAMEMORYBLOCKKIND_INT,
+ PAMEMORYBLOCKKIND_6
+} PAMemoryBlockKind;
+
+struct PAMemoryBlock {
+ PAMemoryBlockKind kind;
+ union {
+ ExtendedParam *ep;
+ PALocalVar *localvar;
+ PAHeapBlock *heapblock;
+ CInt64 intval;
+ void *x6;
+ } u;
+};
+
+struct LocationSet {
+ PAMemoryBlock *block;
+ Type *rtype;
+ union {
+ struct {
+ CInt64 field;
+ UInt32 stride;
+ } known;
+ struct {
+ PAMemoryBlock *restriction;
+ LocationSet *bitfieldOf;
+ } unknown;
+ } u;
+};
+
+struct LocationSetSet {
+ LocationSet *loc;
+ LocationSetSet *otherLocs;
+ UInt8 count;
+};
+
+struct ParamMapping {
+ IROLinear *actual;
+ Object *formal;
+ ExtendedParam *extended;
+};
+
+struct ParamMappingFunction {
+ ParamMapping *mapping;
+ ParamMappingFunction *otherMappings;
+};
+
+struct PointsToEntry {
+ LocationSet *loc;
+ LocationSetSet *locs;
+};
+
+struct PointsToFunction {
+ PointsToEntry *pte;
+ PointsToFunction *otherPtes;
+};
+
+struct PartialTransferFunction {
+ PointsToFunction *initialPointsToFn;
+ PointsToFunction *finalPointsToFn;
+ LocationSetSet *funcModifies;
+ LocationSet *returnLocation;
+ Boolean x10;
+ struct {
+ IROLinear *nd;
+ PartialTransferFunction *ptf;
+ } context;
+};
+
+struct PTFList {
+ PartialTransferFunction *ptf;
+ PTFList *otherPTFs;
+};
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+// TODO: how many of these are actually in IroPointerAnalysis.c?
+static uint32 stExtendedParamNum;
+static PartialTransferFunction *stUnknownPTF;
+static uint32 stIndentationLevel;
+static UInt8 stTabs[0x2C]; // unused mystery object
+static Stack *stCallingContextStack;
+static ObjectList *stParamObjs;
+static jmp_buf stAbortPointerAnalysis;
+static Object stUnknown;
+static Object *stCurrentProc;
+static ExtendedParamSet *stExtParamSet;
+static PTFList *stPTFList;
+static uint32 stMaxPassCount;
+// TODO: stEvalProcActionParams
+static IRONode *stExceptionFNode;
+
+static PAMemoryBlock stDummyMemoryBlock = {
+ PAMEMORYBLOCKKIND_1
+};
+static PAMemoryBlock *stUnknownMb = &stDummyMemoryBlock;
+
+static LocationSet stDummyLocationSet = {
+ &stDummyMemoryBlock
+};
+
+static LocationSet *stUnknownLs = &stDummyLocationSet;
+
+// forward decls
+inline StackElement *Stack_sub_48A5B0(Stack **stackPtr);
+inline void ObjectSet_RemoveAll(ObjectSet *procList);
+inline void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList);
+inline void LocationSet_Copy(LocationSet *dest, LocationSet *src);
+inline Boolean LocationSet_IsUnknown(LocationSet *ls);
+inline void LocationSetSet_RemoveAll(LocationSetSet *lss);
+inline void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src);
+inline void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf);
+inline void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src);
+inline void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc);
+inline void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src);
+inline void PTFList_RemoveAll(PTFList *ptfList);
+
+inline StackElement *StackElement_New(void) {
+ StackElement *stackElement = IRO_malloc(sizeof(StackElement));
+#line 103
+ IRO_ASSERT(stackElement != NULL);
+#ifdef IRO_DEBUG
+ stackElement->proc = NULL;
+ stackElement->ptf = NULL;
+ stackElement->map = NULL;
+ stackElement->funcCall = NULL;
+#endif
+ return stackElement;
+}
+
+inline void StackElement_Delete(StackElement *stackElement) {
+#line 117
+ IRO_ASSERT(stackElement != NULL);
+ IRO_ASSERT(stackElement->proc == NULL);
+ IRO_ASSERT(stackElement->ptf == NULL);
+ IRO_ASSERT(stackElement->map == NULL);
+ IRO_ASSERT(stackElement->funcCall == NULL);
+ IRO_DEBUG_CLEAR(stackElement, sizeof(StackElement));
+ IRO_free(stackElement);
+}
+
+inline void StackElement_Init(StackElement *stackElement, Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map, IROLinear *funcCall) {
+#line 131
+ IRO_ASSERT(stackElement != NULL);
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(map != NULL);
+ IRO_ASSERT(funcCall != NULL);
+ stackElement->proc = proc;
+ stackElement->ptf = ptf;
+ stackElement->map = map;
+ stackElement->funcCall = funcCall;
+}
+
+inline void StackElement_Copy(StackElement *dest, StackElement *src) {
+#line 145
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+ StackElement_Init(dest, src->proc, src->ptf, src->map, src->funcCall);
+}
+
+inline void StackElement_Term(StackElement *stackElement) {
+#line 156
+ IRO_ASSERT(stackElement != NULL);
+#ifdef IRO_DEBUG
+ stackElement->proc = NULL;
+ stackElement->ptf = NULL;
+ stackElement->map = NULL;
+ stackElement->funcCall = NULL;
+#endif
+}
+
+inline void *StackElement_sub_48A780(StackElement *stackElement) {
+#line 213
+ IRO_ASSERT(stackElement != NULL);
+ return stackElement->proc;
+}
+
+inline Boolean StackRelated_sub_48A760(void *key1, void *key2) {
+#line 220
+ IRO_ASSERT(key1 != NULL);
+ IRO_ASSERT(key2 != NULL);
+ return key1 == key2;
+}
+
+inline Object *StackElement_proc(StackElement *stackElement) {
+#line 228
+ IRO_ASSERT(stackElement != NULL);
+ return stackElement->proc;
+}
+
+inline PartialTransferFunction *StackElement_ptf(StackElement *stackElement) {
+#line 235
+ IRO_ASSERT(stackElement != NULL);
+ return stackElement->ptf;
+}
+
+inline ParamMappingFunction *StackElement_map(StackElement *stackElement) {
+#line 242
+ IRO_ASSERT(stackElement != NULL);
+ return stackElement->map;
+}
+
+inline IROLinear *StackElement_funcCall(StackElement *stackElement) {
+#line 249
+ IRO_ASSERT(stackElement != NULL);
+ return stackElement->funcCall;
+}
+
+inline Stack *Stack_New(void) {
+ Stack *stack = IRO_malloc(sizeof(Stack));
+#line 265
+ IRO_ASSERT(stack != NULL);
+#ifdef IRO_DEBUG
+ stack->top = NULL;
+ stack->next = NULL;
+#endif
+ return stack;
+}
+
+inline void Stack_Delete(Stack *stack) {
+#line 277
+ IRO_ASSERT(stack != NULL);
+ IRO_ASSERT(stack->top == NULL);
+ IRO_ASSERT(stack->next == NULL);
+ IRO_DEBUG_CLEAR(stack, sizeof(Stack));
+ IRO_free(stack);
+}
+
+inline void Stack_Init(Stack *stack) {
+#line 289
+ IRO_ASSERT(stack != NULL);
+ stack->top = NULL;
+ stack->next = NULL;
+}
+
+inline void Stack_Term(Stack **stackPtr) {
+ StackElement *stackElement;
+
+#line 299
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(*stackPtr != NULL);
+
+ while ((*stackPtr)->top) {
+ stackElement = Stack_sub_48A5B0(stackPtr);
+ StackElement_Term(stackElement);
+ StackElement_Delete(stackElement);
+ }
+}
+
+inline void Stack_sub_48A660(Stack **stackPtr, StackElement *stackElement) {
+ StackElement *newElement;
+ Stack *newStack;
+
+#line 315
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(*stackPtr != NULL);
+
+ newElement = StackElement_New();
+ StackElement_Copy(newElement, stackElement);
+
+ newStack = Stack_New();
+ newStack->top = newElement;
+ newStack->next = *stackPtr;
+ *stackPtr = newStack;
+}
+
+inline StackElement *Stack_Top(Stack **stackPtr) {
+#line 331
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(*stackPtr != NULL);
+
+ return (*stackPtr)->top;
+}
+
+inline Stack *Stack_Next(Stack **stackPtr) {
+#line 343
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(*stackPtr != NULL);
+
+ return (*stackPtr)->next;
+}
+
+inline StackElement *Stack_sub_48A5B0(Stack **stackPtr) {
+ StackElement *stackElement;
+
+#line 357
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(*stackPtr != NULL);
+
+ stackElement = (*stackPtr)->top;
+ if (stackElement) {
+ Stack *next = (*stackPtr)->next;
+ (*stackPtr)->top = NULL;
+ (*stackPtr)->next = NULL;
+ Stack_Delete(*stackPtr);
+ *stackPtr = next;
+ }
+
+ return stackElement;
+}
+
+inline StackElement *Stack_sub_48A710(Stack **stackPtr, void *key) {
+ Stack *stack;
+
+#line 379
+ IRO_ASSERT(stackPtr != NULL);
+ IRO_ASSERT(key != NULL);
+
+ for (stack = *stackPtr; stack; stack = stack->next) {
+ if (stack->top) {
+ if (StackRelated_sub_48A760(StackElement_sub_48A780(stack->top), key))
+ return stack->top;
+ }
+ }
+
+ return NULL;
+}
+
+inline ObjectSet *ObjectSet_New(void) {
+ ObjectSet *procList;
+
+ procList = IRO_malloc(sizeof(ObjectSet));
+#line 439
+ IRO_ASSERT(procList != NULL);
+#ifdef IRO_DEBUG
+ procList->proc = NULL;
+ procList->otherProcs = NULL;
+#endif
+ return procList;
+}
+
+inline void ObjectSet_Delete(ObjectSet *procList) {
+#line 451
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(procList->proc == NULL);
+ IRO_ASSERT(procList->otherProcs == NULL);
+ IRO_DEBUG_CLEAR(procList, sizeof(ObjectSet));
+ IRO_free(procList);
+}
+
+inline void ObjectSet_Init(ObjectSet *procList) {
+#line 463
+ IRO_ASSERT(procList != NULL);
+ procList->proc = NULL;
+ procList->otherProcs = NULL;
+}
+
+inline void ObjectSet_Term(ObjectSet *procList) {
+#line 481
+ IRO_ASSERT(procList != NULL);
+ ObjectSet_RemoveAll(procList);
+#ifdef IRO_DEBUG
+ procList->proc = NULL;
+ procList->otherProcs = NULL;
+#endif
+}
+
+inline void ObjectSet_ForEach(ObjectSet *procList, void (*action)(Object *, void *), void *refcon) {
+#line 528
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(action != NULL);
+ IRO_ASSERT(refcon == NULL || refcon != NULL);
+
+ while (procList && procList->proc) {
+ action(procList->proc, refcon);
+ procList = procList->otherProcs;
+ }
+}
+
+inline Object *ObjectSet_sub_485020(ObjectSet *procList, Object *proc) {
+#line 540
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(proc != NULL);
+ while (procList && procList->proc) {
+ if (procList->proc == proc)
+ return procList->proc;
+ procList = procList->otherProcs;
+ }
+ return NULL;
+}
+
+inline Object *ObjectSet_FindFirst(ObjectSet *procList) {
+#line 552
+ IRO_ASSERT(procList != NULL);
+ return procList->proc;
+}
+
+inline int ObjectSet_Count(ObjectSet *procList) {
+ int count;
+
+#line 552
+ IRO_ASSERT(procList != NULL);
+
+ count = 0;
+ while (procList && procList->proc) {
+ count++;
+ procList = procList->otherProcs;
+ }
+
+ return count;
+}
+
+inline void ObjectSet_sub_486800(ObjectSet *procList, Object *proc) {
+ ObjectSet *newProcList;
+
+#line 574
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ if (procList->proc) {
+ newProcList = ObjectSet_New();
+ ObjectSet_Init(newProcList);
+ newProcList->proc = procList->proc;
+ newProcList->otherProcs = procList->otherProcs;
+ procList->otherProcs = newProcList;
+ }
+
+ procList->proc = proc;
+}
+
+inline void ObjectSet_sub_4867D0(ObjectSet *procList, Object *proc) {
+#line 592
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ if (!ObjectSet_sub_485020(procList, proc))
+ ObjectSet_sub_486800(procList, proc);
+}
+
+inline void ObjectSet_Remove(ObjectSet *procList, Object *proc) {
+ ObjectSet *prev;
+ ObjectSet *tmp;
+
+#line 605
+ IRO_ASSERT(procList != NULL);
+ IRO_ASSERT(proc != NULL);
+
+ prev = NULL;
+ while (procList && procList->proc) {
+ if (procList->proc == proc) {
+ if (!prev) {
+ if (procList->otherProcs == NULL) {
+ procList->proc = NULL;
+ } else {
+ tmp = procList->otherProcs;
+ procList->proc = procList->otherProcs->proc;
+ procList->otherProcs = procList->otherProcs->otherProcs;
+ tmp->proc = NULL;
+ tmp->otherProcs = NULL;
+ ObjectSet_Term(tmp);
+ ObjectSet_Delete(tmp);
+ }
+ } else {
+ prev->otherProcs = procList->otherProcs;
+ procList->proc = NULL;
+ procList->otherProcs = NULL;
+ ObjectSet_Term(procList);
+ ObjectSet_Delete(procList);
+ }
+ return;
+ }
+ prev = procList;
+ procList = procList->otherProcs;
+ }
+}
+
+inline void ObjectSet_RemoveAll(ObjectSet *procList) {
+#line 645
+ IRO_ASSERT(procList != NULL);
+
+ while (procList && procList->proc)
+ ObjectSet_Remove(procList, procList->proc);
+}
+
+inline void ObjectSet_AddSetAction(Object *proc, void *refcon) {
+#line 655
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ ObjectSet_sub_4867D0(refcon, proc);
+}
+
+inline void ObjectSet_SimpleAddSetAction(Object *proc, void *refcon) {
+#line 663
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ ObjectSet_sub_486800(refcon, proc);
+}
+
+inline void ObjectSet_sub_48C590(ObjectSet *dest, ObjectSet *src) {
+#line 671
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ if (dest->proc)
+ ObjectSet_ForEach(src, ObjectSet_AddSetAction, dest);
+ else
+ ObjectSet_ForEach(src, ObjectSet_SimpleAddSetAction, dest);
+}
+
+inline void ObjectSet_RemoveSetAction(Object *proc, void *refcon) {
+#line 682
+ IRO_ASSERT(proc != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ ObjectSet_Remove(refcon, proc);
+}
+
+inline void ObjectSet_removeiter_sub_48C890(ObjectSet *dest, ObjectSet *src) {
+#line 690
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ ObjectSet_ForEach(src, ObjectSet_RemoveSetAction, dest);
+}
+
+inline Boolean ObjectSet_sub_484FA0(ObjectSet *os1, ObjectSet *os2) {
+ ObjectSet *scan;
+
+#line 700
+ IRO_ASSERT(os1 != NULL);
+ IRO_ASSERT(os2 != NULL);
+
+ if (os1 == os2)
+ return 1;
+
+ for (scan = os1; scan && scan->proc; scan = scan->otherProcs) {
+ if (!ObjectSet_sub_485020(os2, scan->proc))
+ return 0;
+ }
+
+ for (scan = os2; scan && scan->proc; scan = scan->otherProcs) {
+ if (!ObjectSet_sub_485020(os1, scan->proc))
+ return 0;
+ }
+
+ return 1;
+}
+
+inline ExtendedParam *ExtendedParam_New(void) {
+ ExtendedParam *ep = IRO_malloc(sizeof(ExtendedParam));
+
+#line 755
+ IRO_ASSERT(ep != NULL);
+#ifdef IRO_DEBUG
+ ep->objectSet = NULL;
+#endif
+ return ep;
+}
+
+inline void ExtendedParam_Delete(ExtendedParam *ep) {
+ IRO_ASSERT(ep != NULL);
+ IRO_ASSERT(ep->objectSet == NULL);
+ IRO_DEBUG_CLEAR(ep, sizeof(ExtendedParam));
+ IRO_free(ep);
+}
+
+inline void ExtendedParam_Init(ExtendedParam *ep, Object *obj) {
+#line 777
+ IRO_ASSERT(ep != NULL);
+ IRO_ASSERT(obj != NULL);
+ IRO_ASSERT(obj->extParam == NULL);
+ IRO_ASSERT(stExtendedParamNum < ((uint32) -1) / 2 - 1);
+
+ ep->objectSet = ObjectSet_New();
+ ObjectSet_Init(ep->objectSet);
+ ObjectSet_sub_4867D0(ep->objectSet, obj);
+ obj->extParam = ep;
+
+ ep->x4 = stExtendedParamNum++;
+}
+
+inline void ExtendedParam_TermAction(Object *obj, void *refcon) {
+ obj->extParam = NULL;
+}
+
+inline void ExtendedParam_Term(ExtendedParam *ep) {
+ IRO_ASSERT(ep != NULL);
+
+ ObjectSet_ForEach(ep->objectSet, ExtendedParam_TermAction, NULL);
+ ObjectSet_Term(ep->objectSet);
+ ObjectSet_Delete(ep->objectSet);
+#ifdef IRO_DEBUG
+ ep->objectSet = NULL;
+#endif
+}
+
+inline Boolean ExtendedParams_Equal(ExtendedParam *ep1, ExtendedParam *ep2) {
+#line 841
+ IRO_ASSERT(ep1 != NULL);
+ IRO_ASSERT(ep2 != NULL);
+ IRO_ASSERT(ep1->objectSet != NULL);
+ IRO_ASSERT(ep2->objectSet != NULL);
+
+ if (ep1 == ep2)
+ return 1;
+
+ return ep1->x4 == ep2->x4 && ObjectSet_sub_484FA0(ep1->objectSet, ep2->objectSet);
+}
+
+inline ExtendedParam *ExtendedParam_FindByObject(Object *obj) {
+#line 856
+ IRO_ASSERT(obj != NULL);
+
+ return obj->extParam;
+}
+
+inline void ExtendedParam_sub_4867B0(ExtendedParam *ep, Object *obj) {
+#line 863
+ IRO_ASSERT(ep != NULL);
+ IRO_ASSERT(ep->objectSet != NULL);
+ IRO_ASSERT(obj != NULL);
+
+ ObjectSet_sub_4867D0(ep->objectSet, obj);
+ obj->extParam = ep;
+}
+
+inline void ExtendedParam_RemoveObjectSetAction(Object *object, void *refcon) {
+ object->extParam = NULL;
+}
+
+inline void EP_sub_48C850(ExtendedParam *ep, ObjectSet *objSet) {
+#line 888
+ IRO_ASSERT(ep != NULL);
+ IRO_ASSERT(ep->objectSet != NULL);
+ IRO_ASSERT(objSet != NULL);
+
+ ObjectSet_removeiter_sub_48C890(ep->objectSet, objSet);
+ ObjectSet_ForEach(objSet, ExtendedParam_RemoveObjectSetAction, NULL);
+}
+
+inline ObjectSet *ExtendedParam_objectSet(ExtendedParam *ep) {
+#line 898
+ IRO_ASSERT(ep != NULL);
+
+ return ep->objectSet;
+}
+
+inline uint32 ExtendedParam_sub_489110(ExtendedParam *ep) {
+#line 905
+ IRO_ASSERT(ep != NULL);
+
+ return ep->x4;
+}
+
+inline ExtendedParamSet *AllocsExtParamSet_sub_4876C0(void) {
+ ExtendedParamSet *epList = IRO_malloc(sizeof(ExtendedParamSet));
+
+#line 924
+ IRO_ASSERT(epList != NULL);
+#ifdef IRO_DEBUG
+ epList->ep = NULL;
+ epList->otherEps = NULL;
+#endif
+ return epList;
+}
+
+inline void FreesExtParamSet_sub_48CAE0(ExtendedParamSet *epList) {
+#line 936
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(epList->ep == NULL);
+ IRO_ASSERT(epList->otherEps == NULL);
+ IRO_DEBUG_CLEAR(epList, sizeof(ExtendedParamSet));
+ IRO_free(epList);
+}
+
+inline void InitsExtParamSet_sub_4876A0(ExtendedParamSet *epList) {
+#line 948
+ IRO_ASSERT(epList != NULL);
+ epList->ep = NULL;
+ epList->otherEps = NULL;
+}
+
+inline void TermsExtParamSet_sub_48CB00(ExtendedParamSet *epList) {
+#line 966
+ IRO_ASSERT(epList != NULL);
+ ExtendedParamSet_RemoveAll(epList);
+#ifdef IRO_DEBUG
+ epList->ep = NULL;
+ epList->otherEps = NULL;
+#endif
+}
+
+inline void MaybeWalkExtParamSet_sub_48CBE0(ExtendedParamSet *epList, void (*action)(ExtendedParam *, void *), void *refcon) {
+#line 1010
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(action != NULL);
+
+ while (epList && epList->ep) {
+ action(epList->ep, refcon);
+ epList = epList->otherEps;
+ }
+}
+
+inline ExtendedParam *ExtParamSet_sub_4876D0(ExtendedParamSet *epList, ExtendedParam *ep) {
+#line 1022
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(ep != NULL);
+
+ while (epList && epList->ep) {
+ if (epList->ep == ep)
+ return epList->ep;
+ epList = epList->otherEps;
+ }
+
+ return NULL;
+}
+
+inline void ExtParamSet_sub_487660(ExtendedParamSet *epList, ExtendedParam *ep) {
+#line 1056
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(ep != NULL);
+
+ if (epList->ep) {
+ ExtendedParamSet *newSet = AllocsExtParamSet_sub_4876C0();
+ InitsExtParamSet_sub_4876A0(newSet);
+ newSet->ep = epList->ep;
+ newSet->otherEps = epList->otherEps;
+ epList->otherEps = newSet;
+ }
+
+ epList->ep = ep;
+}
+
+inline void ExtParamSet_sub_487630(ExtendedParamSet *epList, ExtendedParam *ep) {
+#line 1076
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(ep != NULL);
+
+ if (!ExtParamSet_sub_4876D0(epList, ep))
+ ExtParamSet_sub_487660(epList, ep);
+}
+
+inline void ExtendedParamSet_Remove(ExtendedParamSet *epList, ExtendedParam *ep) {
+ ExtendedParamSet *prev;
+ ExtendedParamSet *tmp;
+
+#line 1089
+ IRO_ASSERT(epList != NULL);
+ IRO_ASSERT(ep != NULL);
+
+ prev = NULL;
+ while (epList && epList->ep) {
+ if (epList->ep == ep) {
+ if (!prev) {
+ if (epList->otherEps == NULL) {
+ epList->ep = NULL;
+ } else {
+ tmp = epList->otherEps;
+ epList->ep = epList->otherEps->ep;
+ epList->otherEps = epList->otherEps->otherEps;
+ tmp->ep = NULL;
+ tmp->otherEps = NULL;
+ TermsExtParamSet_sub_48CB00(tmp);
+ FreesExtParamSet_sub_48CAE0(tmp);
+ }
+ } else {
+ prev->otherEps = epList->otherEps;
+ epList->ep = NULL;
+ epList->otherEps = NULL;
+ TermsExtParamSet_sub_48CB00(epList);
+ FreesExtParamSet_sub_48CAE0(epList);
+ }
+ return;
+ }
+ prev = epList;
+ epList = epList->otherEps;
+ }
+}
+
+inline void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList) {
+#line 1129
+ IRO_ASSERT(epList != NULL);
+
+ while (epList && epList->ep)
+ ExtendedParamSet_Remove(epList, epList->ep);
+}
+
+inline PAHeapBlock *CreateUniqueHeapAlloc_sub_486420(void) {
+ PAHeapBlock *hb = IRO_malloc(sizeof(PAHeapBlock));
+
+#line 1225
+ IRO_ASSERT(hb != NULL);
+#ifdef IRO_DEBUG
+ hb->parent = NULL;
+#endif
+ return hb;
+}
+
+inline void InitUniqueHeapAlloc_sub_486410(PAHeapBlock *hb, IROLinear *nd) {
+#line 1247
+ IRO_ASSERT(hb != NULL);
+
+ hb->x0 = nd;
+}
+
+inline Boolean PAHeapBlocks_Equal(PAHeapBlock *hb1, PAHeapBlock *hb2) {
+#line 1296
+ IRO_ASSERT(hb1 != NULL);
+ IRO_ASSERT(hb2 != NULL);
+
+ return (hb1 == hb2) || (hb1->x0 == hb2->x0);
+}
+
+inline PALocalVar *PALocalVar_New(void) {
+ PALocalVar *local = IRO_malloc(sizeof(PALocalVar));
+
+#line 1333
+ IRO_ASSERT(local != NULL);
+#ifdef IRO_DEBUG
+ local->parent = NULL;
+ local->nextSibling = NULL;
+#endif
+ return local;
+}
+
+inline void PALocalVar_InitByObject(PALocalVar *local, Object *obj) {
+#line 1357
+ IRO_ASSERT(local != NULL);
+ IRO_ASSERT(obj != NULL);
+
+ local->x0 = obj;
+ if (obj->name && obj->name->name) {
+ local->x4 = IRO_malloc(strlen(obj->name->name) + 1);
+ strcpy(local->x4, obj->name->name);
+ } else {
+ local->x4 = NULL;
+ }
+}
+
+inline void PALocalVar_InitByName(PALocalVar *local, char *name) {
+#line 1372
+ IRO_ASSERT(local != NULL);
+ IRO_ASSERT(name != NULL);
+
+ local->x0 = NULL;
+ local->x4 = IRO_malloc(strlen(name) + 1);
+ strcpy(local->x4, name);
+}
+
+inline Boolean PALocalVars_Equal(PALocalVar *local1, PALocalVar *local2) {
+#line 1419
+ IRO_ASSERT(local1 == NULL || local1 != NULL);
+ IRO_ASSERT(local2 == NULL || local2 != NULL);
+
+ if (local1 == local2)
+ return 1;
+ if (!local1 || !local2)
+ return 0;
+
+ if (!local1->x0 || !local2->x0) {
+ if (local1->x4)
+ return local2->x4 && !strcmp(local1->x4, local2->x4);
+ }
+
+ return local1->x0 == local2->x0;
+}
+
+inline void PALocalVar_SetSth_sub_4847C0(PALocalVar *local, Object *obj) {
+#line 1436
+ IRO_ASSERT(local != NULL);
+ IRO_ASSERT(obj == NULL || obj != NULL);
+
+ local->x0 = obj;
+}
+
+inline Object *PALocalVar_Get0_sub_4847E0(PALocalVar *local) {
+#line 1444
+ IRO_ASSERT(local != NULL);
+ return local->x0;
+}
+
+inline char *PALocalVar_Get4_sub_4847D0(PALocalVar *local) {
+#line 1451
+ IRO_ASSERT(local != NULL);
+ return local->x4;
+}
+
+inline PAMemoryBlock *PAMemoryBlock_New(void) {
+ PAMemoryBlock *mb = IRO_malloc(sizeof(PAMemoryBlock));
+
+#line 1491
+ IRO_ASSERT(mb != NULL);
+#ifdef IRO_DEBUG
+ mb->kind = PAMEMORYBLOCKKIND_INVALID;
+#endif
+ return mb;
+}
+
+inline void PAMemoryBlock_Delete(PAMemoryBlock *mb) {
+#line 1502
+ IRO_ASSERT(mb != NULL);
+ IRO_ASSERT(mb->kind == PAMEMORYBLOCKKIND_INVALID);
+ IRO_free(mb);
+}
+
+inline void PAMemoryBlock_Init(PAMemoryBlock *mb, PAMemoryBlockKind kind, void *thing) {
+#line 1513
+ IRO_ASSERT(mb != NULL);
+ IRO_ASSERT(thing == NULL || thing != NULL);
+
+ mb->kind = kind;
+ switch (mb->kind) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ mb->u.ep = (ExtendedParam *) thing;
+ break;
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ mb->u.localvar = (PALocalVar *) thing;
+ break;
+ case PAMEMORYBLOCKKIND_HEAPBLOCK:
+ mb->u.heapblock = (PAHeapBlock *) thing;
+ break;
+ case PAMEMORYBLOCKKIND_INT:
+ mb->u.intval = *((CInt64 *) thing);
+ break;
+ case PAMEMORYBLOCKKIND_6:
+ mb->u.x6 = (void *) thing;
+ break;
+ default:
+#line 1535
+ CError_FATAL();
+ }
+}
+
+inline void PAMemoryBlock_Term(PAMemoryBlock *mb) {
+#line 1552
+ IRO_ASSERT(mb != NULL);
+
+#ifdef IRO_DEBUG
+ mb->kind = PAMEMORYBLOCKKIND_INVALID;
+#endif
+}
+
+inline Boolean MemoryBlocks_Equal(PAMemoryBlock *mb1, PAMemoryBlock *mb2) {
+#line 1657
+ IRO_ASSERT(mb1 == NULL || mb1 != NULL);
+ IRO_ASSERT(mb2 == NULL || mb2 != NULL);
+
+ if (mb1 == mb2)
+ return 1;
+
+ if (!mb1 || !mb2 || mb1->kind != mb2->kind)
+ return 0;
+
+ switch (mb1->kind) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ return ExtendedParams_Equal(mb1->u.ep, mb2->u.ep);
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ return PALocalVars_Equal(mb1->u.localvar, mb2->u.localvar);
+ case PAMEMORYBLOCKKIND_HEAPBLOCK:
+ return PAHeapBlocks_Equal(mb1->u.heapblock, mb2->u.heapblock);
+ case PAMEMORYBLOCKKIND_INT:
+ return CInt64_Equal(mb1->u.intval, mb2->u.intval);
+ case PAMEMORYBLOCKKIND_6:
+ return mb1->u.x6 == mb2->u.x6;
+ default:
+#line 1684
+ CError_FATAL();
+ return 0;
+ }
+}
+
+inline PAMemoryBlockKind PAMemoryBlock_kind(PAMemoryBlock *mb) {
+#line 1692
+ IRO_ASSERT(mb != NULL);
+
+ return mb->kind;
+}
+
+inline void *PAMemoryBlock_thing(PAMemoryBlock *mb) {
+#line 1699
+ IRO_ASSERT(mb != NULL);
+
+ switch (mb->kind) {
+ case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
+ return mb->u.ep;
+ case PAMEMORYBLOCKKIND_LOCALVAR:
+ return mb->u.localvar;
+ case PAMEMORYBLOCKKIND_HEAPBLOCK:
+ return mb->u.heapblock;
+ case PAMEMORYBLOCKKIND_INT:
+ return &mb->u.intval;
+ case PAMEMORYBLOCKKIND_6:
+ return mb->u.x6;
+ default:
+#line 1719
+ CError_FATAL();
+ return NULL;
+ }
+}
+
+inline LocationSet *LocationSet_New(void) {
+ LocationSet *ls = IRO_malloc(sizeof(LocationSet));
+
+#line 1767
+ IRO_ASSERT(ls != NULL);
+#ifdef IRO_DEBUG
+ ls->block = NULL;
+ ls->rtype = NULL;
+ ls->u.known.field = cint64_zero;
+ ls->u.known.stride = 0;
+#endif
+ return ls;
+}
+
+inline void LocationSet_Delete(LocationSet *ls) {
+#line 1781
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+ IRO_ASSERT(ls->block == NULL);
+ IRO_ASSERT(CInt64_IsZero(&ls->u.known.field));
+ IRO_ASSERT(ls->u.known.stride == 0);
+ IRO_ASSERT(ls->rtype == NULL);
+ IRO_DEBUG_CLEAR(ls, sizeof(LocationSet));
+ IRO_free(ls);
+}
+
+inline void LocationSet_InitKnown(LocationSet *ls, PAMemoryBlock *block, CInt64 field, UInt32 stride, Type *rtype) {
+#line 1796
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+ IRO_ASSERT(block != NULL);
+ IRO_ASSERT(rtype == NULL || rtype != NULL);
+ ls->block = block;
+ ls->rtype = rtype;
+ ls->u.known.field = field;
+ ls->u.known.stride = stride;
+}
+
+inline void LocationSet_InitUnknown(LocationSet *ls, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) {
+#line 1809
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+ IRO_ASSERT(rtype == NULL || rtype != NULL);
+ IRO_ASSERT(restriction == NULL || restriction != NULL);
+ IRO_ASSERT(bitfieldOf == NULL || bitfieldOf != NULL);
+
+ LocationSet_Copy(ls, stUnknownLs);
+ ls->rtype = rtype;
+ ls->u.unknown.restriction = restriction;
+ if (bitfieldOf) {
+ ls->u.unknown.bitfieldOf = LocationSet_New();
+ LocationSet_Copy(ls->u.unknown.bitfieldOf, bitfieldOf);
+ } else {
+ ls->u.unknown.bitfieldOf = NULL;
+ }
+}
+
+inline void LocationSet_Copy(LocationSet *dest, LocationSet *src) {
+#line 1829
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ dest->block = src->block;
+ dest->rtype = src->rtype;
+
+ if (!LocationSet_IsUnknown(src)) {
+ dest->u.known.field = src->u.known.field;
+ dest->u.known.stride = src->u.known.stride;
+ } else {
+ dest->u.unknown.restriction = src->u.unknown.restriction;
+ if (src->u.unknown.bitfieldOf != NULL) {
+ dest->u.unknown.bitfieldOf = LocationSet_New();
+ LocationSet_Copy(dest->u.unknown.bitfieldOf, src->u.unknown.bitfieldOf);
+ } else {
+ dest->u.unknown.bitfieldOf = NULL;
+ }
+ }
+}
+
+inline void LocationSet_Term(LocationSet *ls) {
+#line 1857
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+
+#ifdef IRO_DEBUG
+ if (LocationSet_IsUnknown(ls) && ls->u.unknown.bitfieldOf) {
+ LocationSet_Term(ls->u.unknown.bitfieldOf);
+ LocationSet_Delete(ls->u.unknown.bitfieldOf);
+ }
+ ls->block = NULL;
+ ls->rtype = NULL;
+ ls->u.known.field = cint64_zero;
+ ls->u.known.stride = 0;
+#endif
+}
+
+inline Boolean LocationSets_Overlap(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) {
+ Boolean isUnknown1, isUnknown2;
+ PAMemoryBlock *restriction1, *restriction2;
+
+#line 1974
+ IRO_ASSERT(ls1 != NULL);
+ IRO_ASSERT(rtype1 == NULL || rtype1 != NULL);
+ IRO_ASSERT(ls2 != NULL);
+ IRO_ASSERT(rtype2 == NULL || rtype2 != NULL);
+
+ if (ls1 == ls2)
+ return 1;
+
+ isUnknown1 = LocationSet_IsUnknown(ls1);
+ if (isUnknown1)
+ restriction1 = ls1->u.unknown.restriction;
+ else
+ restriction1 = NULL;
+
+ isUnknown2 = LocationSet_IsUnknown(ls2);
+ if (isUnknown2)
+ restriction2 = ls2->u.unknown.restriction;
+ else
+ restriction2 = NULL;
+
+ if (
+ (isUnknown1 && !restriction1) ||
+ (isUnknown2 && !restriction2) ||
+ (isUnknown1 && isUnknown2 && MemoryBlocks_Equal(restriction1, restriction2))
+ )
+ return 1;
+
+ if (isUnknown1 || isUnknown2)
+ return 0;
+
+ if (MemoryBlocks_Equal(ls1->block, ls2->block)) {
+ UInt32 size1;
+ UInt32 size2;
+ UInt32 i;
+ CInt64 work;
+ CInt64 longgcd;
+
+ if (rtype1)
+ size1 = rtype1->size;
+ else
+ size1 = -1;
+
+ if (rtype2)
+ size2 = rtype2->size;
+ else
+ size2 = -1;
+
+ if (ls1->u.known.stride == ls2->u.known.stride) {
+ CInt64 longsize1;
+ CInt64 longsize2;
+ CInt64_SetULong(&longsize1, size1);
+ CInt64_SetULong(&longsize2, size2);
+
+ return CInt64_Equal(ls1->u.known.field, ls2->u.known.field) ||
+ (CInt64_Less(ls1->u.known.field, ls2->u.known.field) && CInt64_Greater(CInt64_Add(ls1->u.known.field, longsize1), ls2->u.known.field)) ||
+ (CInt64_Less(ls2->u.known.field, ls1->u.known.field) && CInt64_Greater(CInt64_Add(ls2->u.known.field, longsize2), ls1->u.known.field));
+ } else {
+ work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field);
+ if (CInt64_IsNegative(&work))
+ work = CInt64_Neg(work);
+
+ CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride));
+ if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero))
+ return 1;
+
+ if (size1 == -1)
+ return 1;
+
+ for (i = 1; i < size1; i++) {
+ CInt64_SetLong(&work, i);
+ work = CInt64_Add(work, ls1->u.known.field);
+ work = CInt64_Sub(work, ls2->u.known.field);
+ if (CInt64_IsNegative(&work))
+ work = CInt64_Neg(work);
+ if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero))
+ return 1;
+ }
+
+ if (size2 == -1)
+ return 1;
+
+ for (i = 1; i < size2; i++) {
+ CInt64_SetLong(&work, i);
+ work = CInt64_Add(work, ls2->u.known.field);
+ work = CInt64_Sub(work, ls1->u.known.field);
+ if (CInt64_IsNegative(&work))
+ work = CInt64_Neg(work);
+ if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero))
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+inline Boolean LocationSets_Equal(LocationSet *ls1, LocationSet *ls2) {
+#line 2080
+ IRO_ASSERT(ls1 != NULL);
+ IRO_ASSERT(ls2 != NULL);
+
+ return
+ (ls1 == ls2) ||
+ (
+ (LocationSet_IsUnknown(ls1) && LocationSet_IsUnknown(ls2)) &&
+ (MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction)) &&
+ ((ls1->u.unknown.bitfieldOf == ls2->u.unknown.bitfieldOf) ||
+ (ls1->u.unknown.bitfieldOf && ls2->u.unknown.bitfieldOf && LocationSets_Equal(ls1->u.unknown.bitfieldOf, ls2->u.unknown.bitfieldOf))) &&
+ ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size))
+ ) ||
+ (
+ (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) &&
+ (ls1->u.known.stride == ls2->u.known.stride) &&
+ ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) &&
+ CInt64_Equal(ls1->u.known.field, ls2->u.known.field) &&
+ MemoryBlocks_Equal(ls1->block, ls2->block)
+ );
+}
+
+inline Boolean LocationSets_LookupCompatible(LocationSet *ls1, LocationSet *ls2) {
+#line 2119
+ IRO_ASSERT(ls1 != NULL);
+ IRO_ASSERT(ls2 != NULL);
+
+ if (
+ (ls1 == ls2) ||
+ (
+ LocationSet_IsUnknown(ls1) &&
+ LocationSet_IsUnknown(ls2) &&
+ MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction) &&
+ (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size))
+ ))
+ return 1;
+
+ if (
+ (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) &&
+ (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) &&
+ MemoryBlocks_Equal(ls1->block, ls2->block)
+ ) {
+ CInt64 work;
+ CInt64 longgcd;
+
+ if (ls1->u.known.stride == ls2->u.known.stride)
+ return CInt64_Equal(ls1->u.known.field, ls2->u.known.field);
+
+ work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field);
+ if (CInt64_IsNegative(&work))
+ work = CInt64_Neg(work);
+
+ CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride));
+ return CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero);
+ }
+
+ return 0;
+}
+
+inline Boolean LocationSet_Contains(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) {
+ Boolean unknown1;
+ Boolean unknown2;
+ PAMemoryBlock *restriction2;
+ PAMemoryBlock *restriction1;
+ CInt64 longsize1;
+ CInt64 longsize2;
+
+#line 2168
+ IRO_ASSERT(ls1 != NULL);
+ IRO_ASSERT(ls2 != NULL);
+ IRO_ASSERT(rtype1 != NULL);
+ IRO_ASSERT(rtype2 != NULL);
+
+ if (ls1 == ls2)
+ return 1;
+
+ unknown1 = LocationSet_IsUnknown(ls1);
+ if (unknown1)
+ restriction1 = ls1->u.unknown.restriction;
+ else
+ restriction1 = NULL;
+
+ unknown2 = LocationSet_IsUnknown(ls2);
+ if (unknown2)
+ restriction2 = ls2->u.unknown.restriction;
+ else
+ restriction2 = NULL;
+
+ if (unknown1)
+ return !restriction1 || (unknown2 && MemoryBlocks_Equal(restriction2, restriction1));
+
+ CInt64_SetULong(&longsize1, rtype1->size);
+ CInt64_SetULong(&longsize2, rtype2->size);
+
+ return
+ !LocationSet_IsUnknown(ls2) &&
+ (ls1->u.known.stride == 0) &&
+ (ls2->u.known.stride == 0) &&
+ rtype1->size >= rtype2->size &&
+ CInt64_LessEqual(ls1->u.known.field, ls2->u.known.field) &&
+ CInt64_GreaterEqual(CInt64_Add(ls1->u.known.field, longsize1), CInt64_Add(ls2->u.known.field, longsize2)) &&
+ MemoryBlocks_Equal(ls1->block, ls2->block);
+}
+
+inline Boolean LocationSet_IsUnknown(LocationSet *ls) {
+#line 2233
+ IRO_ASSERT(ls != NULL);
+
+ return (ls == stUnknownLs) || (ls->block == stUnknownMb);
+}
+
+inline Boolean LocationSet_sub_48AF30(LocationSet *ls) {
+ return
+ !LocationSet_IsUnknown(ls) &&
+ (ls->u.known.stride == 0) &&
+ CInt64_IsZero(&ls->u.known.field) &&
+ PAMemoryBlock_kind(ls->block) == PAMEMORYBLOCKKIND_LOCALVAR &&
+ !PAMemoryBlock_thing(ls->block);
+}
+
+inline void LocationSet_SetRtype(LocationSet *ls, Type *rtype) {
+#line 2263
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+ IRO_ASSERT(rtype != NULL);
+
+ ls->rtype = rtype;
+}
+
+inline void SetsLocationSetField_sub_4851B0(LocationSet *ls, CInt64 field) {
+#line 2272
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+
+ ls->u.known.field = field;
+}
+
+inline void SetsLocationSetStride_sub_4852D0(LocationSet *ls, SInt32 stride) {
+#line 2280
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+
+ ls->u.known.stride = stride;
+}
+
+inline PAMemoryBlock *LocationSet_block(LocationSet *ls) {
+#line 2298
+ IRO_ASSERT(ls != NULL);
+
+ return ls->block;
+}
+
+inline Type *LocationSet_rtype(LocationSet *ls) {
+#line 2306
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(ls != stUnknownLs);
+
+ return ls->rtype;
+}
+
+inline CInt64 LocationSet_field(LocationSet *ls) {
+#line 2314
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+
+ return ls->u.known.field;
+}
+
+inline UInt32 LocationSet_stride(LocationSet *ls) {
+#line 2322
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+
+ return ls->u.known.stride;
+}
+
+inline PAMemoryBlock *LocationSet_restriction(LocationSet *ls) {
+#line 2330
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(LocationSet_IsUnknown(ls));
+
+ return ls->u.unknown.restriction;
+}
+
+inline LocationSet *LocationSet_bitfieldOf(LocationSet *ls) {
+#line 2338
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(LocationSet_IsUnknown(ls));
+
+ return ls->u.unknown.bitfieldOf;
+}
+
+inline LocationSetSet *LocationSetSet_New() {
+ LocationSetSet *lss = IRO_malloc(sizeof(LocationSetSet));
+
+#line 2356
+ IRO_ASSERT(lss != NULL);
+#ifdef IRO_DEBUG
+ lss->loc = NULL;
+ lss->otherLocs = NULL;
+ lss->count = 0;
+#endif
+ return lss;
+}
+
+inline void LocationSetSet_Delete(LocationSetSet *lss) {
+#line 2369
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(lss->loc == NULL);
+ IRO_ASSERT(lss->otherLocs == NULL);
+ IRO_ASSERT(lss->count == 0);
+ IRO_DEBUG_CLEAR(lss, sizeof(LocationSetSet));
+ IRO_free(lss);
+}
+
+inline void LocationSetSet_Init(LocationSetSet *lss) {
+#line 2382
+ IRO_ASSERT(lss != NULL);
+
+ lss->loc = NULL;
+ lss->otherLocs = NULL;
+ lss->count = 0;
+}
+
+inline void LocationSetSet_Copy(LocationSetSet *dest, LocationSetSet *src) {
+#line 2391
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ dest->loc = NULL;
+ dest->otherLocs = NULL;
+ dest->count = 0;
+ LocationSetSet_AddSet(dest, src);
+}
+
+inline void LocationSetSet_Term(LocationSetSet *lss) {
+#line 2402
+ IRO_ASSERT(lss != NULL);
+
+ LocationSetSet_RemoveAll(lss);
+
+#ifdef IRO_DEBUG
+ lss->loc = NULL;
+ lss->otherLocs = NULL;
+ lss->count = 0;
+#endif
+}
+
+inline void LocationSetSet_ForEach(LocationSetSet *lss, void (*action)(LocationSet *, void *), void *refcon) {
+#line 2446
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(action != NULL);
+ IRO_ASSERT(refcon == NULL || refcon != NULL);
+
+ while (lss && lss->loc) {
+ action(lss->loc, refcon);
+ lss = lss->otherLocs;
+ }
+}
+
+inline LocationSet *LocationSetSet_Find(LocationSetSet *lss, LocationSet *ls) {
+#line 2458
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ while (lss && lss->loc) {
+ if (LocationSets_Equal(lss->loc, ls))
+ return lss->loc;
+ lss = lss->otherLocs;
+ }
+
+ return NULL;
+}
+
+inline LocationSet *LocationSetSet_FindUnknown(LocationSetSet *lss) {
+#line 2470
+ IRO_ASSERT(lss != NULL);
+
+ if (!lss->loc)
+ return stUnknownLs;
+
+ while (lss && lss->loc) {
+ if (LocationSet_IsUnknown(lss->loc))
+ return lss->loc;
+ lss = lss->otherLocs;
+ }
+
+ return NULL;
+}
+
+inline LocationSet *LocationSetSet_FindFirst(LocationSetSet *lss) {
+#line 2498
+ IRO_ASSERT(lss != NULL);
+
+ return lss->loc;
+}
+
+inline int LocationSetSet_Count(LocationSetSet *lss) {
+#line 2505
+ IRO_ASSERT(lss != NULL);
+
+ return lss->count;
+}
+
+inline void LocationSetSet_RemoveAllWithMemoryBlock(LocationSetSet *lss, PAMemoryBlock *block) {
+ LocationSetSet *first;
+ LocationSetSet *prev;
+ LocationSetSet *next;
+ LocationSetSet *tmp;
+
+#line 2514
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(block != NULL);
+
+ first = lss;
+ prev = NULL;
+ while (lss && lss->loc) {
+ next = lss->otherLocs;
+ if (MemoryBlocks_Equal(block, lss->loc->block)) {
+ if (lss->loc != stUnknownLs) {
+ LocationSet_Term(lss->loc);
+ LocationSet_Delete(lss->loc);
+ }
+ if (!prev) {
+ if (lss->otherLocs == NULL) {
+ lss->loc = NULL;
+ prev = lss;
+ } else {
+ tmp = lss->otherLocs;
+ lss->loc = lss->otherLocs->loc;
+ lss->otherLocs = lss->otherLocs->otherLocs;
+ tmp->loc = NULL;
+ tmp->otherLocs = NULL;
+ LocationSetSet_Term(tmp);
+ LocationSetSet_Delete(tmp);
+ prev = NULL;
+ next = lss;
+ }
+ } else {
+ prev->otherLocs = lss->otherLocs;
+ lss->loc = NULL;
+ lss->otherLocs = NULL;
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ prev = lss;
+ }
+ first->count--;
+ }
+ lss = next;
+ }
+}
+
+inline void LocationSetSet_SimpleAdd(LocationSetSet *lss, LocationSet *ls) {
+#line 2572
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ if (!LocationSet_IsUnknown(ls) && lss->count < 4) {
+ LocationSet *ls2;
+
+ if (ls == stUnknownLs) {
+ ls2 = stUnknownLs;
+ } else {
+ ls2 = LocationSet_New();
+ LocationSet_Copy(ls2, ls);
+ }
+
+ if (lss->loc) {
+ LocationSetSet *lss2 = LocationSetSet_New();
+ LocationSetSet_Init(lss2);
+ lss2->loc = lss->loc;
+ lss2->otherLocs = lss->otherLocs;
+ lss->otherLocs = lss2;
+ }
+
+ lss->loc = ls2;
+ lss->count++;
+ } else {
+ LocationSet *ls2;
+
+ LocationSetSet_RemoveAll(lss);
+ ls2 = LocationSet_New();
+ if (LocationSet_IsUnknown(ls)) {
+ LocationSet_Copy(ls2, ls);
+ } else {
+ LocationSet_Copy(ls2, stUnknownLs);
+ if (ls->rtype)
+ LocationSet_SetRtype(ls2, ls->rtype);
+ }
+
+ lss->loc = ls2;
+ lss->count = 1;
+ }
+}
+
+inline void LocationSetSet_Add(LocationSetSet *lss, LocationSet *ls) {
+#line 2622
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ if (!lss->loc || (!LocationSet_IsUnknown(lss->loc) && !LocationSetSet_Find(lss, ls))) {
+ if (!LocationSet_IsUnknown(ls) && ls->u.known.stride)
+ LocationSetSet_RemoveAllWithMemoryBlock(lss, ls->block);
+ LocationSetSet_SimpleAdd(lss, ls);
+ }
+}
+
+inline void LocationSetSet_AddUnknown(LocationSetSet *lss, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) {
+ LocationSet *ls;
+
+#line 2643
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(rtype == NULL || rtype != NULL);
+ IRO_ASSERT(restriction == NULL || restriction != NULL);
+ IRO_ASSERT(bitfieldOf == NULL || bitfieldOf != NULL);
+
+ ls = LocationSet_New();
+ LocationSet_InitUnknown(ls, rtype, restriction, bitfieldOf);
+ LocationSetSet_Add(lss, ls);
+ LocationSet_Term(ls);
+ LocationSet_Delete(ls);
+}
+
+inline void LocationSetSet_Remove(LocationSetSet *lss, LocationSet *ls) {
+ LocationSetSet *prev;
+ LocationSetSet *first;
+ LocationSetSet *tmp;
+
+#line 2659
+ IRO_ASSERT(lss != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ first = lss;
+ prev = NULL;
+ while (lss && lss->loc) {
+ if (LocationSets_Equal(lss->loc, ls)) {
+ if (lss->loc != stUnknownLs) {
+ LocationSet_Term(lss->loc);
+ LocationSet_Delete(lss->loc);
+ }
+ if (!prev) {
+ if (lss->otherLocs == NULL) {
+ lss->loc = NULL;
+ } else {
+ tmp = lss->otherLocs;
+ lss->loc = lss->otherLocs->loc;
+ lss->otherLocs = lss->otherLocs->otherLocs;
+ tmp->loc = NULL;
+ tmp->otherLocs = NULL;
+ LocationSetSet_Term(tmp);
+ LocationSetSet_Delete(tmp);
+ }
+ } else {
+ prev->otherLocs = lss->otherLocs;
+ lss->loc = NULL;
+ lss->otherLocs = NULL;
+ LocationSetSet_Term(lss);
+ LocationSetSet_Delete(lss);
+ }
+ first->count--;
+ return;
+ }
+
+ prev = lss;
+ lss = lss->otherLocs;
+ }
+}
+
+inline void LocationSetSet_RemoveAll(LocationSetSet *lss) {
+#line 2707
+ IRO_ASSERT(lss != NULL);
+
+ while (lss && lss->loc)
+ LocationSetSet_Remove(lss, lss->loc);
+}
+
+inline void LocationSetSet_AddSetAction(LocationSet *ls, void *refcon) {
+#line 2717
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ LocationSetSet_Add((LocationSetSet *) refcon, ls);
+}
+
+inline void LocationSetSet_SimpleAddSetAction(LocationSet *ls, void *refcon) {
+#line 2725
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ LocationSetSet_SimpleAdd((LocationSetSet *) refcon, ls);
+}
+
+inline void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src) {
+#line 2733
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ if (dest->count)
+ LocationSetSet_ForEach(src, LocationSetSet_AddSetAction, dest);
+ else
+ LocationSetSet_ForEach(src, LocationSetSet_SimpleAddSetAction, dest);
+}
+
+inline void LocationSetSet_RemoveSetAction(LocationSet *ls, void *refcon) {
+#line 2744
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ LocationSetSet_Remove((LocationSetSet *) refcon, ls);
+}
+
+inline void LocationSetSet_sub_488700(LocationSetSet *dest, LocationSetSet *src) {
+#line 2752
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ LocationSetSet_ForEach(src, LocationSetSet_RemoveSetAction, dest);
+}
+
+inline Boolean LocationSetSets_Equal(LocationSetSet *lss1, LocationSetSet *lss2) {
+#line 2826
+ IRO_ASSERT(lss1 != NULL);
+ IRO_ASSERT(lss2 != NULL);
+
+ if (lss1 == lss2)
+ return 1;
+ if (LocationSetSet_Count(lss1) != LocationSetSet_Count(lss2))
+ return 0;
+
+ while (lss1 && lss1->loc) {
+ if (!LocationSetSet_Find(lss2, lss1->loc))
+ return 0;
+ lss1 = lss1->otherLocs;
+ }
+
+ return 1;
+}
+
+inline ParamMapping *ParamMapping_New(void) {
+ ParamMapping *pm = IRO_malloc(sizeof(ParamMapping));
+
+#line 2885
+ IRO_ASSERT(pm != NULL);
+#ifdef IRO_DEBUG
+ pm->actual = NULL;
+ pm->formal = NULL;
+ pm->extended = NULL;
+#endif
+ return pm;
+}
+
+inline void ParamMapping_Delete(ParamMapping *pm) {
+#line 2898
+ IRO_ASSERT(pm != NULL);
+ IRO_ASSERT(pm->actual == NULL);
+ IRO_ASSERT(pm->formal == NULL);
+ IRO_ASSERT(pm->extended == NULL);
+ IRO_DEBUG_CLEAR(pm, sizeof(ParamMapping));
+ IRO_free(pm);
+}
+
+inline void ParamMapping_Init_PROBABLY(ParamMapping *pm, IROLinear *actual, Object *formal, ExtendedParam *extended) {
+#line 2911
+ IRO_ASSERT(pm != NULL);
+
+ pm->actual = actual;
+ pm->formal = formal;
+ pm->extended = extended;
+}
+
+inline void ParamMapping_Copy(ParamMapping *dest, ParamMapping *src) {
+#line 2920
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ dest->actual = src->actual;
+ dest->formal = src->formal;
+ dest->extended = src->extended;
+}
+
+inline void ParamMapping_Term(ParamMapping *pm) {
+#line 2933
+ IRO_ASSERT(pm != NULL);
+
+#ifdef IRO_DEBUG
+ pm->actual = NULL;
+ pm->formal = NULL;
+ pm->extended = NULL;
+#endif
+}
+
+inline void ParamMapping_SetExtended(ParamMapping *pm, ExtendedParam *ep) {
+#line 2992
+ IRO_ASSERT(pm != NULL);
+
+ pm->extended = ep;
+}
+
+inline IROLinear *ParamMapping_actual(ParamMapping *pm) {
+#line 2999
+ IRO_ASSERT(pm != NULL);
+
+ return pm->actual;
+}
+
+inline ExtendedParam *ParamMapping_extended(ParamMapping *pm) {
+#line 3011
+ IRO_ASSERT(pm != NULL);
+
+ return pm->extended;
+}
+
+inline ParamMappingFunction *ParamMappingFunction_New(void) {
+ ParamMappingFunction *pmf = IRO_malloc(sizeof(ParamMappingFunction));
+
+#line 3026
+ IRO_ASSERT(pmf != NULL);
+#ifdef IRO_DEBUG
+ pmf->mapping = NULL;
+ pmf->otherMappings = NULL;
+#endif
+ return pmf;
+}
+
+inline void ParamMappingFunction_Delete(ParamMappingFunction *pmf) {
+#line 3039
+ IRO_ASSERT(pmf != NULL);
+ IRO_ASSERT(pmf->mapping == NULL);
+ IRO_ASSERT(pmf->otherMappings == NULL);
+ IRO_DEBUG_CLEAR(pmf, sizeof(ParamMappingFunction));
+ IRO_free(pmf);
+}
+
+inline void ParamMappingFunction_Init(ParamMappingFunction *pmf) {
+#line 3050
+ IRO_ASSERT(pmf != NULL);
+
+ pmf->mapping = NULL;
+ pmf->otherMappings = NULL;
+}
+
+inline void ParamMappingFunction_Copy(ParamMappingFunction *dest, ParamMappingFunction *src) {
+#line 3058
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ dest->mapping = NULL;
+ dest->otherMappings = NULL;
+ ParamMappingFunction_AddAllMaybe_sub_487C50(dest, src);
+}
+
+inline void ParamMappingFunction_Term(ParamMappingFunction *pmf) {
+#line 3068
+ IRO_ASSERT(pmf != NULL);
+
+ ParamMappingFunction_RemoveAll(pmf);
+
+#ifdef IRO_DEBUG
+ pmf->mapping = NULL;
+ pmf->otherMappings = NULL;
+#endif
+}
+
+inline void pmf_sub_487C70(ParamMappingFunction *pmf, void (*action)(ParamMapping *, void *), void *refcon) {
+#line 3111
+ IRO_ASSERT(pmf != NULL);
+ IRO_ASSERT(action != NULL);
+ IRO_ASSERT(refcon == NULL || refcon != NULL);
+
+ while (pmf && pmf->mapping) {
+ action(pmf->mapping, refcon);
+ pmf = pmf->otherMappings;
+ }
+}
+
+inline ParamMapping *ParamMappingFunction_FindMappingByFormal(ParamMappingFunction *pmf, Object *formal) {
+#line 3123
+ IRO_ASSERT(pmf != NULL);
+ IRO_ASSERT(formal != NULL);
+
+ while (pmf && pmf->mapping) {
+ if (pmf->mapping->formal == formal)
+ return pmf->mapping;
+ pmf = pmf->otherMappings;
+ }
+
+ return NULL;
+}
+
+inline void Pmf_Add_sub_486610(ParamMappingFunction *pmf, ParamMapping *mapping) {
+ ParamMapping *existing;
+
+#line 3138
+ IRO_ASSERT(pmf != NULL);
+ IRO_ASSERT(mapping != NULL);
+
+ existing = ParamMappingFunction_FindMappingByFormal(pmf, mapping->formal);
+ if (!existing) {
+ existing = ParamMapping_New();
+ ParamMapping_Copy(existing, mapping);
+ if (pmf->mapping) {
+ ParamMappingFunction *newPMF = ParamMappingFunction_New();
+ ParamMappingFunction_Init(newPMF);
+ newPMF->mapping = pmf->mapping;
+ newPMF->otherMappings = pmf->otherMappings;
+ pmf->otherMappings = newPMF;
+ }
+ pmf->mapping = existing;
+ } else {
+ existing->actual = mapping->actual;
+ existing->extended = mapping->extended;
+ }
+}
+
+inline void ParamMappingFunction_Remove(ParamMappingFunction *pmf, ParamMapping *mapping) {
+ ParamMappingFunction *prev;
+ ParamMappingFunction *tmp;
+
+#line 3170
+ IRO_ASSERT(pmf != NULL);
+ IRO_ASSERT(mapping != NULL);
+
+ prev = NULL;
+ while (pmf && pmf->mapping) {
+ if (pmf->mapping->formal == mapping->formal) {
+ ParamMapping_Term(pmf->mapping);
+ ParamMapping_Delete(pmf->mapping);
+ if (!prev) {
+ if (pmf->otherMappings == NULL) {
+ pmf->mapping = NULL;
+ } else {
+ tmp = pmf->otherMappings;
+ pmf->mapping = pmf->otherMappings->mapping;
+ pmf->otherMappings = pmf->otherMappings->otherMappings;
+ tmp->mapping = NULL;
+ tmp->otherMappings = NULL;
+ ParamMappingFunction_Term(tmp);
+ ParamMappingFunction_Delete(tmp);
+ }
+ } else {
+ prev->otherMappings = pmf->otherMappings;
+ pmf->mapping = NULL;
+ pmf->otherMappings = NULL;
+ ParamMappingFunction_Term(pmf);
+ ParamMappingFunction_Delete(pmf);
+ }
+ return;
+ }
+
+ prev = pmf;
+ pmf = pmf->otherMappings;
+ }
+}
+
+inline void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf) {
+#line 3213
+ IRO_ASSERT(pmf != NULL);
+
+ while (pmf && pmf->mapping)
+ ParamMappingFunction_Remove(pmf, pmf->mapping);
+}
+
+inline void ParamMappingFunction_AddFunctionAction(ParamMapping *mapping, void *refcon) {
+#line 3223
+ IRO_ASSERT(mapping != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ Pmf_Add_sub_486610((ParamMappingFunction *) refcon, mapping);
+}
+
+inline void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src) {
+#line 3231
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ pmf_sub_487C70(src, ParamMappingFunction_AddFunctionAction, dest);
+}
+
+inline PointsToEntry *PointsToEntry_New(void) {
+ PointsToEntry *pte = IRO_malloc(sizeof(PointsToEntry));
+
+#line 3288
+ IRO_ASSERT(pte != NULL);
+#ifdef IRO_DEBUG
+ pte->loc = NULL;
+ pte->locs = NULL;
+#endif
+ return pte;
+}
+
+inline void PointsToEntry_Delete(PointsToEntry *pte) {
+#line 3300
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(pte->loc == NULL);
+ IRO_ASSERT(pte->locs == NULL);
+ IRO_DEBUG_CLEAR(pte, sizeof(PointsToEntry));
+ IRO_free(pte);
+}
+
+inline void PointsToEntry_Init(PointsToEntry *pte, LocationSet *loc, LocationSetSet *locs) {
+#line 3312
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(loc != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(loc));
+ IRO_ASSERT(locs != NULL);
+
+ pte->loc = LocationSet_New();
+ LocationSet_Copy(pte->loc, loc);
+
+ pte->locs = LocationSetSet_New();
+ LocationSetSet_Copy(pte->locs, locs);
+}
+
+inline void PointsToEntry_Copy(PointsToEntry *dest, PointsToEntry *src) {
+#line 3325
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ PointsToEntry_Init(dest, src->loc, src->locs);
+}
+
+inline void PointsToEntry_Term(PointsToEntry *pte) {
+#line 3333
+ IRO_ASSERT(pte != NULL);
+
+ LocationSet_Term(pte->loc);
+ LocationSet_Delete(pte->loc);
+ LocationSetSet_Term(pte->locs);
+ LocationSetSet_Delete(pte->locs);
+
+#ifdef IRO_DEBUG
+ pte->loc = NULL;
+ pte->locs = NULL;
+#endif
+}
+
+inline Boolean PointsToEntries_Equal(PointsToEntry *pte1, PointsToEntry *pte2) {
+#line 3381
+ IRO_ASSERT(pte1 != NULL);
+ IRO_ASSERT(pte2 != NULL);
+
+ if (pte1 == pte2)
+ return 1;
+
+ return LocationSets_Equal(pte1->loc, pte2->loc) && LocationSetSets_Equal(pte1->locs, pte2->locs);
+}
+
+inline LocationSet *PointsToEntry_loc(PointsToEntry *pte) {
+#line 3407
+ IRO_ASSERT(pte != NULL);
+
+ return pte->loc;
+}
+
+inline LocationSetSet *PointsToEntry_locs(PointsToEntry *pte) {
+#line 3414
+ IRO_ASSERT(pte != NULL);
+
+ return pte->locs;
+}
+
+inline PointsToFunction *PointsToFunction_New(void) {
+ PointsToFunction *pointsToFunc = IRO_malloc(sizeof(PointsToFunction));
+
+#line 3430
+ IRO_ASSERT(pointsToFunc != NULL);
+#ifdef IRO_DEBUG
+ pointsToFunc->pte = NULL;
+ pointsToFunc->otherPtes = NULL;
+#endif
+ return pointsToFunc;
+}
+
+inline void PointsToFunction_Delete(PointsToFunction *pointsToFunc) {
+#line 3442
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pointsToFunc->pte == NULL);
+ IRO_ASSERT(pointsToFunc->otherPtes == NULL);
+ IRO_DEBUG_CLEAR(pointsToFunc, sizeof(PointsToFunction));
+ IRO_free(pointsToFunc);
+}
+
+inline void PointsToFunction_Init(PointsToFunction *pointsToFunc) {
+#line 3454
+ IRO_ASSERT(pointsToFunc != NULL);
+
+ pointsToFunc->pte = NULL;
+ pointsToFunc->otherPtes = NULL;
+}
+
+inline void PointsToFunction_Copy(PointsToFunction *dest, PointsToFunction *src) {
+#line 3462
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ dest->pte = NULL;
+ dest->otherPtes = NULL;
+ PointsToFunction_AddAllIGuess_sub_487D80(dest, src);
+}
+
+inline void PointsToFunction_Term(PointsToFunction *pointsToFunc) {
+#line 3472
+ IRO_ASSERT(pointsToFunc != NULL);
+
+ PointsToFunction_RemoveAll(pointsToFunc);
+
+#ifdef IRO_DEBUG
+ pointsToFunc->pte = NULL;
+ pointsToFunc->otherPtes = NULL;
+#endif
+}
+
+inline void PointsToFunction_ForEach(PointsToFunction *pointsToFunc, void (*action)(PointsToEntry *, void *), void *refcon) {
+#line 3515
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(action != NULL);
+ IRO_ASSERT(refcon == NULL || refcon != NULL);
+
+ while (pointsToFunc && pointsToFunc->pte) {
+ action(pointsToFunc->pte, refcon);
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+}
+
+inline PointsToEntry *PointsToFunction_FindByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) {
+#line 3527
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ while (pointsToFunc && pointsToFunc->pte) {
+ if (LocationSets_Equal(pointsToFunc->pte->loc, ls))
+ return pointsToFunc->pte;
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+
+ return NULL;
+}
+
+inline PointsToEntry *PointsToFunction_FindFirst(PointsToFunction *pointsToFunc) {
+#line 3539
+ IRO_ASSERT(pointsToFunc != NULL);
+
+ return pointsToFunc->pte;
+}
+
+inline PointsToEntry *PointsToFunction_FindByLookupCompatibleLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) {
+#line 3546
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(ls != NULL);
+
+ while (pointsToFunc && pointsToFunc->pte) {
+ if (ls->u.known.stride) {
+ if (LocationSets_Equal(pointsToFunc->pte->loc, ls))
+ return pointsToFunc->pte;
+ } else if (LocationSets_LookupCompatible(pointsToFunc->pte->loc, ls)) {
+ return pointsToFunc->pte;
+ }
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+
+ return NULL;
+}
+
+inline PointsToEntry *PointsToFunction_FindContainingLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls, Type *rtype) {
+#line 3565
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(rtype != NULL);
+
+ while (pointsToFunc && pointsToFunc->pte) {
+ if (pointsToFunc->pte->locs->loc && !LocationSet_IsUnknown(pointsToFunc->pte->locs->loc)) {
+ if (!pointsToFunc->pte->locs->otherLocs && LocationSet_Contains(pointsToFunc->pte->loc, pointsToFunc->pte->locs->loc->rtype, ls, rtype))
+ return pointsToFunc->pte;
+ }
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+
+ return NULL;
+}
+
+inline void PointsToFunction_RemoveOverlappingLocations(PointsToFunction *pointsToFunc, PointsToEntry *pte) {
+ Type *rtype1;
+ Type *rtype2;
+ LocationSet *ls;
+ PointsToFunction *prev;
+ PointsToFunction *next;
+ PointsToFunction *tmp;
+
+#line 3601
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(pte->locs != NULL);
+
+ if (pte->locs->loc && pte->locs->loc != stUnknownLs)
+ rtype1 = pte->locs->loc->rtype;
+ else
+ rtype1 = NULL;
+ ls = pte->loc;
+#line 3614
+ IRO_ASSERT(ls != NULL);
+
+ prev = NULL;
+ while (pointsToFunc && pointsToFunc->pte) {
+ next = pointsToFunc->otherPtes;
+ if (pointsToFunc->pte->locs->loc && pointsToFunc->pte->locs->loc != stUnknownLs)
+ rtype2 = pointsToFunc->pte->locs->loc->rtype;
+ else
+ rtype2 = NULL;
+
+ if (LocationSets_Overlap(ls, rtype1, pointsToFunc->pte->loc, rtype2)) {
+ PointsToEntry_Term(pointsToFunc->pte);
+ PointsToEntry_Delete(pointsToFunc->pte);
+ if (!prev) {
+ if (pointsToFunc->otherPtes == NULL) {
+ pointsToFunc->pte = NULL;
+ prev = pointsToFunc;
+ } else {
+ tmp = pointsToFunc->otherPtes;
+ pointsToFunc->pte = pointsToFunc->otherPtes->pte;
+ pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes;
+ tmp->pte = NULL;
+ tmp->otherPtes = NULL;
+ PointsToFunction_Term(tmp);
+ PointsToFunction_Delete(tmp);
+ prev = NULL;
+ next = pointsToFunc;
+ }
+ } else {
+ prev->otherPtes = pointsToFunc->otherPtes;
+ pointsToFunc->pte = NULL;
+ pointsToFunc->otherPtes = NULL;
+ PointsToFunction_Term(pointsToFunc);
+ PointsToFunction_Delete(pointsToFunc);
+ prev = pointsToFunc;
+ }
+ }
+
+ pointsToFunc = next;
+ }
+}
+
+inline Boolean ShouldAddNewPointsToEntryToFunction(PointsToFunction *pointsToFunc, PointsToEntry *pte) {
+ Boolean flag;
+ Boolean isKnown;
+ SInt32 stride;
+ PointsToFunction *next;
+ LocationSet *loc;
+ LocationSet *loc2;
+ Type *rtype1;
+ Type *rtype2;
+ LocationSetSet *locs2;
+ LocationSet *tmp;
+ LocationSet *unknown;
+ Boolean flag2;
+ Boolean flag3;
+
+#line 3675
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(pte->locs != NULL);
+ IRO_ASSERT(PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc) == NULL);
+ IRO_ASSERT((unknown = LocationSetSet_FindFirst(pte->locs)) != NULL);
+ IRO_ASSERT(LocationSet_IsUnknown(unknown));
+ IRO_ASSERT(LocationSet_bitfieldOf(unknown) == NULL);
+ IRO_ASSERT(LocationSet_restriction(unknown) == NULL);
+
+ if (pte->locs->loc && pte->locs->loc != stUnknownLs)
+ rtype1 = pte->locs->loc->rtype;
+ else
+ rtype1 = NULL;
+
+ loc = pte->loc;
+#line 3693
+ IRO_ASSERT(loc != NULL);
+
+ isKnown = !LocationSet_IsUnknown(loc);
+ if (isKnown)
+ stride = LocationSet_stride(loc);
+
+ flag = 0;
+ while (pointsToFunc && pointsToFunc->pte) {
+ next = pointsToFunc->otherPtes;
+
+ locs2 = pointsToFunc->pte->locs;
+
+ if (locs2->loc && locs2->loc != stUnknownLs)
+ rtype2 = locs2->loc->rtype;
+ else
+ rtype2 = NULL;
+
+ loc2 = pointsToFunc->pte->loc;
+
+ flag2 = !(tmp = LocationSetSet_FindFirst(locs2)) ||
+ !LocationSet_IsUnknown(tmp) ||
+ LocationSet_bitfieldOf(tmp) ||
+ LocationSet_restriction(tmp);
+
+ flag3 = LocationSets_Overlap(loc, rtype1, loc2, rtype2);
+
+ if (!flag && flag3)
+ flag = 1;
+
+ if (flag3 && (flag2 || (isKnown && stride && LocationSet_stride(loc2) == 0)))
+ return 1;
+
+ pointsToFunc = next;
+ }
+
+ return !flag;
+}
+
+inline Boolean PointsToFunction_SimpleAdd(PointsToFunction *pointsToFunc, PointsToEntry *pte) {
+ PointsToEntry *newPTE;
+
+#line 3741
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pte != NULL);
+
+ newPTE = PointsToEntry_New();
+ PointsToEntry_Copy(newPTE, pte);
+ if (pointsToFunc->pte) {
+ PointsToFunction *newPointsToFunc = PointsToFunction_New();
+ PointsToFunction_Init(newPointsToFunc);
+ newPointsToFunc->pte = pointsToFunc->pte;
+ newPointsToFunc->otherPtes = pointsToFunc->otherPtes;
+ pointsToFunc->otherPtes = newPointsToFunc;
+ }
+ pointsToFunc->pte = newPTE;
+ return 1;
+}
+
+inline Boolean PointsToFunction_Add(PointsToFunction *pointsToFunc, PointsToEntry *pte) {
+#line 3766
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pte != NULL);
+
+ if (!PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc)) {
+ LocationSet *ls;
+ if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) ||
+ LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) {
+ PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte);
+ if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype)
+ PointsToFunction_SimpleAdd(pointsToFunc, pte);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+inline Boolean PointsToFunction_AddWithoutChecking(PointsToFunction *pointsToFunc, PointsToEntry *pte) {
+ LocationSet *ls;
+
+#line 3793
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(pte != NULL);
+
+ if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) ||
+ LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) {
+ PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte);
+ if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype)
+ PointsToFunction_SimpleAdd(pointsToFunc, pte);
+ return 1;
+ }
+
+ return 0;
+}
+
+inline void PointsToFunction_RemoveByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) {
+ PointsToFunction *prev;
+ PointsToFunction *tmp;
+
+#line 3170
+ IRO_ASSERT(pointsToFunc != NULL);
+ IRO_ASSERT(ls != NULL);
+ IRO_ASSERT(!LocationSet_IsUnknown(ls));
+
+ prev = NULL;
+ while (pointsToFunc && pointsToFunc->pte) {
+ if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) {
+ PointsToEntry_Term(pointsToFunc->pte);
+ PointsToEntry_Delete(pointsToFunc->pte);
+ if (!prev) {
+ if (pointsToFunc->otherPtes == NULL) {
+ pointsToFunc->pte = NULL;
+ } else {
+ tmp = pointsToFunc->otherPtes;
+ pointsToFunc->pte = pointsToFunc->otherPtes->pte;
+ pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes;
+ tmp->pte = NULL;
+ tmp->otherPtes = NULL;
+ PointsToFunction_Term(tmp);
+ PointsToFunction_Delete(tmp);
+ }
+ } else {
+ prev->otherPtes = pointsToFunc->otherPtes;
+ pointsToFunc->pte = NULL;
+ pointsToFunc->otherPtes = NULL;
+ PointsToFunction_Term(pointsToFunc);
+ PointsToFunction_Delete(pointsToFunc);
+ }
+ return;
+ }
+
+ prev = pointsToFunc;
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+}
+
+inline void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc) {
+#line 3862
+ IRO_ASSERT(pointsToFunc != NULL);
+
+ while (pointsToFunc && pointsToFunc->pte)
+ PointsToFunction_RemoveByLocationSet(pointsToFunc, pointsToFunc->pte->loc);
+}
+
+inline void PointsToFunction_AddFunctionAction(PointsToEntry *pte, void *refcon) {
+#line 3872
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ PointsToFunction_Add((PointsToFunction *) refcon, pte);
+}
+
+inline void PointsToFunction_SimpleAddFunctionAction(PointsToEntry *pte, void *refcon) {
+#line 3880
+ IRO_ASSERT(pte != NULL);
+ IRO_ASSERT(refcon != NULL);
+
+ PointsToFunction_SimpleAdd((PointsToFunction *) refcon, pte);
+}
+
+inline void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src) {
+#line 3888
+ IRO_ASSERT(dest != NULL);
+ IRO_ASSERT(src != NULL);
+
+ if (dest->pte)
+ PointsToFunction_ForEach(src, PointsToFunction_AddFunctionAction, dest);
+ else
+ PointsToFunction_ForEach(src, PointsToFunction_SimpleAddFunctionAction, dest);
+}
+
+inline void PointsToFunction_SortByExtendedParamNum(PointsToFunction *pointsToFunc) {
+ UInt32 value1;
+ UInt32 value2;
+ PointsToFunction *scan;
+
+ while (pointsToFunc && pointsToFunc->pte) {
+ value1 = 0;
+ if (pointsToFunc->pte->loc && pointsToFunc->pte->loc->block) {
+ PAMemoryBlock *block = pointsToFunc->pte->loc->block;
+ if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) {
+ value1 = 2 * (block->u.ep->x4) + 1;
+ } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) {
+ if (block->u.localvar->x0 && block->u.localvar->x0->extParam)
+ value1 = 2 * block->u.localvar->x0->extParam->x4;
+ }
+ }
+
+ for (scan = pointsToFunc->otherPtes; scan && scan->pte; scan = scan->otherPtes) {
+ value2 = 0;
+ if (scan->pte->loc && scan->pte->loc->block) {
+ PAMemoryBlock *block = scan->pte->loc->block;
+ if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) {
+ value2 = 2 * (block->u.ep->x4) + 1;
+ } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) {
+ if (block->u.localvar->x0 && block->u.localvar->x0->extParam)
+ value2 = 2 * block->u.localvar->x0->extParam->x4;
+ }
+ }
+
+ if (value2 < value1) {
+ LocationSet *saveloc;
+ LocationSetSet *savelocs;
+ saveloc = pointsToFunc->pte->loc;
+ savelocs = pointsToFunc->pte->locs;
+ pointsToFunc->pte->loc = scan->pte->loc;
+ pointsToFunc->pte->locs = scan->pte->locs;
+ scan->pte->loc = saveloc;
+ scan->pte->locs = savelocs;
+ }
+ }
+
+ pointsToFunc = pointsToFunc->otherPtes;
+ }
+}
+
+inline Boolean PointsToFunctions_Equal(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) {
+ PointsToFunction *scan;
+ PointsToEntry *pte;
+
+#line 3968
+ IRO_ASSERT(pointsToFunc1 != NULL);
+ IRO_ASSERT(pointsToFunc2 != NULL);
+
+ if (pointsToFunc1 == pointsToFunc2)
+ return 1;
+
+ for (scan = pointsToFunc1; scan && scan->pte; scan = scan->otherPtes) {
+ pte = PointsToFunction_FindByLocationSet(pointsToFunc2, scan->pte->loc);
+ if (!pte || !PointsToEntries_Equal(pte, scan->pte))
+ return 0;
+ }
+
+ for (scan = pointsToFunc2; scan && scan->pte; scan = scan->otherPtes) {
+ pte = PointsToFunction_FindByLocationSet(pointsToFunc1, scan->pte->loc);
+ if (!pte || !PointsToEntries_Equal(pte, scan->pte))
+ return 0;
+ }
+
+ return 1;
+}
+
+inline Boolean PointsToFunctions_Match(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) {
+ return 1;
+}
+
+inline PartialTransferFunction *PartialTransferFunction_New() {
+ PartialTransferFunction *ptf = IRO_malloc(sizeof(PartialTransferFunction));
+
+#line 4110
+ IRO_ASSERT(ptf != NULL);
+#ifdef IRO_DEBUG
+ ptf->initialPointsToFn = NULL;
+ ptf->finalPointsToFn = NULL;
+ ptf->funcModifies = NULL;
+ ptf->context.nd = NULL;
+ ptf->context.ptf = NULL;
+ ptf->returnLocation = NULL;
+#endif
+ return ptf;
+}
+
+inline void PartialTransferFunction_Delete(PartialTransferFunction *ptf) {
+#line 4126
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(ptf->initialPointsToFn == NULL);
+ IRO_ASSERT(ptf->finalPointsToFn == NULL);
+ IRO_ASSERT(ptf->funcModifies == NULL);
+ IRO_ASSERT(ptf->context.nd == NULL);
+ IRO_ASSERT(ptf->context.ptf == NULL);
+ IRO_ASSERT(ptf->returnLocation == NULL);
+ IRO_DEBUG_CLEAR(ptf, sizeof(PartialTransferFunction));
+ IRO_free(ptf);
+}
+
+inline void PartialTransferFunction_Init(PartialTransferFunction *ptf, IROLinear *contextNd, PartialTransferFunction *contextPTF) {
+#line 4142
+ IRO_ASSERT(ptf != NULL);
+ IRO_ASSERT(contextNd != NULL);
+ IRO_ASSERT(contextPTF != NULL);
+
+ ptf->initialPointsToFn = PointsToFunction_New();
+ PointsToFunction_Init(ptf->initialPointsToFn);
+ ptf->finalPointsToFn = PointsToFunction_New();
+ PointsToFunction_Init(ptf->finalPointsToFn);
+
+ ptf->funcModifies = LocationSetSet_New();
+ LocationSetSet_Init(ptf->funcModifies);
+ LocationSetSet_AddUnknown(ptf->funcModifies, NULL, NULL, NULL);
+
+ ptf->returnLocation = NULL;
+ ptf->x10 = 0;
+
+ ptf->context.nd = contextNd;
+ ptf->context.ptf = contextPTF;
+}
+
+inline void PartialTransferFunction_Copy(PartialTransferFunction *dest, PartialTransferFunction *src) {
+#line 4164
+ IRO_ASSERT(src != NULL);
+ IRO_ASSERT(dest != NULL);
+
+ dest->initialPointsToFn = PointsToFunction_New();
+ PointsToFunction_Copy(dest->initialPointsToFn, src->initialPointsToFn);
+ dest->finalPointsToFn = PointsToFunction_New();
+ PointsToFunction_Copy(dest->finalPointsToFn, src->finalPointsToFn);
+
+ dest->funcModifies = LocationSetSet_New();
+ LocationSetSet_Copy(dest->funcModifies, src->funcModifies);
+
+ if (src->returnLocation) {
+ dest->returnLocation = LocationSet_New();
+ LocationSet_Copy(dest->returnLocation, src->returnLocation);
+ } else {
+ dest->returnLocation = NULL;
+ }
+
+ dest->x10 = src->x10;
+ dest->context = src->context;
+}
+
+inline void PartialTransferFunction_Term(PartialTransferFunction *ptf) {
+#line 4190
+ IRO_ASSERT(ptf != NULL);
+
+ PointsToFunction_Term(ptf->initialPointsToFn);
+ PointsToFunction_Delete(ptf->initialPointsToFn);
+ PointsToFunction_Term(ptf->finalPointsToFn);
+ PointsToFunction_Delete(ptf->finalPointsToFn);
+ LocationSetSet_Term(ptf->funcModifies);
+ LocationSetSet_Delete(ptf->funcModifies);
+
+ if (ptf->returnLocation) {
+ PAMemoryBlock_Term(ptf->returnLocation->block);
+ PAMemoryBlock_Delete(ptf->returnLocation->block);
+ LocationSet_Term(ptf->returnLocation);
+ LocationSet_Delete(ptf->returnLocation);
+ ptf->returnLocation = NULL;
+ }
+
+#ifdef IRO_DEBUG
+ ptf->initialPointsToFn = NULL;
+ ptf->finalPointsToFn = NULL;
+ ptf->funcModifies = NULL;
+ ptf->context.nd = NULL;
+ ptf->context.ptf = NULL;
+#endif
+}
+
+inline PointsToFunction *PartialTransferFunction_initialPointsToFn(PartialTransferFunction *ptf) {
+#line 4221
+ IRO_ASSERT(ptf != NULL);
+
+ return ptf->initialPointsToFn;
+}
+
+inline PointsToFunction *PartialTransferFunction_finalPointsToFn(PartialTransferFunction *ptf) {
+#line 4227
+ IRO_ASSERT(ptf != NULL);
+
+ return ptf->finalPointsToFn;
+}
+
+inline LocationSetSet *PTF_sub_48D750(PartialTransferFunction *ptf) {
+#line 4233
+ IRO_ASSERT(ptf != NULL);
+
+ return ptf->funcModifies;
+}
+
+inline LocationSet *PartialTransferFunction_returnLocation(PartialTransferFunction *ptf) {
+#line 4249
+ IRO_ASSERT(ptf != NULL);
+
+ if (!ptf->returnLocation) {
+ PAMemoryBlock *block;
+ LocationSet *ls;
+
+ block = PAMemoryBlock_New();
+ PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, NULL);
+ ls = LocationSet_New();
+ LocationSet_InitKnown(ls, block, cint64_zero, 0, TYPE(&void_ptr));
+ ptf->returnLocation = ls;
+ }
+
+ return ptf->returnLocation;
+}
+
+inline IROLinear *PTF_sub_48B980(PartialTransferFunction *ptf) {
+#line 4265
+ IRO_ASSERT(ptf != NULL);
+
+ return ptf->context.nd;
+}
+
+inline PartialTransferFunction *PTF_sub_48B970(PartialTransferFunction *ptf) {
+#line 4271
+ IRO_ASSERT(ptf != NULL);
+
+ return ptf->context.ptf;
+}
+
+inline void PartialTransferFunction_sub_48A610(PartialTransferFunction *ptf, Boolean value) {
+#line 4298
+ IRO_ASSERT(ptf != NULL);
+
+ ptf->x10 = (value != 0) ? 1 : 0;
+}
+
+inline PTFList *PTFList_New(void) {
+ PTFList *ptfList = IRO_malloc(sizeof(PTFList));
+
+#line 4393
+ IRO_ASSERT(ptfList != NULL);
+#ifdef IRO_DEBUG
+ ptfList->ptf = NULL;
+ ptfList->otherPTFs = NULL;
+#endif
+ return ptfList;
+}
+
+inline void PTFList_Delete(PTFList *ptfList) {
+#line 4405
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(ptfList->ptf == NULL);
+ IRO_ASSERT(ptfList->otherPTFs == NULL);
+ IRO_DEBUG_CLEAR(ptfList, sizeof(PTFList));
+ IRO_free(ptfList);
+}
+
+inline void PTFList_Init(PTFList *ptfList) {
+#line 4417
+ IRO_ASSERT(ptfList != NULL);
+
+ ptfList->ptf = NULL;
+ ptfList->otherPTFs = NULL;
+}
+
+inline void PTFList_Term(PTFList *ptfList) {
+#line 4435
+ IRO_ASSERT(ptfList != NULL);
+
+ PTFList_RemoveAll(ptfList);
+
+#ifdef IRO_DEBUG
+ ptfList->ptf = NULL;
+ ptfList->otherPTFs = NULL;
+#endif
+}
+
+inline void PTFList_ForEach(PTFList *ptfList, void (*action)(PartialTransferFunction *, void *), void *refcon) {
+#line 4478
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(action != NULL);
+ IRO_ASSERT(refcon == NULL || refcon != NULL);
+
+ while (ptfList && ptfList->ptf) {
+ action(ptfList->ptf, refcon);
+ ptfList = ptfList->otherPTFs;
+ }
+}
+
+inline PartialTransferFunction *PTFList_sub_48A0F0(PTFList *ptfList, PartialTransferFunction *ptf) {
+#line 4490
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ while (ptfList && ptfList->ptf) {
+ if (ptfList->ptf == ptf)
+ return ptfList->ptf;
+
+ ptfList = ptfList->otherPTFs;
+ }
+
+ return NULL;
+}
+
+inline PartialTransferFunction *PTFList_FindFirst(PTFList *ptfList) {
+#line 4502
+ IRO_ASSERT(ptfList != NULL);
+
+ return ptfList->ptf;
+}
+
+inline void PTFList_sub_48A080(PTFList *ptfList, PartialTransferFunction *ptf) {
+#line 4511
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ if (ptfList->ptf) {
+ PTFList *newList = PTFList_New();
+ PTFList_Init(newList);
+ newList->ptf = ptfList->ptf;
+ newList->otherPTFs = ptfList->otherPTFs;
+ ptfList->otherPTFs = newList;
+ }
+
+ ptfList->ptf = ptf;
+}
+
+inline void PTFList_sub_48A050(PTFList *ptfList, PartialTransferFunction *ptf) {
+#line 4529
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ if (!PTFList_sub_48A0F0(ptfList, ptf))
+ PTFList_sub_48A080(ptfList, ptf);
+}
+
+inline void PTFList_Remove(PTFList *ptfList, PartialTransferFunction *ptf) {
+ PTFList *prev;
+ PTFList *tmp;
+
+#line 4542
+ IRO_ASSERT(ptfList != NULL);
+ IRO_ASSERT(ptf != NULL);
+
+ prev = NULL;
+ while (ptfList && ptfList->ptf) {
+ if (ptfList->ptf == ptf) {
+ if (!prev) {
+ if (ptfList->otherPTFs == NULL) {
+ ptfList->ptf = NULL;
+ } else {
+ tmp = ptfList->otherPTFs;
+ ptfList->ptf = ptfList->otherPTFs->ptf;
+ ptfList->otherPTFs = ptfList->otherPTFs->otherPTFs;
+ tmp->ptf = NULL;
+ tmp->otherPTFs = NULL;
+ PTFList_Term(tmp);
+ PTFList_Delete(tmp);
+ }
+ } else {
+ prev->otherPTFs = ptfList->otherPTFs;
+ ptfList->ptf = NULL;
+ ptfList->otherPTFs = NULL;
+ PTFList_Term(ptfList);
+ PTFList_Delete(ptfList);
+ }
+ return;
+ }
+
+ prev = ptfList;
+ ptfList = ptfList->otherPTFs;
+ }
+}
+
+inline void PTFList_RemoveAll(PTFList *ptfList) {
+#line 4582
+ IRO_ASSERT(ptfList != NULL);
+
+ while (ptfList && ptfList->ptf)
+ PTFList_Remove(ptfList, ptfList->ptf);
+}
diff --git a/compiler_and_linker/unsorted/IroPropagate.c b/compiler_and_linker/unsorted/IroPropagate.c
index e69de29..ebcbb56 100644
--- a/compiler_and_linker/unsorted/IroPropagate.c
+++ b/compiler_and_linker/unsorted/IroPropagate.c
@@ -0,0 +1,595 @@
+#include "compiler/IroPropagate.h"
+#include "compiler/IroCSE.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroEval.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IROUseDef.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/objects.h"
+#include "compiler/CExpr.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CParser.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+
+IROAssign *IRO_FirstAssign;
+IROAssign *IRO_LastAssign;
+SInt32 IRO_NumAssign;
+
+static Boolean VarIsUsedInOtherFNodes(VarRecord *var, IRONode *node) {
+ if (var->defs && var->uses) {
+ IROUse *use;
+ IRODef *def = NULL;
+ for (use = var->uses; use; use = use->varnext) {
+ if (!def && use->node == node && use->linear && !(use->linear->flags & IROLF_Assigned)) {
+ for (def = var->defs; def; def = def->varnext) {
+ if (Bv_IsBitSet(def->index, use->x18))
+ break;
+ }
+ }
+ }
+
+ if (def) {
+ for (use = var->uses; use; use = use->varnext) {
+ if (use->node != node && use->linear && !(use->linear->flags & IROLF_Assigned)) {
+ if (Bv_IsBitSet(def->index, use->x18))
+ return 1;
+ }
+ }
+ }
+ } else {
+ IROLinear *linear;
+ IRONode *scan;
+ for (scan = IRO_FirstNode; scan; scan = scan->nextnode) {
+ if (scan != node) {
+ linear = scan->first;
+ while (1) {
+ if (!linear)
+ break;
+
+ if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
+ if (IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1) == var)
+ return 1;
+ }
+
+ if (linear == scan->last)
+ break;
+ linear = linear->next;
+ }
+ }
+ }
+ IRO_CheckForUserBreak();
+ }
+
+ return 0;
+}
+
+static void GetExprUses(IROLinear *linear, Boolean isFirst) {
+ if (isFirst && IS_LINEAR_ENODE(linear, EOBJREF)) {
+ Object *obj = linear->u.node->data.objref;
+ if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) {
+ VarRecord *var = IRO_FindVar(obj, 0, 1);
+ if (var)
+ Bv_SetBit(var->index, IRO_VarKills);
+ }
+ }
+}
+
+static void GetExprKills(IROLinear *linear, Boolean isFirst) {
+ if (isFirst)
+ IRO_GetKills(linear);
+}
+
+static void CheckUnorderedRegionForDefs(IROLinear *linear, BitVector *a, BitVector *b, Boolean *flag) {
+ Bv_Clear(a);
+ Bv_Clear(IRO_VarKills);
+ IRO_WalkTree(linear, GetExprKills);
+ Bv_Or(IRO_VarKills, a);
+ if (Bv_BitsInCommon(a, b))
+ *flag = 1;
+}
+
+static void CheckUnorderedRegionsForDefs(IROLinear *linear1, IROLinear *linear2, BitVector *a, BitVector *b, Boolean *flag) {
+ int i;
+
+ switch (linear1->type) {
+ case IROLinearOp2Arg:
+ if (linear1->nodetype == ELAND) break;
+ if (linear1->nodetype == ELOR) break;
+ if (linear1->nodetype == ECOMMA) break;
+ if (linear1->u.diadic.left != linear2)
+ CheckUnorderedRegionForDefs(linear1->u.diadic.left, a, b, flag);
+ if (linear1->u.diadic.right != linear2)
+ CheckUnorderedRegionForDefs(linear1->u.diadic.right, a, b, flag);
+ break;
+ case IROLinearFunccall:
+ if (linear1->u.funccall.linear8 != linear2)
+ CheckUnorderedRegionForDefs(linear1->u.funccall.linear8, a, b, flag);
+ for (i = 0; !*flag && i < linear1->u.funccall.argCount; i++) {
+ if (linear1->u.funccall.args[i] != linear2)
+ CheckUnorderedRegionForDefs(linear1->u.funccall.args[i], a, b, flag);
+ }
+ break;
+ }
+}
+
+static Boolean PropagationHasDefsInUnorderedRegions(IROLinear *a, IROLinear *b) {
+ Boolean flag;
+ IROLinear *father;
+ BitVector *bv1;
+ BitVector *bv2;
+ VarRecord *var;
+
+ flag = 0;
+ if ((father = IRO_LocateFather(a))) {
+ Bv_AllocVector(&bv1, IRO_NumVars + 1);
+ Bv_AllocVector(&bv2, IRO_NumVars + 1);
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ IRO_WalkTree(b, GetExprUses);
+ Bv_Or(IRO_VarKills, bv2);
+ var = IRO_FindVar(a->u.diadic.left->u.node->data.objref, 0, 1);
+ Bv_SetBit(var->index, bv2);
+ while (father && !flag) {
+ CheckUnorderedRegionsForDefs(father, a, bv1, bv2, &flag);
+ a = father;
+ father = IRO_LocateFather(father);
+ }
+ }
+
+ return flag;
+}
+
+int IRO_IsRegable(Object *obj) {
+ if (obj->datatype == DLOCAL && obj->u.var.info)
+ return obj->u.var.info->noregister == 0;
+ return 0;
+}
+
+static Boolean IsPropagatable(IROLinear *linear) {
+ Object *obj;
+ Object *obj2;
+
+ if (IS_LINEAR_DIADIC(linear, EASS) && (obj = IRO_IsVariable(linear->u.diadic.left)) && obj->type == linear->rtype && !is_volatile_object(obj)) {
+ if (linear->u.diadic.left->flags & IROLF_BitfieldIndirect) {
+ if (!IRO_IsConstant(linear->u.diadic.right))
+ return 0;
+ else
+ return 1;
+ }
+
+ if (IRO_IsConstant(linear->u.diadic.right))
+ return 1;
+
+ if ((obj2 = IRO_IsVariable(linear->u.diadic.right)) && !is_volatile_object(obj2) && IRO_TypesEqual(obj->type, linear->rtype)) {
+ if (!Inline_IsObjectData(linear->u.diadic.right->u.monadic->u.node->data.objref)) {
+ if (IRO_IsRegable(obj) && !IRO_IsRegable(obj2))
+ return 0;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static Boolean IsIntGenKillCandidate(IROLinear *linear) {
+ if (linear->type == IROLinearFunccall)
+ return 1;
+
+ if (IRO_IsAssignOp[linear->nodetype] && (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg))
+ return 1;
+
+ if (linear->type == IROLinearAsm)
+ return 1;
+
+ return 0;
+}
+
+static Boolean IsPropagatableExpr(IROLinear *linear, IROList *list) {
+ Object *obj;
+ if (IS_LINEAR_DIADIC(linear, EASS) && !(linear->flags & IROLF_Reffed)) {
+ if ((obj = IRO_IsVariable(linear->u.diadic.left)) && !is_volatile_object(obj) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) {
+ if (!IRO_IsRegable(obj))
+ return 0;
+ if (IS_LINEAR_ENODE(linear->u.diadic.right, ESTRINGCONST))
+ return 0;
+
+ IRO_FindDepends(linear->u.diadic.right);
+ if (!IRO_NotSubable)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void ClearAvailibilityOnNode(IRONode *node, UInt32 bit) {
+ IRONode *scan;
+
+ for (scan = node->nextnode; scan; scan = scan->nextnode)
+ Bv_ClearBit(bit, scan->x16);
+}
+
+Boolean IRO_CopyAndConstantPropagation(void) {
+ IROAssign *ass2;
+ IROAssign *ass;
+ IROLinear *linear;
+ IRONode *node;
+ VarRecord *var;
+ BitVector *bv;
+ Boolean flag;
+ Boolean result;
+
+ IRO_FirstAssign = NULL;
+ IRO_NumAssign = 0;
+ result = 0;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ linear = node->first;
+ while (1) {
+ if (!linear)
+ break;
+
+ if (IsPropagatable(linear) && (var = IRO_FindAssigned(linear))) {
+ IROAssign *newass;
+ IRO_Dump("Found propagatable assignment at: %d\n", linear->index);
+ newass = oalloc(sizeof(IROAssign));
+ newass->linear = linear;
+ newass->next = NULL;
+ newass->index = ++IRO_NumAssign;
+ newass->varIndex = var->index;
+ newass->linear2 = linear->u.diadic.right;
+ newass->var = NULL;
+ newass->varObj = IRO_IsVariable(linear->u.diadic.right);
+ newass->node = node;
+ if (newass->varObj)
+ newass->var = IRO_FindVar(newass->varObj, 0, 1);
+ if (!IRO_FirstAssign)
+ IRO_FirstAssign = newass;
+ else
+ IRO_LastAssign->next = newass;
+ IRO_LastAssign = newass;
+ }
+
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+
+ node = IRO_FirstNode;
+ ass = IRO_FirstAssign;
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+ while (node) {
+ Bv_AllocVector(&node->x16, IRO_NumAssign);
+ if (node != IRO_FirstNode)
+ Bv_Set(node->x16);
+ Bv_AllocVector(&node->x22, IRO_NumAssign);
+ Bv_AllocVector(&node->x1E, IRO_NumAssign);
+ Bv_AllocVector(&node->x2A, IRO_NumAssign);
+ node->x1A = NULL;
+
+ linear = node->first;
+ while (1) {
+ if (!linear)
+ break;
+
+ if (IsIntGenKillCandidate(linear)) {
+ //IROAssign *ass2;
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(linear);
+
+ for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
+ if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) {
+ Bv_SetBit(ass2->index, node->x22);
+ Bv_ClearBit(ass2->index, node->x1E);
+ }
+ if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) {
+ Bv_SetBit(ass2->index, node->x22);
+ Bv_ClearBit(ass2->index, node->x1E);
+ }
+ }
+ }
+
+ while (ass && ass->linear == linear) {
+ Bv_SetBit(ass->index, node->x1E);
+ ass = ass->next;
+ }
+
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+
+ Bv_Copy(node->x16, node->x2A);
+ Bv_Minus(node->x22, node->x2A);
+ Bv_Or(node->x1E, node->x2A);
+ node = node->nextnode;
+ }
+
+ IRO_CheckForUserBreak();
+
+ Bv_AllocVector(&bv, IRO_NumAssign);
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node == IRO_FirstNode) {
+ Bv_Clear(bv);
+ } else {
+ UInt16 i;
+ Bv_Set(bv);
+ for (i = 0; i < node->numpred; i++)
+ Bv_And(IRO_NodeTable[node->pred[i]]->x2A, bv);
+ }
+
+ if (!Bv_Compare(bv, node->x16)) {
+ flag = 1;
+ Bv_Copy(bv, node->x16);
+ }
+
+ Bv_Copy(node->x16, node->x2A);
+ Bv_Minus(node->x22, node->x2A);
+ Bv_Or(node->x1E, node->x2A);
+ }
+ } while (flag);
+
+ IRO_CheckForUserBreak();
+
+ node = IRO_FirstNode;
+ ass = IRO_FirstAssign;
+ while (node) {
+ IRO_Avail = node->x16;
+ linear = node->first;
+ while (1) {
+ if (!linear)
+ break;
+
+ if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
+ if ((var = IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1))) {
+ //IROAssign *ass2;
+ for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
+ if (
+ ass2->varIndex == var->index &&
+ Bv_IsBitSet(ass2->index, IRO_Avail) &&
+ (IRO_IsConstant(ass2->linear2) || node->loopdepth <= ass2->node->loopdepth) &&
+ !PropagationHasDefsInUnorderedRegions(linear, ass2->linear2)
+ ) {
+ if (ass2->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass2->linear->u.diadic.left->rtype)) {
+ ENode *enode = IRO_NewENode(ass2->linear2->u.node->type);
+ *enode = *ass2->linear2->u.node;
+ if (enode->type == EINTCONST) {
+ if (linear->flags & IROLF_BitfieldIndirect) {
+ IRO_TruncateBitfieldValueToType(&enode->data.intval, linear->rtype, var->x1A);
+ enode->rtype = linear->rtype;
+ result = 1;
+ } else {
+ IRO_TruncateValueToType(&enode->data.intval, linear->rtype);
+ enode->rtype = linear->rtype;
+ }
+ }
+ linear->u.monadic->type = IROLinearNop;
+ linear->type = IROLinearOperand;
+ linear->u.node = enode;
+ } else if (ass2->varObj && IRO_is_CPtypeequal(linear->rtype, ass2->linear->rtype)) {
+ linear->u.diadic.left->u.node = create_objectrefnode(ass2->varObj);
+ if (ass2->linear2->flags & IROLF_BitfieldIndirect)
+ linear->flags |= IROLF_BitfieldIndirect;
+ }
+ IRO_Dump("Found propagation at %d from %d\n", linear->index, ass2->linear->index);
+ break;
+ }
+ }
+ }
+ } else if (linear->type == IROLinearAsm) {
+ IAEffects effects;
+ int i;
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+
+ for (i = 0; i < effects.numoperands; i++) {
+ if (effects.operands[i].type == IAEffect_0 && effects.operands[i].offset == 0 && effects.operands[i].object->type->size == effects.operands[i].size) {
+ if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) {
+ //IROAssign *ass2;
+ 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) {
+ enode = create_objectrefnode(ass2->varObj);
+ } else if (ass2->linear2->type == IROLinearOperand) {
+ enode = ass2->linear2->u.node;
+ } else {
+#line 768
+ CError_FATAL();
+ }
+ CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (IsIntGenKillCandidate(linear)) {
+ //IROAssign *ass2;
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(linear);
+
+ for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) {
+ if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) {
+ Bv_ClearBit(ass2->index, IRO_Avail);
+ }
+ if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) {
+ Bv_ClearBit(ass2->index, IRO_Avail);
+ }
+ }
+
+ while (ass && ass->linear == linear) {
+ Bv_SetBit(ass->index, IRO_Avail);
+ ass = ass->next;
+ }
+ }
+
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+ node = node->nextnode;
+ }
+
+ IRO_CheckForUserBreak();
+
+ return result;
+}
+
+void IRO_ExpressionPropagation(void) {
+ IRONode *node;
+ IROLinear *linear;
+ Object *obj;
+ VarRecord *var;
+ IROAssign *ass;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ IRO_FirstAssign = NULL;
+ IRO_LastAssign = NULL;
+ IRO_NumAssign = 0;
+
+ linear = node->first;
+ while (1) {
+ IROList list;
+ if (!linear)
+ break;
+
+ IRO_InitList(&list);
+ if (IsPropagatableExpr(linear, &list)) {
+ if ((var = IRO_FindAssigned(linear))) {
+ IRO_Dump("Found propagatable expression assignment at: %d\n", linear->index);
+ ass = oalloc(sizeof(IROAssign));
+ ass->linear = linear;
+ ass->next = NULL;
+ ass->index = ++IRO_NumAssign;
+ ass->varIndex = var->index;
+ ass->linear2 = linear->u.diadic.right;
+ ass->x20 = 0;
+ ass->node = node;
+ IRO_FindDepends(linear->u.diadic.right);
+ ass->depends = IRO_Depends;
+ if (!IRO_FirstAssign) {
+ IRO_FirstAssign = ass;
+ ass->prev = NULL;
+ } else {
+ IRO_LastAssign->next = ass;
+ ass->prev = IRO_LastAssign;
+ }
+ IRO_LastAssign = ass;
+ }
+ }
+
+ if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
+ if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) {
+ for (ass = IRO_LastAssign; ass; ass = ass->prev) {
+ if (ass->varIndex == var->index)
+ ass->x20++;
+ }
+ }
+ }
+
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+
+ Bv_AllocVector(&IRO_Avail, IRO_NumAssign);
+
+ linear = node->first;
+ while (1) {
+ if (!linear)
+ break;
+
+ if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) {
+ if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) {
+ for (ass = IRO_LastAssign; ass; ass = ass->next) {
+ if (ass->varIndex == var->index && Bv_IsBitSet(ass->index, IRO_Avail) && !PropagationHasDefsInUnorderedRegions(linear, ass->linear2)) {
+ if (ass->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass->linear->u.diadic.left->rtype)) {
+ ENode *enode = IRO_NewENode(ass->linear2->u.node->type);
+ *enode = *ass->linear2->u.node;
+ if (enode->type == EINTCONST) {
+ IRO_TruncateValueToType(&enode->data.intval, linear->rtype);
+ enode->rtype = linear->rtype;
+ } else if (enode->type == EOBJREF) {
+ IROLinear *tmp = IRO_LocateFather(linear);
+ if (tmp && (tmp->flags & IROLF_Assigned))
+ linear->flags |= IROLF_Assigned;
+ }
+ linear->u.monadic->type = IROLinearNop;
+ linear->type = IROLinearOperand;
+ linear->u.node = enode;
+ } else if (IRO_IsVariable(ass->linear2) && IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype)) {
+ linear->u.monadic->u.node = create_objectrefnode(ass->linear2->u.monadic->u.node->data.objref);
+ if (ass->linear2->flags & IROLF_BitfieldIndirect)
+ linear->flags |= IROLF_BitfieldIndirect;
+ } else if (IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype) && ass->x20 == 1 && !VarIsUsedInOtherFNodes(var, node)) {
+ IROList list;
+ IRO_InitList(&list);
+ IRO_DuplicateExpr(ass->linear->u.diadic.right, &list);
+ if (IS_TYPE_FLOAT(ass->linear->rtype)) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
+ tmp->index = ++IRO_NumLinear;
+ tmp->rtype = ass->linear->rtype;
+ tmp->nodetype = ETYPCON;
+ tmp->nodeflags = ENODE_FLAG_80;
+ tmp->u.monadic = list.tail;
+ IRO_AddToList(tmp, &list);
+ }
+ IRO_PasteAfter(list.head, list.tail, linear);
+ IRO_LocateFather_Cut_And_Paste(linear, list.tail);
+ linear = list.tail;
+ }
+ IRO_Dump("Found expression propagation at %d from %d\n", linear->index, ass->linear->index);
+ break;
+ }
+ }
+ }
+ }
+
+ if (linear->type != IROLinearNop && IsIntGenKillCandidate(linear)) {
+ Bv_Clear(IRO_VarKills);
+ IRO_GetKills(linear);
+ for (ass = IRO_FirstAssign; ass; ass = ass->next) {
+ if (Bv_IsBitSet(ass->varIndex, IRO_VarKills))
+ Bv_ClearBit(ass->index, IRO_Avail);
+ if ((obj = IRO_IsVariable(ass->linear->u.diadic.right))) {
+ if ((var = IRO_FindVar(obj, 0, 1))) {
+ if (Bv_IsBitSet(var->index, IRO_VarKills))
+ Bv_ClearBit(ass->index, IRO_Avail);
+ }
+ } else {
+ IROList list;
+ IRO_InitList(&list);
+ IRO_Depends = ass->depends;
+ IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right);
+ if (Bv_BitsInCommon(IRO_VarKills, ass->depends))
+ Bv_ClearBit(ass->index, IRO_Avail);
+ }
+ }
+
+ for (ass = IRO_FirstAssign; ass; ass = ass->next) {
+ IRO_Depends = ass->depends;
+ IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right);
+ if (ass->linear == linear && !Bv_IsBitSet(ass->varIndex, ass->depends))
+ Bv_SetBit(ass->index, IRO_Avail);
+ }
+ }
+
+ if (linear == node->last)
+ break;
+ linear = linear->next;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
diff --git a/compiler_and_linker/unsorted/IroRangePropagation.c b/compiler_and_linker/unsorted/IroRangePropagation.c
index e69de29..c471277 100644
--- a/compiler_and_linker/unsorted/IroRangePropagation.c
+++ b/compiler_and_linker/unsorted/IroRangePropagation.c
@@ -0,0 +1,776 @@
+#include "compiler/IroRangePropagation.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IroVars.h"
+#include "compiler/CInt64.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef enum ERangeType {
+ ERangeType0,
+ ERangeType1,
+ ERangeType2,
+ ERangeType3
+} ERangeType;
+
+typedef struct ERange {
+ ERangeType type;
+ CInt64 upper;
+ CInt64 lower;
+} ERange;
+
+typedef struct ERecord {
+ Object *object;
+ ERange *range;
+ struct ERecord *next;
+} ERecord;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static ERecord *ERangeFirst;
+static ERecord *ERangeLast;
+
+static ERange *ERnewERange(ERangeType type) {
+ ERange *range;
+
+ range = oalloc(sizeof(ERange));
+ range->type = type;
+ return range;
+}
+
+static ERecord *ERnewRecord(Object *object, ERange *range) {
+ ERecord *record;
+
+ record = oalloc(sizeof(ERecord));
+ record->object = object;
+ record->range = range;
+ record->next = ERangeFirst;
+ ERangeFirst = record;
+ if (!ERangeLast)
+ ERangeLast = record;
+ return record;
+}
+
+static ERecord *ERecordFound(Object *obj) {
+ ERecord *scan;
+
+ scan = ERangeFirst;
+ while (scan && obj != scan->object)
+ scan = scan->next;
+
+ return scan;
+}
+
+static Boolean EREandHasNoUse(ERange *range, CInt64 val) {
+ UInt16 i;
+ CInt64 v11;
+ CInt64 work;
+
+ i = 0;
+ work = range->upper;
+ while (CInt64_NotEqual(work = CInt64_ShrU(work, cint64_one), cint64_zero))
+ i++;
+
+ if (CInt64_NotEqual(range->upper, cint64_zero))
+ i++;
+
+ CInt64_SetULong(&work, i);
+ v11 = CInt64_Sub(CInt64_Shl(cint64_one, work), cint64_one);
+ if (CInt64_NotEqual(cint64_zero, CInt64_And(CInt64_Inv(val), v11)))
+ return 0;
+ else
+ return 1;
+}
+
+static void ERcheckOverflow(ERange *range, Type *type) {
+ CInt64 typeSize;
+ CInt64 work;
+ CInt64 work2;
+ CInt64 value3;
+
+ if (!range)
+ return;
+
+ if (!IS_TYPE_INT(type)) {
+ range->type = ERangeType3;
+ return;
+ }
+
+ CInt64_SetLong(&typeSize, type->size);
+ CInt64_SetLong(&value3, 3);
+
+ if (IRO_IsUnsignedType(type)) {
+ if (type->size < 8) {
+ work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Shl(typeSize, value3)), cint64_one);
+ if (CInt64_GreaterU(range->upper, work))
+ range->type = ERangeType3;
+ } else {
+ range->type = ERangeType3;
+ }
+ } else {
+ if (type->size < 8) {
+ work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)), cint64_one);
+ work2 = CInt64_Shl(cint64_negone, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one));
+ if (CInt64_Greater(range->upper, work) || CInt64_Less(range->lower, work2))
+ range->type = ERangeType3;
+ } else {
+ range->type = ERangeType3;
+ }
+ }
+}
+
+static void ERinvalidAll(void) {
+ ERecord *record;
+
+ for (record = ERangeFirst; record; record = record->next)
+ record->range->type = ERangeType3;
+}
+
+static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) {
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *inner;
+ Boolean failed;
+ IROListNode *resultList;
+ IROLinear *scannd;
+ Boolean foundObjRef;
+ ERecord *record;
+ ERange *range;
+ IROListNode *next;
+ Object *obj;
+ IROLinear *analysend;
+ Object *proc;
+
+ failed = 0;
+ if (nd->type == IROLinearOp2Arg)
+ inner = nd->u.diadic.left;
+ else
+ inner = nd->u.monadic;
+
+ if (
+ inner &&
+ inner->type == IROLinearOp1Arg &&
+ inner->nodetype == EINDIRECT &&
+ (analysend = inner->u.monadic) &&
+ copts.opt_pointer_analysis &&
+ analysend->pointsToFunction &&
+ (proc = FunctionName)
+ ) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList);
+
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ failed = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ break;
+ }
+ }
+
+ if (!foundObjRef) {
+ failed = 1;
+ break;
+ }
+ }
+
+ if (!failed) {
+ for (; list; list = list->nextList) {
+ 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);
+
+ range = nd->x16;
+ if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC)
+ range = inner->x16;
+
+ record = ERecordFound(obj);
+ if (!record)
+ ERnewRecord(obj, range);
+ else
+ record->range = range;
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ failed = 1;
+ }
+ } else {
+ failed = 1;
+ }
+
+ if (failed) {
+ ERinvalidAll();
+ nd->x16 = ERnewERange(ERangeType3);
+ }
+}
+
+static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) {
+ IROListNode *scan;
+ IROLinear *scannd;
+ Boolean failed;
+ Boolean foundObjRef;
+ IROListNode *list;
+ IROListNode *resultList;
+ ERecord *record;
+ IROListNode *next;
+ Object *obj;
+ IROLinear *analysend;
+ Object *proc;
+ ObjectList *olist;
+ ObjectList *killList;
+
+ failed = 0;
+
+ if (
+ (analysend = nd->u.funccall.linear8) &&
+ copts.opt_pointer_analysis &&
+ analysend->pointsToFunction &&
+ (proc = FunctionName)
+ ) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList);
+
+ if (resultList) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ failed = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) {
+ if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = scannd->u.node->data.objref;
+#line 385
+ CError_ASSERT(obj != NULL);
+
+ killList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, nd, &killList);
+
+ for (olist = killList; olist; olist = olist->next) {
+ if (!olist->object) {
+ failed = 1;
+ break;
+ }
+ }
+
+ while (killList) {
+ olist = killList->next;
+ IRO_free(killList);
+ killList = olist;
+ }
+
+ if (failed)
+ break;
+ }
+ }
+
+ if (!foundObjRef)
+ failed = 1;
+ if (failed)
+ break;
+ }
+
+ if (!failed) {
+ for (list = resultList; list; list = list->nextList) {
+ 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;
+ killList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, nd, &killList);
+
+ for (olist = killList; olist; olist = olist->next) {
+ if ((record = ERecordFound(olist->object)))
+ record->range->type = ERangeType3;
+ }
+
+ while (killList) {
+ olist = killList->next;
+ IRO_free(killList);
+ killList = olist;
+ }
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ failed = 1;
+ }
+ } else {
+ failed = 1;
+ }
+
+ if (failed)
+ ERinvalidAll();
+}
+
+static void ERfoldOperand(IROLinear *nd) {
+ switch (nd->u.node->type) {
+ case EOBJREF:
+ nd->x16 = NULL;
+ break;
+ case EINTCONST:
+ nd->x16 = ERnewERange(ERangeType0);
+ nd->x16->upper = nd->x16->lower = nd->u.node->data.intval;
+ break;
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ nd->x16 = ERnewERange(ERangeType0);
+ break;
+ }
+}
+
+static Boolean ERfoldExpr(IROLinear *nd) {
+ ERecord *record;
+ ERange *range;
+ IROLinear *tmp;
+ IROLinear *inner;
+ Object *obj;
+
+ switch (nd->nodetype) {
+ case EINDIRECT:
+ inner = nd->u.monadic;
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) {
+ if (!inner->x16 && (obj = inner->u.node->data.objref)) {
+ if ((record = ERecordFound(obj))) {
+ inner->x16 = ERnewERange(ERangeType3);
+ *inner->x16 = *record->range;
+ } else {
+ inner->x16 = ERnewERange(ERangeType3);
+ inner->x16->upper = cint64_max;
+ inner->x16->lower = cint64_min;
+ ERnewRecord(obj, inner->x16);
+ }
+ }
+ nd->x16 = inner->x16;
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ } else {
+ if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF && !inner->x16)
+ inner->x16 = ERnewERange(ERangeType3);
+ nd->x16 = ERnewERange(ERangeType3);
+ }
+ break;
+ case EAND:
+ case EANDASS:
+ if (IRO_IsIntConstant(nd->u.diadic.right)) {
+ CInt64 val = nd->u.diadic.right->u.node->data.intval;
+ nd->x16 = ERnewERange(ERangeType1);
+ nd->x16->upper = val;
+ nd->x16->lower = cint64_zero;
+ if (
+ (range = nd->u.diadic.left->x16) &&
+ range->type != ERangeType3 &&
+ CInt64_LessEqualU(range->upper, val) &&
+ CInt64_LessEqualU(range->lower, val) &&
+ EREandHasNoUse(range, val) &&
+ !IRO_HasSideEffect(nd->u.diadic.left)
+ ) {
+ IRO_Dump("eliminating redundant EAND %ld; upperBound==0x%x, lowerBound==0x%x, Constant==0x%x\n",
+ nd->index,
+ CInt64_GetULong(&range->upper),
+ CInt64_GetULong(&range->upper),
+ CInt64_GetULong(&val)
+ );
+ IRO_NopOut(nd->u.diadic.right);
+ nd->type = IROLinearNop;
+ nd->expr = NULL;
+ tmp = nd->u.diadic.left;
+ nd->u.diadic.left = nd->u.diadic.right;
+ if (!IRO_LocateFather_Cut_And_Paste(nd, tmp)) {
+ tmp->flags &= ~IROLF_Reffed;
+ if (IRO_IsVariable(tmp))
+ IRO_NopOut(tmp);
+ }
+ }
+ } else {
+ if (nd->u.diadic.right->x16) {
+ nd->x16 = ERnewERange(ERangeType3);
+ *nd->x16 = *nd->u.diadic.right->x16;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case ELOGNOT:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ nd->x16 = ERnewERange(ERangeType1);
+ nd->x16->upper = cint64_one;
+ nd->x16->lower = cint64_zero;
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EBINNOT:
+ case EFORCELOAD:
+ case EXOR:
+ case EOR:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case ETYPCON:
+ case EBITFIELD:
+ case ECOND:
+ case ENULLCHECK:
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ break;
+ case EASS:
+ if (IS_TYPE_INT(nd->rtype))
+ nd->x16 = nd->u.diadic.right->x16;
+ break;
+ case EMUL:
+ case EMULV:
+ case EMULASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ if (IRO_IsUnsignedType(nd->rtype)) {
+ nd->x16->upper = CInt64_MulU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
+ nd->x16->lower = CInt64_MulU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
+ } else {
+ nd->x16->upper = CInt64_Mul(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
+ nd->x16->lower = CInt64_Mul(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EDIV:
+ case EDIVASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) {
+ if (IRO_IsUnsignedType(nd->rtype)) {
+ nd->x16->upper = CInt64_DivU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_DivU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ } else {
+ nd->x16->upper = CInt64_Div(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_Div(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EMODULO:
+ case EMODASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) {
+ if (IRO_IsUnsignedType(nd->rtype)) {
+ nd->x16->upper = CInt64_ModU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_ModU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ } else {
+ nd->x16->upper = CInt64_Mod(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_Mod(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EADDV:
+ case EADD:
+ case EADDASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ nd->x16->upper = CInt64_Add(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
+ nd->x16->lower = CInt64_Add(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case ESUBV:
+ case ESUB:
+ case ESUBASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ nd->x16->upper = CInt64_Sub(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_Sub(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case ESHL:
+ case ESHLASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ nd->x16->upper = CInt64_Shl(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper);
+ nd->x16->lower = CInt64_Shl(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case ESHR:
+ case ESHRASS:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 &&
+ nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ if (IRO_IsUnsignedType(nd->rtype)) {
+ nd->x16->upper = CInt64_ShrU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_ShrU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ } else {
+ nd->x16->upper = CInt64_Shr(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower);
+ nd->x16->lower = CInt64_Shr(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper);
+ }
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EPOSTINC:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ range = nd->u.monadic->x16;
+ *nd->x16 = *range;
+ range->upper = CInt64_Add(range->upper, cint64_one);
+ range->lower = CInt64_Add(range->lower, cint64_one);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EPOSTDEC:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ range = nd->u.monadic->x16;
+ *nd->x16 = *range;
+ range->upper = CInt64_Sub(range->upper, cint64_one);
+ range->lower = CInt64_Sub(range->lower, cint64_one);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EPREINC:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ range = nd->u.monadic->x16;
+ nd->x16->upper = CInt64_Add(range->upper, cint64_one);
+ nd->x16->lower = CInt64_Add(range->lower, cint64_one);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EPREDEC:
+ if (IS_TYPE_INT(nd->rtype)) {
+ if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) {
+ nd->x16 = ERnewERange(ERangeType2);
+ range = nd->u.monadic->x16;
+ nd->x16->upper = CInt64_Sub(range->upper, cint64_one);
+ nd->x16->lower = CInt64_Sub(range->lower, cint64_one);
+ } else {
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ }
+ }
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ case EMONMIN:
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ break;
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ nd->x16 = ERnewERange(ERangeType3);
+ nd->x16->upper = cint64_max;
+ nd->x16->lower = cint64_min;
+ break;
+ default:
+ ERcheckOverflow(nd->x16, nd->rtype);
+ break;
+ }
+
+ if (
+ (nd->type == IROLinearOp1Arg || nd->type == IROLinearOp2Arg) &&
+ IRO_IsAssignOp[nd->nodetype] &&
+ nd->x16 &&
+ IS_TYPE_INT(nd->rtype)
+ ) {
+ IROLinear *x = NULL;
+ if (nd->type == IROLinearOp2Arg)
+ x = nd->u.diadic.left;
+ else if (nd->type == IROLinearOp1Arg)
+ x = nd->u.monadic;
+
+ if (x->type == IROLinearOp1Arg &&
+ x->nodetype == EINDIRECT &&
+ (x->u.monadic->nodetype == EINDIRECT || x->u.monadic->nodetype == EADD)) {
+ SetRangesForKillsByIndirectAssignment(nd);
+ } else {
+ obj = NULL;
+ if (x)
+ obj = IRO_IsVariable(x);
+ if (!obj)
+ return 0;
+
+ range = nd->x16;
+ if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC)
+ range = x->x16;
+
+ record = ERecordFound(obj);
+ if (!record)
+ ERnewRecord(obj, range);
+ else
+ record->range = range;
+ }
+ }
+
+ return nd->x16 != NULL;
+}
+
+static Boolean ERfoldLinear(IROLinear *nd) {
+ nd->x16 = 0;
+
+ switch (nd->type) {
+ case IROLinearNop:
+ case IROLinearEnd:
+ break;
+ case IROLinearOperand:
+ ERfoldOperand(nd);
+ break;
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ ERfoldExpr(nd);
+ break;
+ case IROLinearFunccall:
+ InvalidateRangesForKillsByFunctionCall(nd);
+ break;
+ case IROLinearAsm:
+ ERinvalidAll();
+ break;
+ }
+
+ return 0;
+}
+
+Boolean IRO_RangePropagateInFNode(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+ Boolean result;
+
+ result = 0;
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ ERangeFirst = ERangeLast = NULL;
+ for (nd = fnode->first; nd != fnode->last; nd = nd->next)
+ ERfoldLinear(nd);
+ if (ERfoldLinear(nd))
+ result = 1;
+ }
+
+ if (result) {
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
diff --git a/compiler_and_linker/unsorted/IroSubable.c b/compiler_and_linker/unsorted/IroSubable.c
index e69de29..6b8daf0 100644
--- a/compiler_and_linker/unsorted/IroSubable.c
+++ b/compiler_and_linker/unsorted/IroSubable.c
@@ -0,0 +1,160 @@
+#include "compiler/IroSubable.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroPropagate.h"
+#include "compiler/IroUtil.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+static Boolean IsSubableOp[MAXEXPR];
+
+void IRO_InitializeIsSubableOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ IsSubableOp[i] = 0;
+
+ IsSubableOp[EPOSTINC] = 0;
+ IsSubableOp[EPOSTDEC] = 0;
+ IsSubableOp[EPREINC] = 0;
+ IsSubableOp[EPREDEC] = 0;
+ IsSubableOp[EINDIRECT] = 0;
+ IsSubableOp[EMONMIN] = 1;
+ IsSubableOp[EBINNOT] = 1;
+ IsSubableOp[ELOGNOT] = 1;
+ IsSubableOp[EFORCELOAD] = 0;
+ IsSubableOp[EMUL] = 1;
+ IsSubableOp[EMULV] = 1;
+ IsSubableOp[EDIV] = 1;
+ IsSubableOp[EMODULO] = 1;
+ IsSubableOp[EADDV] = 1;
+ IsSubableOp[ESUBV] = 1;
+ IsSubableOp[EADD] = 1;
+ IsSubableOp[ESUB] = 1;
+ IsSubableOp[ESHL] = 1;
+ IsSubableOp[ESHR] = 1;
+ IsSubableOp[ELESS] = 0;
+ IsSubableOp[EGREATER] = 0;
+ IsSubableOp[ELESSEQU] = 0;
+ IsSubableOp[EGREATEREQU] = 0;
+ IsSubableOp[EEQU] = 0;
+ IsSubableOp[ENOTEQU] = 0;
+ IsSubableOp[EAND] = 1;
+ IsSubableOp[EXOR] = 1;
+ IsSubableOp[EOR] = 1;
+ IsSubableOp[ELAND] = 0;
+ IsSubableOp[ELOR] = 0;
+ IsSubableOp[EASS] = 0;
+ IsSubableOp[EMULASS] = 0;
+ IsSubableOp[EDIVASS] = 0;
+ IsSubableOp[EMODASS] = 0;
+ IsSubableOp[EADDASS] = 0;
+ IsSubableOp[ESUBASS] = 0;
+ IsSubableOp[ESHLASS] = 0;
+ IsSubableOp[ESHRASS] = 0;
+ IsSubableOp[EANDASS] = 0;
+ IsSubableOp[EXORASS] = 0;
+ IsSubableOp[EORASS] = 0;
+ IsSubableOp[ECOMMA] = 0;
+ IsSubableOp[EPMODULO] = 0;
+ IsSubableOp[EROTL] = 0;
+ IsSubableOp[EROTR] = 0;
+ IsSubableOp[EBCLR] = 0;
+ IsSubableOp[EBTST] = 0;
+ IsSubableOp[EBSET] = 0;
+ IsSubableOp[ETYPCON] = 0;
+ IsSubableOp[EBITFIELD] = 0;
+ IsSubableOp[EINTCONST] = 0;
+ IsSubableOp[EFLOATCONST] = 0;
+ IsSubableOp[ESTRINGCONST] = 0;
+ IsSubableOp[ECOND] = 0;
+ IsSubableOp[EFUNCCALL] = 0;
+ IsSubableOp[EFUNCCALLP] = 0;
+ IsSubableOp[EOBJREF] = 0;
+ IsSubableOp[EMFPOINTER] = 0;
+ IsSubableOp[ENULLCHECK] = 0;
+ IsSubableOp[EPRECOMP] = 0;
+ IsSubableOp[ETEMP] = 0;
+ IsSubableOp[EARGOBJ] = 0;
+ IsSubableOp[ELOCOBJ] = 0;
+ IsSubableOp[ELABEL] = 0;
+ IsSubableOp[ESETCONST] = 0;
+ IsSubableOp[ENEWEXCEPTION] = 0;
+ IsSubableOp[ENEWEXCEPTIONARRAY] = 0;
+ IsSubableOp[EOBJLIST] = 0;
+ IsSubableOp[EMEMBER] = 0;
+ IsSubableOp[ETEMPLDEP] = 0;
+ IsSubableOp[EINSTRUCTION] = 0;
+ IsSubableOp[EDEFINE] = 0;
+ IsSubableOp[EREUSE] = 0;
+ IsSubableOp[EASSBLK] = 0;
+ IsSubableOp[EVECTOR128CONST] = 0;
+ IsSubableOp[ECONDASS] = 0;
+}
+
+static int IsSubscript(IROLinear *nd) {
+ return 0;
+}
+
+Boolean IRO_IsSubableExpression(IROLinear *nd) {
+ Object *varobj;
+ Boolean result;
+
+ switch (nd->type) {
+ case IROLinearOp2Arg:
+ if (nd->nodetype == EADD || nd->nodetype == ESUB) {
+ if (
+ IRO_IsConstant(nd->u.diadic.right) &&
+ (varobj = IRO_IsVariable(nd->u.diadic.left)) &&
+ varobj->datatype == DLOCAL &&
+ varobj->u.var.info &&
+ !varobj->u.var.info->noregister)
+ return 0;
+
+ }
+ result = IsSubableOp[nd->nodetype] && !IsSubscript(nd);
+ return result;
+ case IROLinearOp1Arg:
+ if (IsSubableOp[nd->nodetype] && !IsSubscript(nd))
+ return 1;
+
+ if (nd->nodetype == EINDIRECT && !(nd->flags & IROLF_Assigned)) {
+ if (nd->flags & IROLF_Ind) {
+ nd = nd->u.monadic;
+ if (nd->type == IROLinearOperand &&
+ nd->u.node->type == EOBJREF &&
+ nd->u.node->data.objref->datatype == DLOCAL &&
+ nd->u.node->data.objref->u.var.info &&
+ !nd->u.node->data.objref->u.var.info->noregister
+ )
+ return 0;
+ return 1;
+ }
+
+ if (IRO_IsVariable(nd) && IRO_IsRegable(nd->u.monadic->u.node->data.objref))
+ return 0;
+ return 1;
+ } else if (nd->nodetype == ETYPCON && IS_TYPE_INT(nd->rtype) && nd->rtype->size >= nd->u.monadic->rtype->size) {
+ return 1;
+ } else {
+ return 0;
+ }
+ case IROLinearOperand:
+ default:
+ return 0;
+ }
+}
+
+Boolean IRO_IsVectorTempCandidate(IROLinear *nd) {
+ return
+ (
+ nd->type == IROLinearOp1Arg ||
+ nd->type == IROLinearOp2Arg ||
+ nd->type == IROLinearOp3Arg ||
+ nd->type == IROLinearOperand ||
+ nd->type == IROLinearFunccall
+ ) && (
+ (nd->flags & IROLF_LoopInvariant) &&
+ !(nd->flags & IROLF_Ind)
+ );
+}
diff --git a/compiler_and_linker/unsorted/IroTransform.c b/compiler_and_linker/unsorted/IroTransform.c
index e69de29..710f2d8 100644
--- a/compiler_and_linker/unsorted/IroTransform.c
+++ b/compiler_and_linker/unsorted/IroTransform.c
@@ -0,0 +1,3 @@
+#include "compiler/IroTransform.h"
+
+// TODO
diff --git a/compiler_and_linker/unsorted/IroUnrollLoop.c b/compiler_and_linker/unsorted/IroUnrollLoop.c
index e69de29..f5c4fb0 100644
--- a/compiler_and_linker/unsorted/IroUnrollLoop.c
+++ b/compiler_and_linker/unsorted/IroUnrollLoop.c
@@ -0,0 +1,95 @@
+#include "compiler/IroUnrollLoop.h"
+#include "compiler/IroUtil.h"
+
+// forward decls
+static void IRO_FindLoops_Unroll(void);
+
+void IRO_LoopUnroller(void) {
+ VectorPhaseCalledFromUnroll = 1;
+ IRO_FindLoops_Unroll();
+ IRO_CheckForUserBreak();
+}
+
+static void IRO_FindLoops_Unroll(void) {
+}
+
+static void CheckConstant() {
+}
+
+static void UnrollWhileLoopBody() {
+}
+
+static void PatternMatchLoop() {
+}
+
+static void UnrollWhileLoop() {
+}
+
+void IRO_IterateForLoopBody() {
+}
+
+void IRO_LinearizeForLoopPostLoop() {
+}
+
+static void UnrollForLoop() {
+}
+
+static void UnrollStandardLoop() {
+}
+
+static void LoopUnroll() {
+}
+
+static void IsLoopUnrollable() {
+}
+
+void BuildEarlyLoopExitTest() {
+}
+
+void BuildLoopExitTest() {
+}
+
+void IsIterationCountConstant() {
+}
+
+static void IsDifferenceOfTermsConstant() {
+}
+
+void NoOpBlock() {
+}
+
+void IRO_TestConstantIterationCount() {
+}
+
+void BuildOrigIterationCount() {
+}
+
+static void BuildOrigIterationCount_DoWhile() {
+}
+
+void BuildNewFinalvalue() {
+}
+
+static void BuildPreAlignTemp() {
+}
+
+static void BuildNewFinalvalue_DoWhile() {
+}
+
+static void BuildUnrolledFinalvalue_DoWhile() {
+}
+
+void BuildUnrolledBodyEntryTest() {
+}
+
+void ChangeInductionReference() {
+}
+
+void UpdateInductionIncrement() {
+}
+
+void GenInitialAssignment() {
+}
+
+void GenNewInduction() {
+}
diff --git a/compiler_and_linker/unsorted/IroUtil.c b/compiler_and_linker/unsorted/IroUtil.c
index e69de29..37a6be9 100644
--- a/compiler_and_linker/unsorted/IroUtil.c
+++ b/compiler_and_linker/unsorted/IroUtil.c
@@ -0,0 +1,1250 @@
+#include "compiler/IroUtil.h"
+#include "compiler/IroCSE.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroLoop.h"
+#include "compiler/IroVars.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CCompiler.h"
+#include "compiler/CError.h"
+#include "compiler/CException.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/Exceptions.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "cos.h"
+
+static UInt32 IRO_LastUserBreakTick;
+static IROLinear *ExprStart;
+static IROLinear *ExprEnd;
+static IRONode *IRO_Node;
+static SInt32 FuncLevel;
+Object *FunctionName;
+Boolean IRO_IsLeafFunction;
+Boolean IRO_FunctionHasReturn;
+Boolean DisableDueToAsm;
+Boolean LoopOptimizerRun;
+
+Object *IRO_IsVariable(IROLinear *linear) {
+ if (linear->type == IROLinearOp1Arg &&
+ linear->nodetype == EINDIRECT &&
+ linear->u.monadic->type == IROLinearOperand &&
+ linear->u.monadic->u.node->type == EOBJREF)
+ return linear->u.monadic->u.node->data.objref;
+
+ return NULL;
+}
+
+Boolean IRO_IsConstant(IROLinear *linear) {
+ if (linear->type == IROLinearOperand && ENODE_IS3(linear->u.node, EINTCONST, EVECTOR128CONST, EFLOATCONST))
+ return 1;
+ return 0;
+}
+
+Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue) {
+ UInt32 desired;
+ UInt32 value;
+ SInt32 i;
+
+ *powvalue = -1;
+ if (linear->type == IROLinearOperand && linear->u.node->type == EINTCONST) {
+ if (CTool_EndianReadWord32(&linear->u.node->data.intval.hi))
+ return 0;
+
+ desired = CInt64_GetULong(&linear->u.node->data.intval);
+ value = 1;
+ for (i = 0; i < 31; i++) {
+ if (value == desired) {
+ *powvalue = i;
+ return 1;
+ }
+ value += value;
+ }
+ }
+
+ return 0;
+}
+
+Boolean IRO_IsIntConstant(IROLinear *linear) {
+ if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EINTCONST))
+ return 1;
+ return 0;
+}
+
+Boolean IRO_IsFloatConstant(IROLinear *linear) {
+ if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EFLOATCONST))
+ return 1;
+ return 0;
+}
+
+Boolean IRO_IsVector128Constant(IROLinear *linear) {
+ if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EVECTOR128CONST))
+ return 1;
+ return 0;
+}
+
+Boolean IRO_IsAssignment(IROLinear *linear) {
+ if (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg) {
+ if (IRO_IsAssignOp[linear->nodetype])
+ return 1;
+ }
+ return 0;
+}
+
+static Boolean IRO_OperandsSame(ENode *a, ENode *b) {
+ if (a->type == b->type) {
+ switch (a->type) {
+ case EINTCONST:
+ return CInt64_Equal(a->data.intval, b->data.intval);
+ case ESTRINGCONST:
+ return 0;
+ case EFLOATCONST:
+ return a->data.floatval.value == b->data.floatval.value;
+ case EVECTOR128CONST:
+ return (a->data.vector128val.ul[0] == b->data.vector128val.ul[0]) &&
+ (a->data.vector128val.ul[1] == b->data.vector128val.ul[1]) &&
+ (a->data.vector128val.ul[2] == b->data.vector128val.ul[2]) &&
+ (a->data.vector128val.ul[3] == b->data.vector128val.ul[3]);
+ case EOBJREF:
+ return a->data.objref == b->data.objref;
+ }
+ }
+
+ return 0;
+}
+
+Boolean IRO_TypesEqual(Type *a, Type *b) {
+ if (IS_TYPE_BITFIELD(a)) {
+ if (IS_TYPE_BITFIELD(b)) {
+ if (
+ (TYPE_BITFIELD(a)->bitfieldtype == TYPE_BITFIELD(b)->bitfieldtype) &&
+ (TYPE_BITFIELD(a)->unkA == TYPE_BITFIELD(b)->unkA) &&
+ (TYPE_BITFIELD(a)->unkB == TYPE_BITFIELD(b)->unkB))
+ return 1;
+ }
+ return 0;
+ }
+
+ if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b))
+ return 1;
+
+ return is_typeequal(a, b) != 0;
+}
+
+Type *IRO_UnsignedType(Type *type) {
+ if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) {
+ if (type->size == stunsignedchar.size)
+ return TYPE(&stunsignedchar);
+ if (type->size == stunsignedint.size)
+ return TYPE(&stunsignedint);
+ if (type->size == stunsignedshort.size)
+ return TYPE(&stunsignedshort);
+ if (type->size == stunsignedlong.size)
+ return TYPE(&stunsignedlong);
+ if (type->size == stunsignedlonglong.size)
+ return TYPE(&stunsignedlonglong);
+#line 281
+ CError_FATAL();
+ return NULL;
+ }
+
+ if (!IS_TYPE_INT(type)) {
+#line 287
+ CError_FATAL();
+ return NULL;
+ }
+
+ if (type == TYPE(&stbool) || type == TYPE(&stwchar))
+ return type;
+
+ if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar))
+ return TYPE(&stunsignedchar);
+ if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort))
+ return TYPE(&stunsignedshort);
+ if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint))
+ return TYPE(&stunsignedint);
+ if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong))
+ return TYPE(&stunsignedlong);
+ if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong))
+ return TYPE(&stunsignedlonglong);
+
+#line 319
+ CError_FATAL();
+ return NULL;
+}
+
+Type *IRO_SignedType(Type *type) {
+ if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) {
+ if (type->size == stsignedchar.size)
+ return TYPE(&stsignedchar);
+ if (type->size == stsignedint.size)
+ return TYPE(&stsignedint);
+ if (type->size == stsignedshort.size)
+ return TYPE(&stsignedshort);
+ if (type->size == stsignedlong.size)
+ return TYPE(&stsignedlong);
+ if (type->size == stsignedlonglong.size)
+ return TYPE(&stsignedlonglong);
+#line 357
+ CError_FATAL();
+ return NULL;
+ }
+
+ if (!IS_TYPE_INT(type)) {
+#line 363
+ CError_FATAL();
+ return NULL;
+ }
+
+ if (type == TYPE(&stbool) && type->size == stsignedchar.size)
+ return TYPE(&stsignedchar);
+
+ if (type == TYPE(&stwchar) && type->size == stsignedshort.size)
+ return TYPE(&stsignedshort);
+
+ if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar))
+ return TYPE(&stsignedchar);
+ if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort))
+ return TYPE(&stsignedshort);
+ if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint))
+ return TYPE(&stsignedint);
+ if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong))
+ return TYPE(&stsignedlong);
+ if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong))
+ return TYPE(&stsignedlonglong);
+
+#line 399
+ CError_FATAL();
+ return NULL;
+}
+
+Boolean IRO_is_CPtypeequal(Type *a, Type *b) {
+ if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b))
+ return 1;
+
+ return is_typeequal(a, b) != 0;
+}
+
+Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b) {
+ if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) {
+ switch (a->type) {
+ case IROLinearOperand:
+ return IRO_OperandsSame(a->u.node, b->u.node);
+ case IROLinearOp1Arg:
+ if (a->nodetype == b->nodetype)
+ return IRO_ExprsSame(a->u.monadic, b->u.monadic);
+ return 0;
+ case IROLinearOp2Arg:
+ if (a->nodetype == b->nodetype)
+ return IRO_ExprsSame(a->u.diadic.left, b->u.diadic.left) &&
+ IRO_ExprsSame(a->u.diadic.right, b->u.diadic.right);
+ return 0;
+ case IROLinearOp3Arg:
+ if (a->nodetype == b->nodetype)
+ return IRO_ExprsSame(a->u.args3.a, b->u.args3.a) &&
+ IRO_ExprsSame(a->u.args3.b, b->u.args3.b) &&
+ IRO_ExprsSame(a->u.args3.c, b->u.args3.c);
+ return 0;
+ case IROLinearFunccall:
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+CLabel *IRO_NewLabel(void) {
+ CLabel *label = newlabel();
+ label->next = Labels;
+ Labels = label;
+ return label;
+}
+
+Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b) {
+ if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) {
+ Boolean flag = 0;
+
+ switch (a->type) {
+ case IROLinearOperand:
+ return IRO_OperandsSame(a->u.node, b->u.node);
+ case IROLinearOp1Arg:
+ if (a->nodetype == b->nodetype)
+ return IRO_ExprsSameSemantically(a->u.monadic, b->u.monadic);
+ return 0;
+ case IROLinearOp2Arg:
+ if (a->nodetype == b->nodetype) {
+ switch (a->nodetype) {
+ case EMUL:
+ case EADD:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ if (!IRO_HasSideEffect(a)) {
+ flag = IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.right) &&
+ IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.left);
+ }
+ }
+
+ return flag || (IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.left) &&
+ IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.right));
+ }
+ return 0;
+ case IROLinearOp3Arg:
+ if (a->nodetype == b->nodetype)
+ return IRO_ExprsSameSemantically(a->u.args3.a, b->u.args3.a) &&
+ IRO_ExprsSameSemantically(a->u.args3.b, b->u.args3.b) &&
+ IRO_ExprsSameSemantically(a->u.args3.c, b->u.args3.c);
+ return 0;
+ case IROLinearFunccall:
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter) {
+ IROLinear *prev = iter;
+ while (iter && iter != a) {
+ prev = iter;
+ iter = iter->next;
+ }
+
+ if (iter)
+ return prev;
+ return iter;
+}
+
+IROLinear *IRO_FindPreced(IROLinear *a) {
+ IROLinear *iter;
+ IROLinear *prev;
+
+ prev = iter = IRO_FirstLinear;
+ while (iter && iter != a) {
+ prev = iter;
+ iter = iter->next;
+ }
+
+ if (iter)
+ return prev;
+ return iter;
+}
+
+IROLinear *IRO_FindFirst(IROLinear *linear) {
+ short i;
+
+ switch (linear->type) {
+ case IROLinearOperand:
+ return linear;
+ case IROLinearOp1Arg:
+ return IRO_FindFirst(linear->u.monadic);
+ case IROLinearOp2Arg:
+ if (linear->u.diadic.right->index < linear->u.diadic.left->index)
+ return IRO_FindFirst(linear->u.diadic.right);
+ else
+ return IRO_FindFirst(linear->u.diadic.left);
+ case IROLinearOp3Arg:
+ if (linear->u.args3.a->index < linear->u.args3.b->index) {
+ if (linear->u.args3.b->index < linear->u.args3.c->index)
+ return IRO_FindFirst(linear->u.args3.a);
+ else
+ return IRO_FindFirst(linear->u.args3.c);
+ } else {
+ if (linear->u.args3.b->index < linear->u.args3.c->index)
+ return IRO_FindFirst(linear->u.args3.b);
+ else
+ return IRO_FindFirst(linear->u.args3.c);
+ }
+ case IROLinearFunccall:
+ i = linear->u.funccall.argCount - 1;
+ return IRO_FindFirst(linear->u.funccall.args[i]);
+ default:
+#line 641
+ CError_FATAL();
+ return NULL;
+ }
+}
+
+void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) {
+ IROLinear *preced = IRO_FindPreced(a);
+ preced->next = b->next;
+ b->next = c->next;
+ c->next = a;
+}
+
+Boolean IRO_IsConstantZero(IROLinear *linear) {
+ return (IRO_IsIntConstant(linear) && CInt64_IsZero(&linear->u.node->data.intval)) ||
+ (IRO_IsFloatConstant(linear) && CMach_FloatIsZero(linear->u.node->data.floatval));
+}
+
+Boolean IRO_IsConstantOne(IROLinear *linear) {
+ return (IRO_IsIntConstant(linear) && CInt64_IsOne(&linear->u.node->data.intval)) ||
+ (IRO_IsFloatConstant(linear) && CMach_FloatIsOne(linear->u.node->data.floatval));
+}
+
+Boolean IRO_IsConstantNegativeOne(IROLinear *linear) {
+ CInt64 neg = CInt64_Neg(linear->u.node->data.intval);
+ return (IRO_IsIntConstant(linear) && CInt64_IsOne(&neg)) ||
+ (IRO_IsFloatConstant(linear) && CMach_FloatIsNegOne(linear->u.node->data.floatval));
+}
+
+static void ActNop(IROLinear *linear, Boolean isEntry) {
+ if (!isEntry) {
+ linear->type = IROLinearNop;
+ linear->expr = NULL;
+ }
+}
+
+void IRO_NopOut(IROLinear *linear) {
+ IRO_WalkTree(linear, ActNop);
+}
+
+static Boolean NotNoppable(IROLinear *linear) {
+ return (
+ (linear->type == IROLinearFunccall) ||
+ IRO_IsAssignment(linear) ||
+ ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EINSTRUCTION)) ||
+ (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) ||
+ ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref))
+ );
+}
+
+static void ActNopNonSideEffects(IROLinear *linear, Boolean isEntry) {
+ if (isEntry) {
+ if (NotNoppable(linear)) {
+ if (!FuncLevel)
+ linear->flags &= ~IROLF_Reffed;
+ FuncLevel++;
+ }
+ } else {
+ if (NotNoppable(linear)) {
+ FuncLevel--;
+ } else if (!FuncLevel) {
+ linear->type = IROLinearNop;
+ }
+ }
+}
+
+void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level) {
+ FuncLevel = level;
+ IRO_WalkTree(linear, ActNopNonSideEffects);
+}
+
+void IRO_BuildList(IROLinear *linear, Boolean isEntry) {
+ if (!isEntry) {
+ linear->next = NULL;
+ IRO_AddToList(linear, &IRO_InitLList);
+ }
+}
+
+void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func) {
+ int i;
+
+ func(linear, 1);
+ switch (linear->type) {
+ case IROLinearOperand:
+ break;
+ case IROLinearOp1Arg:
+ IRO_WalkTree(linear->u.monadic, func);
+ break;
+ case IROLinearOp2Arg:
+ IRO_WalkTree(linear->u.diadic.left, func);
+ IRO_WalkTree(linear->u.diadic.right, func);
+ break;
+ case IROLinearOp3Arg:
+ IRO_WalkTree(linear->u.args3.a, func);
+ IRO_WalkTree(linear->u.args3.b, func);
+ IRO_WalkTree(linear->u.args3.c, func);
+ break;
+ case IROLinearFunccall:
+ IRO_WalkTree(linear->u.funccall.linear8, func);
+ for (i = 0; i < linear->u.funccall.argCount; i++)
+ IRO_WalkTree(linear->u.funccall.args[i], func);
+ break;
+ }
+ func(linear, 0);
+}
+
+void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func) {
+ int i;
+
+ switch (linear->type) {
+ case IROLinearOperand:
+ break;
+ case IROLinearOp1Arg:
+ IRO_WalkTreeToPropagateFlags(linear->u.monadic, func);
+ break;
+ case IROLinearOp2Arg:
+ IRO_WalkTreeToPropagateFlags(linear->u.diadic.left, func);
+ IRO_WalkTreeToPropagateFlags(linear->u.diadic.right, func);
+ break;
+ case IROLinearOp3Arg:
+ IRO_WalkTreeToPropagateFlags(linear->u.args3.a, func);
+ IRO_WalkTreeToPropagateFlags(linear->u.args3.b, func);
+ IRO_WalkTreeToPropagateFlags(linear->u.args3.c, func);
+ break;
+ case IROLinearFunccall:
+ IRO_WalkTreeToPropagateFlags(linear->u.funccall.linear8, func);
+ for (i = 0; i < linear->u.funccall.argCount; i++)
+ IRO_WalkTreeToPropagateFlags(linear->u.funccall.args[i], func);
+ break;
+ }
+ func(linear, 0);
+}
+
+void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func) {
+ IROLinear *scan;
+
+ for (scan = a; scan; scan = scan->next) {
+ switch (scan->type) {
+ case IROLinearBeginCatch:
+ case IROLinearEndCatch:
+ case IROLinearEndCatchDtor:
+ IRO_WalkTree(scan->u.ctch.linear, func);
+ break;
+ case IROLinearOperand:
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ case IROLinearOp3Arg:
+ case IROLinearFunccall:
+ IRO_WalkTree(scan, func);
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ IRO_WalkTree(scan->u.label.x4, func);
+ break;
+ case IROLinearReturn:
+ if (scan->u.monadic)
+ IRO_WalkTree(scan->u.monadic, func);
+ break;
+ case IROLinearSwitch:
+ IRO_WalkTree(scan->u.swtch.x4, func);
+ break;
+ case IROLinearAsm:
+ func(scan, 1);
+ func(scan, 0);
+ break;
+ case IROLinearEnd:
+ break;
+ }
+
+ if (scan == b)
+ break;
+ }
+}
+
+void IRO_Cut(IROLinear *a, IROLinear *b) {
+ IROLinear *scan;
+ IROLinear *prev;
+ IRONode *node;
+
+ scan = a;
+ while (1) {
+ scan->stmt = NULL;
+ if (scan == b)
+ break;
+ scan = scan->next;
+ }
+
+ prev = NULL;
+ for (scan = IRO_FirstLinear; scan && scan != a; scan = scan->next)
+ prev = scan;
+
+#line 951
+ CError_ASSERT(scan);
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first == a) {
+ if (node->last == b) {
+ node->first = node->last = NULL;
+ break;
+ } else {
+ node->first = b->next;
+ break;
+ }
+ } else if (node->last == b) {
+ node->last = prev;
+ break;
+ }
+ }
+
+ if (prev)
+ prev->next = b->next;
+ else
+ IRO_FirstLinear = b->next;
+}
+
+void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c) {
+ IROLinear *prev;
+ IROLinear *scan;
+ IRONode *node;
+
+#line 1002
+ CError_ASSERT(c && c->type != IROLinearLabel);
+
+ prev = NULL;
+ for (scan = IRO_FirstLinear; scan && scan != c; scan = scan->next)
+ prev = scan;
+
+#line 1016
+ CError_ASSERT(scan);
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first == c) {
+ node->first = a;
+ break;
+ }
+ }
+
+ b->next = c;
+ if (prev)
+ prev->next = a;
+ else
+ IRO_FirstLinear = a;
+}
+
+void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) {
+ IRONode *node;
+
+ switch (c->type) {
+ case IROLinearGoto:
+ case IROLinearIf:
+ case IROLinearIfNot:
+ case IROLinearSwitch:
+#line 1060
+ CError_FATAL();
+ }
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->last == c) {
+ node->last = b;
+ break;
+ }
+ }
+
+ b->next = c->next;
+ c->next = a;
+}
+
+static void FindStart(IROLinear *linear, Boolean isEntry) {
+ IROLinear *scan;
+ if (isEntry) {
+ scan = linear;
+ do {
+ if (scan == ExprStart) {
+ ExprStart = linear;
+ return;
+ }
+ if (scan == ExprEnd)
+ return;
+ } while ((scan = scan->next));
+ }
+}
+
+void IRO_ClipExpr(IROExpr *expr) {
+ ExprStart = ExprEnd = expr->linear;
+ IRO_WalkTree(expr->linear, FindStart);
+ IRO_Cut(ExprStart, ExprEnd);
+}
+
+void IRO_ClipExprTree(IROLinear *linear) {
+ ExprStart = ExprEnd = linear;
+ IRO_WalkTree(linear, FindStart);
+ IRO_Cut(ExprStart, ExprEnd);
+}
+
+static void SetNodeNumInExprList(IROLinear *linear, Boolean isEntry) {
+ if (isEntry && linear->expr)
+ linear->expr->node = IRO_Node;
+}
+
+void IRO_MoveExpression(IROExpr *expr, IROLinear *linear) {
+ IRONode *node;
+ IROLinear *scan;
+
+ ExprStart = ExprEnd = expr->linear;
+ IRO_WalkTree(expr->linear, FindStart);
+
+ if (ExprStart != linear) {
+ IRO_Cut(ExprStart, ExprEnd);
+ IRO_Paste(ExprStart, ExprEnd, linear);
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ for (scan = node->first; scan; scan = scan->next) {
+ if (scan == expr->linear) {
+ expr->node = node;
+ break;
+ }
+ if (scan == node->last)
+ break;
+ }
+ }
+
+ IRO_Node = expr->node;
+ IRO_WalkTree(expr->linear, SetNodeNumInExprList);
+ }
+}
+
+void IRO_InitList(IROList *list) {
+ list->head = list->tail = NULL;
+}
+
+void IRO_AddToList(IROLinear *linear, IROList *list) {
+ if (list->head)
+ list->tail->next = linear;
+ else
+ list->head = linear;
+
+ list->tail = linear;
+ while (list->tail->next)
+ list->tail = list->tail->next;
+}
+
+IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear) {
+ IROLinear *scan;
+
+ for (scan = linear; scan; scan = scan->next) {
+ if (scan->type == IROLinearLabel && scan->u.label.label == label)
+ break;
+ }
+
+#line 1244
+ CError_ASSERT(scan);
+ return scan;
+}
+
+void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list) {
+ IROLinear *scan;
+
+ for (scan = start; scan; scan = scan->next) {
+ if (scan->type != IROLinearNop && !(scan->flags & IROLF_Reffed))
+ IRO_DuplicateExpr(scan, list);
+ if (scan == end)
+ break;
+ }
+}
+
+IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list) {
+ IROLinear *copy;
+ ENode *copynode;
+ int i;
+
+ copy = IRO_NewLinear(linear->type);
+ *copy = *linear;
+
+ copy->index = ++IRO_NumLinear;
+ copy->next = NULL;
+ copy->expr = NULL;
+
+ switch (copy->type) {
+ case IROLinearOperand:
+ copynode = lalloc(sizeof(ENode));
+ *copynode = *linear->u.node;
+ copy->u.node = copynode;
+ break;
+ case IROLinearOp1Arg:
+ copy->u.monadic = IRO_DuplicateExpr(copy->u.monadic, list);
+ break;
+ case IROLinearOp2Arg:
+ if (linear->flags & IROLF_8000) {
+ copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list);
+ copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list);
+ } else {
+ copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list);
+ copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list);
+ }
+ break;
+ case IROLinearOp3Arg:
+ copy->u.args3.a = IRO_DuplicateExpr(copy->u.args3.a, list);
+ copy->u.args3.b = IRO_DuplicateExpr(copy->u.args3.b, list);
+ copy->u.args3.c = IRO_DuplicateExpr(copy->u.args3.c, list);
+ break;
+ case IROLinearFunccall:
+ copy->u.funccall.linear8 = IRO_DuplicateExpr(copy->u.funccall.linear8, list);
+ copy->u.funccall.args = oalloc(sizeof(IROLinear *) * copy->u.funccall.argCount);
+ for (i = 0; i < copy->u.funccall.argCount; i++) {
+ copy->u.funccall.args[i] = IRO_DuplicateExpr(linear->u.funccall.args[i], list);
+ }
+ break;
+ case IROLinearAsm:
+ copy->u.asm_stmt = CodeGen_CopyAsmStat(linear->u.asm_stmt);
+ break;
+ }
+
+ IRO_AddToList(copy, list);
+ return copy;
+}
+
+IROLinear *IRO_TempReference(Object *obj, IROList *list) {
+ IROLinear *op;
+ IROLinear *ind;
+
+ op = IRO_NewLinear(IROLinearOperand);
+ op->u.node = create_objectrefnode(obj);
+ op->rtype = op->u.node->data.objref->type;
+ op->index = ++IRO_NumLinear;
+ op->flags |= IROLF_Reffed | IROLF_Ind;
+ IRO_AddToList(op, list);
+
+ ind = IRO_NewLinear(IROLinearOp1Arg);
+ ind->nodetype = EINDIRECT;
+ ind->rtype = obj->type;
+ ind->u.monadic = op;
+ ind->index = ++IRO_NumLinear;
+ ind->next = NULL;
+ IRO_AddToList(ind, list);
+
+ return ind;
+}
+
+inline IROLinear *LocateFatherHelper(IROLinear *linear, Boolean a, IROLinear ***b) {
+ IROLinear *scan;
+ SInt32 index;
+ int i;
+
+ for (scan = linear->next, index = 0; index < (a ? 2 : 1); index++) {
+ while (scan) {
+ switch (scan->type) {
+ case IROLinearIf:
+ case IROLinearIfNot:
+ if (scan->u.label.x4 == linear) {
+ if (b)
+ *b = &scan->u.label.x4;
+ return scan;
+ }
+ break;
+ case IROLinearReturn:
+ if (scan->u.monadic == linear) {
+ if (b)
+ *b = &scan->u.monadic;
+ return scan;
+ }
+ break;
+ case IROLinearOp1Arg:
+ if (scan->u.monadic == linear) {
+ if (b)
+ *b = &scan->u.monadic;
+ return scan;
+ }
+ break;
+ case IROLinearSwitch:
+ if (scan->u.swtch.x4 == linear) {
+ if (b)
+ *b = &scan->u.swtch.x4;
+ return scan;
+ }
+ break;
+ case IROLinearOp2Arg:
+ if (scan->u.diadic.left == linear) {
+ if (b)
+ *b = &scan->u.diadic.left;
+ return scan;
+ }
+ if (scan->u.diadic.right == linear) {
+ if (b)
+ *b = &scan->u.diadic.right;
+ return scan;
+ }
+ break;
+ case IROLinearOp3Arg:
+ if (scan->u.args3.a == linear) {
+ if (b)
+ *b = &scan->u.args3.a;
+ return scan;
+ }
+ if (scan->u.args3.b == linear) {
+ if (b)
+ *b = &scan->u.args3.b;
+ return scan;
+ }
+ if (scan->u.args3.c == linear) {
+ if (b)
+ *b = &scan->u.args3.c;
+ return scan;
+ }
+ break;
+ case IROLinearFunccall:
+ if (scan->u.funccall.linear8 == linear) {
+ if (b)
+ *b = &scan->u.funccall.linear8;
+ return scan;
+ }
+ for (i = 0; i < scan->u.funccall.argCount; i++) {
+ if (scan->u.funccall.args[i] == linear) {
+ if (b)
+ *b = &scan->u.funccall.args[i];
+ return scan;
+ }
+ }
+ break;
+ case IROLinearNop:
+ case IROLinearOperand:
+ case IROLinearGoto:
+ case IROLinearLabel:
+ case IROLinearEntry:
+ case IROLinearExit:
+ case IROLinearBeginCatch:
+ case IROLinearEndCatch:
+ case IROLinearEndCatchDtor:
+ case IROLinearAsm:
+ case IROLinearEnd:
+ break;
+ default:
+#line 1536
+ CError_FATAL();
+ }
+ scan = scan->next;
+ }
+
+ scan = IRO_FirstLinear;
+ }
+
+ if (b)
+ *b = NULL;
+ return NULL;
+}
+
+IROLinear *IRO_LocateFather(IROLinear *linear) {
+ return LocateFatherHelper(linear, 0, NULL);
+}
+
+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);
+ IRO_NopOut(a);
+ *p = b;
+ }
+ return l;
+}
+
+IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b) {
+ IROLinear **p;
+ IROLinear *l = LocateFatherHelper(a, 0, &p);
+ if (l) {
+#line 1585
+ CError_ASSERT(p && *p);
+ *p = b;
+ }
+ return l;
+}
+
+void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b) {
+ IROLinear **ptr;
+ IROList list;
+
+ if (LocateFatherHelper(a, 1, &ptr)) {
+#line 1605
+ CError_ASSERT(ptr && *ptr);
+ IRO_InitList(&list);
+ *ptr = IRO_TempReference(obj, &list);
+ IRO_PasteAfter(list.head, list.tail, b);
+ if (a->flags & IROLF_LoopInvariant)
+ list.tail->flags |= IROLF_LoopInvariant;
+ } else {
+ IRO_Dump("Oh, oh, did not find reference to replace\n");
+ }
+}
+
+void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b) {
+ IROLinear **ptr;
+ IROList list;
+
+ if (LocateFatherHelper(a, 1, &ptr)) {
+#line 1664
+ CError_ASSERT(ptr && *ptr);
+ *ptr = b;
+ b->flags |= IROLF_Reffed;
+ } else {
+ IRO_Dump("Oh, oh, did not find reference to replace\n");
+ }
+}
+
+void IRO_GetTemp(IROExpr *expr) {
+}
+
+IROLinear *IRO_AssignToTemp(IROExpr *expr) {
+}
+
+IROLinear *IRO_FindStart(IROLinear *linear) {
+ ExprStart = ExprEnd = linear;
+ IRO_WalkTree(linear, FindStart);
+ return ExprStart;
+}
+
+void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr) {
+ IROLinear *scan;
+ for (scan = linear; scan; scan = scan->next) {
+ if (scan->nodetype == ECOMMA) {
+ if (scan != expr->linear) {
+ IRO_NopOut(scan->u.diadic.left);
+ IRO_LocateFather_Cut_And_Paste(scan, scan->u.diadic.right);
+ } else {
+ IRO_NopOut(scan->u.diadic.left);
+ expr->linear = scan->u.diadic.right;
+ }
+ }
+ }
+}
+
+void IRO_RemoveCommaNodeFromIR(void) {
+ IRONode *node;
+ IROLinear *linear;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ linear = node->first;
+ do {
+ if (!linear)
+ break;
+ if (linear->nodetype == ECOMMA) {
+ linear->u.diadic.left->flags &= ~IROLF_Reffed;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, linear->u.diadic.right);
+ linear->type = IROLinearNop;
+ }
+ linear = linear->next;
+ } while (linear != node->last);
+ }
+}
+
+IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear) {
+ IROAddrRecord *rec = oalloc(sizeof(IROAddrRecord));
+ rec->numObjRefs = 0;
+ rec->objRefs = NULL;
+ rec->numMisc = 0;
+ rec->misc = NULL;
+ rec->numInts = 0;
+ rec->ints = NULL;
+ rec->x16 = 0;
+ rec->linear = linear;
+ return rec;
+}
+
+IROLinear *IRO_HasSideEffect(IROLinear *linear) {
+ IROLinear *tmp;
+
+ if (!linear)
+ return linear;
+
+ if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS))
+ return linear;
+
+ switch (linear->type) {
+ case IROLinearAsm:
+ return linear;
+ case IROLinearOperand:
+ if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref))
+ return linear;
+ return NULL;
+ case IROLinearOp1Arg:
+ if (IRO_IsAssignOp[linear->nodetype])
+ return linear;
+ else
+ return IRO_HasSideEffect(linear->u.monadic);
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype])
+ return linear;
+ else if ((tmp = IRO_HasSideEffect(linear->u.diadic.left)))
+ return tmp;
+ else
+ return IRO_HasSideEffect(linear->u.diadic.right);
+ case IROLinearOp3Arg:
+ if ((tmp = IRO_HasSideEffect(linear->u.args3.a)))
+ return tmp;
+ else if ((tmp = IRO_HasSideEffect(linear->u.args3.b)))
+ return tmp;
+ else
+ return IRO_HasSideEffect(linear->u.args3.c);
+ case IROLinearFunccall:
+ return linear;
+ default:
+ return linear;
+ }
+}
+
+IROLinear *IRO_CheckSideEffect(IROLinear *linear) {
+ IROLinear *result;
+ IROLinear *tmp;
+ IROLinear *tmp2;
+ IROLinear *tmp3;
+
+ if (!linear)
+ return linear;
+
+ if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) {
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ }
+
+ result = NULL;
+ switch (linear->type) {
+ case IROLinearAsm:
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ case IROLinearOperand:
+ if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) {
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ }
+ break;
+ case IROLinearOp1Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ }
+ if ((result = IRO_CheckSideEffect(linear->u.monadic))) {
+ if (linear->nodetype == EINDIRECT && linear->u.monadic->type == IROLinearOperand) {
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ }
+ }
+ break;
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ }
+ tmp = IRO_CheckSideEffect(linear->u.diadic.left);
+ tmp2 = IRO_CheckSideEffect(linear->u.diadic.right);
+ if (tmp)
+ result = tmp;
+ else
+ result = tmp2;
+ break;
+ case IROLinearOp3Arg:
+ tmp = IRO_CheckSideEffect(linear->u.args3.a);
+ tmp2 = IRO_CheckSideEffect(linear->u.args3.b);
+ tmp3 = IRO_CheckSideEffect(linear->u.args3.c);
+ result = tmp ? tmp : tmp2 ? tmp2 : tmp3;
+ break;
+ case IROLinearFunccall:
+ linear->flags &= ~IROLF_Reffed;
+ return linear;
+ default:
+ return linear;
+ }
+
+ linear->type = IROLinearNop;
+ IRO_Dump("Nop out with side-effects checking at: %d\n", linear->index);
+ return result;
+}
+
+void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func) {
+ while (action) {
+ switch (action->type) {
+ case EAT_DESTROYLOCAL:
+ func(action->data.destroy_local.local);
+ break;
+ case EAT_DESTROYLOCALCOND:
+ func(action->data.destroy_local_cond.local);
+ func(action->data.destroy_local_cond.cond);
+ break;
+ case EAT_DESTROYLOCALOFFSET:
+ func(action->data.destroy_local_offset.local);
+ break;
+ case EAT_DESTROYLOCALPOINTER:
+ func(action->data.destroy_local_pointer.pointer);
+ break;
+ case EAT_DESTROYLOCALARRAY:
+ func(action->data.destroy_local_array.localarray);
+ break;
+ case EAT_DESTROYPARTIALARRAY:
+ func(action->data.destroy_partial_array.arraypointer);
+ func(action->data.destroy_partial_array.arraycounter);
+ func(action->data.destroy_partial_array.element_size);
+ break;
+ case EAT_DESTROYBASE:
+ func(action->data.destroy_member.objectptr); // wrong union?
+ break;
+ case EAT_DESTROYMEMBER:
+ func(action->data.destroy_member.objectptr);
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ func(action->data.destroy_member_cond.objectptr);
+ func(action->data.destroy_member_cond.cond);
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ func(action->data.destroy_member_array.objectptr);
+ break;
+ case EAT_DELETEPOINTER:
+ func(action->data.delete_pointer.pointerobject);
+ break;
+ case EAT_DELETEPOINTERCOND:
+ func(action->data.delete_pointer_cond.pointerobject);
+ func(action->data.delete_pointer_cond.cond);
+ break;
+ }
+ action = action->prev;
+ }
+}
+
+Boolean IRO_FunctionCallMightThrowException(IROLinear *linear) {
+ Object *obj;
+ if (linear->type == IROLinearFunccall) {
+ obj = NULL;
+ if (linear->u.funccall.linear8->type == IROLinearOperand && ENODE_IS(linear->u.funccall.linear8->u.node, EOBJREF))
+ obj = linear->u.funccall.linear8->u.node->data.objref;
+ if (!obj || CExcept_CanThrowException(obj, obj->datatype == DVFUNC && !(linear->nodeflags & ENODE_FLAG_80)))
+ return 1;
+ }
+ return 0;
+}
+
+IROLinear *IRO_NewIntConst(CInt64 val, Type *type) {
+ ENode *node;
+ IROLinear *linear;
+
+ node = IRO_NewENode(EINTCONST);
+ node->data.intval = val;
+ node->rtype = type;
+
+ linear = IRO_NewLinear(IROLinearOperand);
+ linear->index = ++IRO_NumLinear;
+ linear->rtype = type;
+ linear->u.node = node;
+ return linear;
+}
+
+IROLinear *IRO_NewFloatConst(Float val, Type *type) {
+ ENode *node;
+ IROLinear *linear;
+
+ node = IRO_NewENode(EFLOATCONST);
+ node->data.floatval = val;
+ node->rtype = type;
+
+ linear = IRO_NewLinear(IROLinearOperand);
+ linear->index = ++IRO_NumLinear;
+ linear->rtype = type;
+ linear->u.node = node;
+ return linear;
+}
+
+Boolean IRO_IsAddressMultiply(IROLinear *linear) {
+ return 0;
+}
+
+void IRO_SetupForUserBreakChecking(void) {
+ IRO_LastUserBreakTick = 0;
+}
+
+void IRO_CheckForUserBreak(void) {
+ if (IRO_LastUserBreakTick + 8 < COS_GetTicks()) {
+ if (CWUserBreak(cparams.context))
+ CError_UserBreak();
+ IRO_LastUserBreakTick = COS_GetTicks();
+ }
+}
+
diff --git a/compiler_and_linker/unsorted/IroVars.c b/compiler_and_linker/unsorted/IroVars.c
index e69de29..e306dd0 100644
--- a/compiler_and_linker/unsorted/IroVars.c
+++ b/compiler_and_linker/unsorted/IroVars.c
@@ -0,0 +1,1449 @@
+#include "compiler/IroVars.h"
+#include "compiler/IroDump.h"
+#include "compiler/IroFlowgraph.h"
+#include "compiler/IroJump.h"
+#include "compiler/IroLinearForm.h"
+#include "compiler/IroMalloc.h"
+#include "compiler/IroPointerAnalysis.h"
+#include "compiler/IroUtil.h"
+#include "compiler/IROUseDef.h"
+#include "compiler/CClass.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CParser.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/Exceptions.h"
+#include "compiler/objects.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/BitVector.h"
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct IndirectRecordMatch {
+ IROLinear *nd;
+ struct IndirectRecordMatch *otherMatches;
+} IndirectRecordMatch;
+
+typedef struct IndirectRecord {
+ IROLinear *linear;
+ unsigned char flags;
+ VarRecord *var;
+ SInt32 addend;
+ SInt32 size;
+ int startbit;
+ int endbit;
+ Type *type;
+ struct IndirectRecord *next;
+ IndirectRecordMatch *matches;
+ IROLinear *x26;
+} IndirectRecord;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static IndirectRecord *IRO_FirstIndirectRecord;
+static IndirectRecord *IRO_LastIndirectRecord;
+static IROLinear *TheBaseTerm;
+VarRecord *IRO_FirstVar;
+VarRecord *IRO_LastVar;
+SInt32 IRO_NumVars;
+Boolean IRO_IsBitField;
+SInt32 IRO_BaseTerms;
+SInt32 IRO_VarTerms;
+Boolean IRO_IsModifyOp[MAXEXPR];
+Boolean IRO_IsAssignOp[MAXEXPR];
+
+// forward decls
+static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag);
+static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type);
+static void DisableEntries(IndirectRecord *irec);
+static void DisableAddressedEntries(void);
+static UInt32 ObjectIsArg(Object *obj);
+
+void IRO_InitializeIRO_IsModifyOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ IRO_IsModifyOp[i] = 0;
+
+ IRO_IsModifyOp[EPOSTINC] = 1;
+ IRO_IsModifyOp[EPOSTDEC] = 1;
+ IRO_IsModifyOp[EPREINC] = 1;
+ IRO_IsModifyOp[EPREDEC] = 1;
+ IRO_IsModifyOp[EINDIRECT] = 0;
+ IRO_IsModifyOp[EMONMIN] = 0;
+ IRO_IsModifyOp[EBINNOT] = 0;
+ IRO_IsModifyOp[ELOGNOT] = 0;
+ IRO_IsModifyOp[EFORCELOAD] = 0;
+ IRO_IsModifyOp[EMUL] = 0;
+ IRO_IsModifyOp[EMULV] = 0;
+ IRO_IsModifyOp[EDIV] = 0;
+ IRO_IsModifyOp[EMODULO] = 0;
+ IRO_IsModifyOp[EADDV] = 0;
+ IRO_IsModifyOp[ESUBV] = 0;
+ IRO_IsModifyOp[EADD] = 0;
+ IRO_IsModifyOp[ESUB] = 0;
+ IRO_IsModifyOp[ESHL] = 0;
+ IRO_IsModifyOp[ESHR] = 0;
+ IRO_IsModifyOp[ELESS] = 0;
+ IRO_IsModifyOp[EGREATER] = 0;
+ IRO_IsModifyOp[ELESSEQU] = 0;
+ IRO_IsModifyOp[EGREATEREQU] = 0;
+ IRO_IsModifyOp[EEQU] = 0;
+ IRO_IsModifyOp[ENOTEQU] = 0;
+ IRO_IsModifyOp[EAND] = 0;
+ IRO_IsModifyOp[EXOR] = 0;
+ IRO_IsModifyOp[EOR] = 0;
+ IRO_IsModifyOp[ELAND] = 0;
+ IRO_IsModifyOp[ELOR] = 0;
+ IRO_IsModifyOp[EASS] = 0;
+ IRO_IsModifyOp[EMULASS] = 1;
+ IRO_IsModifyOp[EDIVASS] = 1;
+ IRO_IsModifyOp[EMODASS] = 1;
+ IRO_IsModifyOp[EADDASS] = 1;
+ IRO_IsModifyOp[ESUBASS] = 1;
+ IRO_IsModifyOp[ESHLASS] = 1;
+ IRO_IsModifyOp[ESHRASS] = 1;
+ IRO_IsModifyOp[EANDASS] = 1;
+ IRO_IsModifyOp[EXORASS] = 1;
+ IRO_IsModifyOp[EORASS] = 1;
+ IRO_IsModifyOp[ECOMMA] = 0;
+ IRO_IsModifyOp[EPMODULO] = 1;
+ IRO_IsModifyOp[EROTL] = 1;
+ IRO_IsModifyOp[EROTR] = 1;
+ IRO_IsModifyOp[EBCLR] = 1;
+ IRO_IsModifyOp[EBTST] = 1;
+ IRO_IsModifyOp[EBSET] = 1;
+ IRO_IsModifyOp[ETYPCON] = 0;
+ IRO_IsModifyOp[EBITFIELD] = 0;
+ IRO_IsModifyOp[EINTCONST] = 0;
+ IRO_IsModifyOp[EFLOATCONST] = 0;
+ IRO_IsModifyOp[ESTRINGCONST] = 0;
+ IRO_IsModifyOp[ECOND] = 0;
+ IRO_IsModifyOp[EFUNCCALL] = 0;
+ IRO_IsModifyOp[EFUNCCALLP] = 0;
+ IRO_IsModifyOp[EOBJREF] = 0;
+ IRO_IsModifyOp[EMFPOINTER] = 0;
+ IRO_IsModifyOp[ENULLCHECK] = 0;
+ IRO_IsModifyOp[EPRECOMP] = 0;
+ IRO_IsModifyOp[ETEMP] = 0;
+ IRO_IsModifyOp[EARGOBJ] = 0;
+ IRO_IsModifyOp[ELOCOBJ] = 0;
+ IRO_IsModifyOp[ELABEL] = 0;
+ IRO_IsModifyOp[ESETCONST] = 0;
+ IRO_IsModifyOp[ENEWEXCEPTION] = 0;
+ IRO_IsModifyOp[ENEWEXCEPTIONARRAY] = 0;
+ IRO_IsModifyOp[EOBJLIST] = 0;
+ IRO_IsModifyOp[EMEMBER] = 0;
+ IRO_IsModifyOp[ETEMPLDEP] = 0;
+ IRO_IsModifyOp[EINSTRUCTION] = 0;
+ IRO_IsModifyOp[EDEFINE] = 0;
+ IRO_IsModifyOp[EREUSE] = 0;
+ IRO_IsModifyOp[EASSBLK] = 0;
+ IRO_IsModifyOp[EVECTOR128CONST] = 0;
+ IRO_IsModifyOp[ECONDASS] = 1;
+}
+
+void IRO_InitializeIRO_IsAssignOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ IRO_IsAssignOp[i] = 0;
+
+ IRO_IsAssignOp[EPOSTINC] = 1;
+ IRO_IsAssignOp[EPOSTDEC] = 1;
+ IRO_IsAssignOp[EPREINC] = 1;
+ IRO_IsAssignOp[EPREDEC] = 1;
+ IRO_IsAssignOp[EINDIRECT] = 0;
+ IRO_IsAssignOp[EMONMIN] = 0;
+ IRO_IsAssignOp[EBINNOT] = 0;
+ IRO_IsAssignOp[ELOGNOT] = 0;
+ IRO_IsAssignOp[EFORCELOAD] = 0;
+ IRO_IsAssignOp[EMUL] = 0;
+ IRO_IsAssignOp[EMULV] = 0;
+ IRO_IsAssignOp[EDIV] = 0;
+ IRO_IsAssignOp[EMODULO] = 0;
+ IRO_IsAssignOp[EADDV] = 0;
+ IRO_IsAssignOp[ESUBV] = 0;
+ IRO_IsAssignOp[EADD] = 0;
+ IRO_IsAssignOp[ESUB] = 0;
+ IRO_IsAssignOp[ESHL] = 0;
+ IRO_IsAssignOp[ESHR] = 0;
+ IRO_IsAssignOp[ELESS] = 0;
+ IRO_IsAssignOp[EGREATER] = 0;
+ IRO_IsAssignOp[ELESSEQU] = 0;
+ IRO_IsAssignOp[EGREATEREQU] = 0;
+ IRO_IsAssignOp[EEQU] = 0;
+ IRO_IsAssignOp[ENOTEQU] = 0;
+ IRO_IsAssignOp[EAND] = 0;
+ IRO_IsAssignOp[EXOR] = 0;
+ IRO_IsAssignOp[EOR] = 0;
+ IRO_IsAssignOp[ELAND] = 0;
+ IRO_IsAssignOp[ELOR] = 0;
+ IRO_IsAssignOp[EASS] = 1;
+ IRO_IsAssignOp[EMULASS] = 1;
+ IRO_IsAssignOp[EDIVASS] = 1;
+ IRO_IsAssignOp[EMODASS] = 1;
+ IRO_IsAssignOp[EADDASS] = 1;
+ IRO_IsAssignOp[ESUBASS] = 1;
+ IRO_IsAssignOp[ESHLASS] = 1;
+ IRO_IsAssignOp[ESHRASS] = 1;
+ IRO_IsAssignOp[EANDASS] = 1;
+ IRO_IsAssignOp[EXORASS] = 1;
+ IRO_IsAssignOp[EORASS] = 1;
+ IRO_IsAssignOp[ECOMMA] = 0;
+ IRO_IsAssignOp[EPMODULO] = 1;
+ IRO_IsAssignOp[EROTL] = 1;
+ IRO_IsAssignOp[EROTR] = 1;
+ IRO_IsAssignOp[EBCLR] = 1;
+ IRO_IsAssignOp[EBTST] = 1;
+ IRO_IsAssignOp[EBSET] = 1;
+ IRO_IsAssignOp[ETYPCON] = 0;
+ IRO_IsAssignOp[EBITFIELD] = 0;
+ IRO_IsAssignOp[EINTCONST] = 0;
+ IRO_IsAssignOp[EFLOATCONST] = 0;
+ IRO_IsAssignOp[ESTRINGCONST] = 0;
+ IRO_IsAssignOp[ECOND] = 0;
+ IRO_IsAssignOp[EFUNCCALL] = 0;
+ IRO_IsAssignOp[EFUNCCALLP] = 0;
+ IRO_IsAssignOp[EOBJREF] = 0;
+ IRO_IsAssignOp[EMFPOINTER] = 0;
+ IRO_IsAssignOp[ENULLCHECK] = 0;
+ IRO_IsAssignOp[EPRECOMP] = 0;
+ IRO_IsAssignOp[ETEMP] = 0;
+ IRO_IsAssignOp[EARGOBJ] = 0;
+ IRO_IsAssignOp[ELOCOBJ] = 0;
+ IRO_IsAssignOp[ELABEL] = 0;
+ IRO_IsAssignOp[ESETCONST] = 0;
+ IRO_IsAssignOp[ENEWEXCEPTION] = 0;
+ IRO_IsAssignOp[ENEWEXCEPTIONARRAY] = 0;
+ IRO_IsAssignOp[EOBJLIST] = 0;
+ IRO_IsAssignOp[EMEMBER] = 0;
+ IRO_IsAssignOp[ETEMPLDEP] = 0;
+ IRO_IsAssignOp[EINSTRUCTION] = 0;
+ IRO_IsAssignOp[EDEFINE] = 0;
+ IRO_IsAssignOp[EREUSE] = 0;
+ IRO_IsAssignOp[EASSBLK] = 0;
+ IRO_IsAssignOp[EVECTOR128CONST] = 0;
+ IRO_IsAssignOp[ECONDASS] = 1;
+}
+
+VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2) {
+ VarRecord *var;
+ VarInfo *vi;
+
+ var = object->varptr;
+ if (!var && flag1) {
+ vi = NULL;
+ if (object->datatype == DLOCAL)
+ vi = object->u.var.info;
+ if (vi)
+ vi->usage = 0;
+ var = oalloc(sizeof(VarRecord));
+ var->object = object;
+ var->index = ++IRO_NumVars;
+ var->x6 = 0;
+ var->xA = 0;
+ var->next = NULL;
+ var->defs = NULL;
+ var->uses = NULL;
+ var->x1A = NULL;
+ var->x1E = NULL;
+ var->xB = 0;
+ if (IRO_FirstVar)
+ IRO_LastVar->next = var;
+ else
+ IRO_FirstVar = var;
+ IRO_LastVar = var;
+ object->varptr = var;
+ }
+
+ if (var && !flag2) {
+ var->xB = 1;
+ if (object->datatype == DLOCAL && object->u.var.info && object->u.var.info->noregister == 0)
+ object->u.var.info->noregister = 2;
+ }
+
+ return var;
+}
+
+static void ResetVars(void) {
+ VarRecord *var;
+
+ for (var = IRO_FirstVar; var; var = var->next) {
+ var->xB = 0;
+ if (var->object && var->object->datatype == DLOCAL && var->object->u.var.info) {
+ if (var->object->u.var.info->noregister == 2)
+ var->object->u.var.info->noregister = 0;
+ }
+ }
+}
+
+static void IRO_HandleExceptionActions(IROLinear *linear) {
+ ExceptionAction *action;
+
+ for (action = linear->stmt->dobjstack; action; action = action->prev) {
+ switch (action->type) {
+ case EAT_DESTROYLOCAL:
+ IRO_FindVar(action->data.destroy_local.local, 1, 0);
+ break;
+ case EAT_DESTROYLOCALCOND:
+ IRO_FindVar(action->data.destroy_local_cond.local, 1, 0);
+ break;
+ case EAT_DESTROYLOCALOFFSET:
+ IRO_FindVar(action->data.destroy_local_offset.local, 1, 0);
+ break;
+ case EAT_DESTROYLOCALARRAY:
+ IRO_FindVar(action->data.destroy_local_array.localarray, 1, 0);
+ break;
+ case EAT_DESTROYMEMBER:
+ case EAT_DESTROYBASE:
+ IRO_FindVar(action->data.destroy_member.objectptr, 1, 0);
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ IRO_FindVar(action->data.destroy_member_cond.objectptr, 1, 0);
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ IRO_FindVar(action->data.destroy_member_array.objectptr, 1, 0);
+ break;
+ case EAT_CATCHBLOCK:
+ if (action->data.catch_block.catch_object)
+ IRO_FindVar(action->data.catch_block.catch_object, 1, 0);
+ IRO_FindVar(action->data.catch_block.catch_info_object, 1, 0);
+ break;
+ case EAT_ACTIVECATCHBLOCK:
+ IRO_FindVar(action->data.active_catch_block.catch_info_object, 1, 0);
+ break;
+ }
+ }
+}
+
+void IRO_FindAllVars(void) {
+ IROLinear *linear;
+ VarRecord *var;
+
+ linear = IRO_FirstLinear;
+ IRO_NumVars = 0;
+ IRO_FirstVar = IRO_LastVar = NULL;
+
+ while (linear) {
+ if (IS_LINEAR_ENODE(linear, EOBJREF)) {
+ if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL)
+ IRO_FindVar(linear->u.node->data.objref, 1, (linear->flags & IROLF_Ind) != 0);
+ else
+ linear->u.node->data.objref->varptr = NULL;
+ } else if (linear->type == IROLinearFunccall) {
+ if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
+ IRO_HandleExceptionActions(linear);
+ } else if (linear->type == IROLinearAsm) {
+ IAEffects effects;
+ int i;
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+ for (i = 0; i < effects.numoperands; i++)
+ IRO_FindVar(effects.operands[i].object, 1, effects.operands[i].type != IAEffect_3);
+ }
+ linear = linear->next;
+ }
+
+ var = IRO_FirstVar;
+ Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1);
+ Bv_SetBit(0, IRO_FuncKills);
+ while (var) {
+ if (Inline_IsObjectData(var->object) || var->xB)
+ Bv_SetBit(var->index, IRO_FuncKills);
+ var = var->next;
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+void IRO_ZapVarPtrs(void) {
+ VarRecord *var;
+
+ for (var = IRO_FirstVar; var; var = var->next)
+ var->object->varptr = NULL;
+}
+
+void IRO_UpdateVars(void) {
+ IROLinear *linear;
+ VarRecord *var;
+
+ ResetVars();
+
+ for (linear = IRO_FirstLinear; linear; linear = linear->next) {
+ if (IS_LINEAR_ENODE(linear, EOBJREF)) {
+ if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL)
+ IRO_FindVar(linear->u.node->data.objref, 0, (linear->flags & IROLF_Ind) || !(linear->flags & IROLF_Reffed));
+ } else if (linear->type == IROLinearFunccall) {
+ if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
+ IRO_HandleExceptionActions(linear);
+ } else if (linear->type == IROLinearAsm) {
+ IAEffects effects;
+ int i;
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+ for (i = 0; i < effects.numoperands; i++)
+ IRO_FindVar(effects.operands[i].object, 0, effects.operands[i].type != IAEffect_3);
+ }
+ }
+
+ var = IRO_FirstVar;
+ Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1);
+ Bv_SetBit(0, IRO_FuncKills);
+ while (var) {
+ if (Inline_IsObjectData(var->object) || var->xB)
+ Bv_SetBit(var->index, IRO_FuncKills);
+ var = var->next;
+ }
+}
+
+void IRO_AddElmToList(IROLinear *linear, IROElmList **list) {
+ IROElmList *l = oalloc(sizeof(IROElmList));
+ l->element = linear;
+ l->next = NULL;
+ if (!*list) {
+ *list = l;
+ } else {
+ l->next = *list;
+ *list = l;
+ }
+}
+
+void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec) {
+ if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) {
+ IRO_DecomposeAddressExpression(linear->u.diadic.left, rec);
+ } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) {
+ rec->numInts++;
+ IRO_AddElmToList(linear->u.diadic.left, &rec->ints);
+ } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) {
+ rec->numObjRefs++;
+ IRO_AddElmToList(linear->u.diadic.left, &rec->objRefs);
+ } else {
+ rec->numMisc++;
+ IRO_AddElmToList(linear->u.diadic.left, &rec->misc);
+ }
+
+ if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) {
+ IRO_DecomposeAddressExpression(linear->u.diadic.right, rec);
+ } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
+ rec->numInts++;
+ IRO_AddElmToList(linear->u.diadic.right, &rec->ints);
+ } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) {
+ rec->numObjRefs++;
+ IRO_AddElmToList(linear->u.diadic.right, &rec->objRefs);
+ } else {
+ rec->numMisc++;
+ IRO_AddElmToList(linear->u.diadic.right, &rec->misc);
+ }
+}
+
+void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear) {
+ if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) {
+ IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.left);
+ } else if (!IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) {
+ if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) {
+ IRO_BaseTerms++;
+ TheBaseTerm = linear->u.diadic.left;
+ } else {
+ IRO_VarTerms++;
+ }
+ }
+
+ if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) {
+ IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.right);
+ } else if (!IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
+ if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) {
+ IRO_BaseTerms++;
+ TheBaseTerm = linear->u.diadic.right;
+ } else {
+ IRO_VarTerms++;
+ }
+ }
+}
+
+VarRecord *IRO_FindAssigned(IROLinear *linear) {
+ VarRecord *rec;
+
+ IRO_IsBitField = 0;
+ if (linear->type == IROLinearOp2Arg) {
+ linear = linear->u.diadic.left;
+ } else if (linear->type == IROLinearOp1Arg) {
+ linear = linear->u.monadic;
+ } else {
+#line 818
+ CError_FATAL();
+ }
+
+ if (IS_LINEAR_MONADIC(linear, EINDIRECT))
+ linear = linear->u.monadic;
+
+ if (IS_LINEAR_MONADIC(linear, EBITFIELD)) {
+ IRO_IsBitField = 1;
+ linear = linear->u.monadic;
+ }
+
+ if (IS_LINEAR_DIADIC(linear, EADD)) {
+ if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
+ linear = linear->u.diadic.left;
+ } else {
+ IRO_BaseTerms = 0;
+ IRO_DecomposeAddressExpression_Cheap(linear);
+ if (IRO_BaseTerms == 1)
+ linear = TheBaseTerm;
+ }
+ }
+
+ if (!IS_LINEAR_ENODE(linear, EOBJREF))
+ return NULL;
+
+ if ((rec = IRO_FindVar(linear->u.node->data.objref, 0, 1)))
+ return rec;
+ else
+ return NULL;
+}
+
+static void GetKillsByIndirectAssignment(IROLinear *linear) {
+ IROListNode *resultList;
+ IROLinear *nd;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *inner;
+ Boolean result;
+ Boolean foundLinear;
+
+ result = 0;
+
+ if (linear->type == IROLinearOp2Arg)
+ linear = linear->u.diadic.left;
+ else
+ linear = linear->u.monadic;
+
+ if (
+ linear &&
+ linear->type == IROLinearOp1Arg &&
+ linear->nodetype == EINDIRECT &&
+ (inner = linear->u.monadic) &&
+ copts.opt_pointer_analysis &&
+ inner->pointsToFunction &&
+ FunctionName
+ )
+ {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
+ if ((list = resultList)) {
+ for (scan = list; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundLinear = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundLinear = 1;
+ break;
+ }
+ }
+ if (!foundLinear) {
+ result = 1;
+ break;
+ }
+ }
+
+ if (!result) {
+ while (list) {
+ for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ Object *obj;
+ VarRecord *var;
+ int index;
+
+ obj = nd->u.node->data.objref;
+#line 952
+ CError_ASSERT(obj != NULL);
+
+ var = IRO_FindVar(obj, 1, 1);
+#line 954
+ CError_ASSERT(var != NULL);
+
+ index = var->index;
+#line 956
+ CError_ASSERT(index != 0);
+
+ Bv_SetBit(index, IRO_VarKills);
+ }
+ }
+
+ list = list->nextList;
+ }
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result)
+ Bv_Or(IRO_FuncKills, IRO_VarKills);
+}
+
+static void GetKillsByFunctionCall(IROLinear *linear) {
+ IROListNode *resultList;
+ IROLinear *nd;
+ IROListNode *list;
+ IROListNode *scan;
+ IROLinear *inner;
+ Boolean result;
+ Boolean foundLinear;
+ Object *obj;
+ ObjectList *killList;
+ ObjectList *olist;
+
+ result = 0;
+
+ if (
+ (inner = linear->u.funccall.linear8) &&
+ copts.opt_pointer_analysis &&
+ inner->pointsToFunction &&
+ FunctionName
+ )
+ {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
+ if (resultList) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundLinear = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundLinear = 1;
+ obj = nd->u.node->data.objref;
+#line 1028
+ CError_ASSERT(obj != NULL);
+
+ killList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, linear, &killList);
+
+ for (olist = killList; olist; olist = olist->next) {
+ if (!olist->object) {
+ result = 1;
+ break;
+ }
+ }
+
+ while (killList) {
+ ObjectList *next = killList->next;
+ IRO_free(killList);
+ killList = next;
+ }
+
+ if (result)
+ break;
+ }
+ }
+
+ if (!foundLinear)
+ result = 1;
+ if (result)
+ break;
+ }
+
+ if (!result) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ obj = nd->u.node->data.objref;
+ killList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, linear, &killList);
+
+ for (olist = killList; olist; olist = olist->next) {
+ VarRecord *var;
+ int index;
+
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 1079
+ CError_ASSERT(var != NULL);
+
+ index = var->index;
+#line 1081
+ CError_ASSERT(index != 0);
+
+ Bv_SetBit(index, IRO_VarKills);
+ }
+
+ while (killList) {
+ ObjectList *next = killList->next;
+ IRO_free(killList);
+ killList = next;
+ }
+ }
+ }
+ }
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ if (result)
+ Bv_Or(IRO_FuncKills, IRO_VarKills);
+}
+
+void IRO_GetKills(IROLinear *linear) {
+ VarRecord *var;
+
+ switch (linear->type) {
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ if (IRO_IsAssignOp[linear->nodetype]) {
+ IROLinear *assigned;
+ int index;
+
+ var = IRO_FindAssigned(linear);
+ index = 0;
+ if (var) index = var->index;
+ Bv_SetBit(index, IRO_VarKills);
+
+ if (!index)
+ GetKillsByIndirectAssignment(linear);
+ }
+ break;
+ case IROLinearFunccall:
+ GetKillsByFunctionCall(linear);
+ break;
+ case IROLinearAsm: {
+ IAEffects effects;
+ int i;
+
+ CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
+ for (i = 0; i < effects.numoperands; i++) {
+ switch (effects.operands[i].type) {
+ case IAEffect_1:
+ case IAEffect_2:
+ case IAEffect_4:
+ if ((var = IRO_FindVar(effects.operands[i].object, 0, 1)))
+ Bv_SetBit(var->index, IRO_VarKills);
+ break;
+ }
+ }
+
+ if (effects.x1 || effects.x4)
+ Bv_Or(IRO_FuncKills, IRO_VarKills);
+ break;
+ }
+ }
+}
+
+void IRO_CheckInit(void) {
+ IRONode *fnode;
+ IROLinear *nd;
+ VarRecord *var;
+ ObjectList *olist;
+ int flag;
+ int i;
+ BitVector *bv;
+
+ IRO_MakeReachable(IRO_FirstNode);
+ fnode = IRO_FirstNode;
+ Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
+
+ while (fnode) {
+ Bv_AllocVector(&fnode->x16, IRO_NumVars + 1);
+ Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1);
+
+ for (nd = fnode->first; nd; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ if (nd->flags & IROLF_Ind) {
+ if (!(nd->flags & IROLF_Assigned) || (nd->flags & IROLF_Used)) {
+ if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) {
+ if (!Bv_IsBitSet(var->index, fnode->x1E))
+ Bv_SetBit(var->index, fnode->x16);
+ }
+ }
+ } else {
+ if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 0))) {
+ Bv_SetBit(var->index, fnode->x1E);
+ }
+ }
+ } else if (nd->type == IROLinearOp2Arg && nd->nodetype == EASS) {
+ if ((var = IRO_FindAssigned(nd)))
+ Bv_SetBit(var->index, fnode->x1E);
+ } else if (nd->type == IROLinearAsm) {
+ IAEffects effects;
+
+ CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects);
+ for (i = 0; i < effects.numoperands; i++) {
+ var = IRO_FindVar(effects.operands[i].object, 0, 1);
+ switch (effects.operands[i].type) {
+ case IAEffect_1:
+ case IAEffect_2:
+ case IAEffect_4:
+ Bv_SetBit(var->index, fnode->x1E);
+ break;
+ }
+ }
+ }
+
+ if (nd == fnode->last)
+ break;
+ }
+
+ fnode = fnode->nextnode;
+ }
+
+ Bv_AllocVector(&bv, IRO_NumVars + 1);
+
+ do {
+ flag = 0;
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ Bv_Copy(fnode->x1E, bv);
+ for (i = 0; i < fnode->numpred; i++)
+ Bv_Or(IRO_NodeTable[fnode->pred[i]]->x1E, bv);
+ if (!Bv_Compare(bv, fnode->x1E)) {
+ Bv_Copy(bv, fnode->x1E);
+ flag = 1;
+ }
+ }
+ } while (flag);
+
+ Bv_Clear(IRO_VarKills);
+
+ for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
+ if (fnode->x36) {
+ Bv_Copy(fnode->x16, bv);
+ for (i = 0; i < fnode->numpred; i++)
+ Bv_Minus(IRO_NodeTable[fnode->pred[i]]->x1E, bv);
+ Bv_Or(bv, IRO_VarKills);
+ }
+ }
+
+ for (olist = locals; olist; olist = olist->next) {
+ if ((var = IRO_FindVar(olist->object, 0, 1)) && Bv_IsBitSet(var->index, IRO_VarKills)) {
+ VarInfo *vi = olist->object->u.var.info;
+ if (!IsTempName(olist->object->name) && !is_volatile_object(olist->object)) {
+ if (!IS_TYPE_CLASS(olist->object->type) || !CClass_IsEmpty(TYPE_CLASS(olist->object->type))) {
+ CError_SetErrorToken(&vi->deftoken);
+ CError_Warning(CErrorStr185, olist->object->name->name);
+ }
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static void RewriteIndDec(void) {
+ IROLinear *add;
+ IROLinear *indirect;
+ IROLinear *Int;
+ IROLinear *nd;
+ CInt64 value;
+ IROList list;
+
+ for (nd = IRO_FirstLinear; nd; nd = nd->next) {
+ if (
+ nd->type == IROLinearOp1Arg &&
+ (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) &&
+ !(nd->flags & IROLF_Reffed)
+ ) {
+ indirect = nd->u.monadic;
+ if (
+ indirect->type == IROLinearOp1Arg &&
+ indirect->nodetype == EINDIRECT &&
+ indirect->u.monadic->type == IROLinearOp1Arg &&
+ indirect->u.monadic->nodetype == EBITFIELD
+ ) {
+ value = IRO_GetSelfAssignmentVal(nd);
+ IRO_InitList(&list);
+
+ nd->type = IROLinearOp2Arg;
+ nd->nodetype = EASS;
+ nd->u.diadic.left = indirect;
+ IRO_DuplicateExpr(indirect, &list);
+
+ Int = IRO_NewIntConst(value, indirect->rtype);
+ Int->flags |= IROLF_Used | IROLF_Reffed;
+
+ add = IRO_NewLinear(IROLinearOp2Arg);
+ add->nodetype = EADD;
+ add->u.diadic.left = list.tail;
+ add->u.diadic.left->flags = 0;
+ add->u.diadic.left->flags |= IROLF_Used | IROLF_Reffed;
+ add->u.diadic.right = Int;
+ add->rtype = indirect->rtype;
+ add->flags = 0;
+ add->flags |= IROLF_Used | IROLF_Reffed;
+
+ nd->u.diadic.right = add;
+
+ IRO_AddToList(Int, &list);
+ IRO_AddToList(add, &list);
+ IRO_PasteAfter(list.head, list.tail, indirect);
+ }
+ }
+ }
+}
+
+void IRO_RewriteBitFieldTemps(void) {
+ IROLinear *nd;
+ IROLinear *expr2;
+ Object *obj;
+ VarRecord *var;
+ IROList list;
+
+ 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);
+
+ expr2 = var->x1E;
+#line 1532
+ CError_ASSERT(expr2 != NULL);
+
+ IRO_InitList(&list);
+ IRO_DuplicateExpr(expr2, &list);
+ IRO_NopOut(nd->u.monadic);
+ nd->u.monadic = list.tail;
+ IRO_Paste(list.head, list.tail, nd);
+ }
+ }
+}
+
+static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) {
+ IROLinear *funcnd;
+ IROLinear *nd;
+ IROListNode *scan;
+ IROListNode *resultList;
+ ObjectList *olist;
+ ObjectList *killList;
+ VarRecord *var;
+ Boolean result;
+ Boolean foundObjRef;
+ Object *obj;
+
+ result = 0;
+
+ funcnd = funccall->u.funccall.linear8;
+ if (funcnd && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList);
+
+ if (resultList) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = nd->u.node->data.objref;
+#line 1592
+ CError_ASSERT(obj != NULL);
+
+ killList = NULL;
+ PointerAnalysis_GetFunctionKills(obj, funccall, &killList);
+ for (olist = killList; olist; olist = olist->next) {
+ if (!olist->object) {
+ result = 1;
+ } else {
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 1604
+ CError_ASSERT(var != NULL);
+ if (var->xB)
+ result = 1;
+ }
+
+ if (result)
+ break;
+ }
+
+ while (killList) {
+ ObjectList *next = killList->next;
+ IRO_free(killList);
+ killList = next;
+ }
+
+ if (!result) {
+ killList = NULL;
+ PointerAnalysis_GetFunctionDependencies(obj, funccall, &killList);
+ for (olist = killList; olist; olist = olist->next) {
+ if (!olist->object) {
+ result = 1;
+ } else {
+ var = IRO_FindVar(olist->object, 1, 1);
+#line 1632
+ CError_ASSERT(var != NULL);
+ if (var->xB)
+ result = 1;
+ }
+
+ if (result)
+ break;
+ }
+
+ while (killList) {
+ ObjectList *next = killList->next;
+ IRO_free(killList);
+ killList = next;
+ }
+ }
+
+ if (result)
+ break;
+ }
+ }
+
+ if (!foundObjRef)
+ result = 1;
+ if (result)
+ break;
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ return result;
+}
+
+static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) {
+ Boolean result;
+ IROLinear *inner;
+ IROLinear *nd;
+ IROListNode *scan;
+ IROListNode *resultList;
+ Boolean foundObjRef;
+ Object *obj;
+ VarRecord *var;
+
+ result = 0;
+
+ if (
+ indirect &&
+ indirect->type == IROLinearOp1Arg &&
+ indirect->nodetype == EINDIRECT &&
+ (inner = indirect->u.monadic) &&
+ copts.opt_pointer_analysis &&
+ inner->pointsToFunction &&
+ FunctionName
+ ) {
+ resultList = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
+ if (resultList) {
+ for (scan = resultList; scan; scan = scan->nextList) {
+ if (!scan->list.head || !scan->list.tail) {
+ result = 1;
+ break;
+ }
+
+ foundObjRef = 0;
+ for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
+ if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
+ foundObjRef = 1;
+ obj = nd->u.node->data.objref;
+#line 1723
+ CError_ASSERT(obj != NULL);
+ var = IRO_FindVar(obj, 1, 1);
+#line 1725
+ CError_ASSERT(var != NULL);
+
+ if (var->xB)
+ result = 1;
+ }
+ }
+
+ if (!foundObjRef)
+ result = 1;
+ if (result)
+ break;
+ }
+
+ while (resultList) {
+ IROListNode *next = resultList->nextList;
+ IRO_free(resultList);
+ resultList = next;
+ }
+ } else {
+ result = 1;
+ }
+ } else {
+ result = 1;
+ }
+
+ return result;
+}
+
+void IRO_ScalarizeClassDataMembers(void) {
+ IROLinear *nd;
+ VarRecord *var;
+ Boolean flag;
+ Object *obj;
+ IndirectRecord *irec;
+ IndirectRecordMatch *match;
+ IROLinear *tmp;
+
+ nd = IRO_FirstLinear;
+ IRO_FirstIndirectRecord = NULL;
+ IRO_LastIndirectRecord = NULL;
+ RewriteIndDec();
+ IRO_DumpAfterPhase("RewriteIndDec", 0);
+ flag = 0;
+
+ while (nd) {
+ if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) {
+ CheckAddress(nd, &flag);
+ }
+ if (nd->type == IROLinearAsm) {
+ IAEffects effects;
+ 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))) {
+ CheckAddressConsistency(nd, var, -1, &stvoid);
+ } else {
+#line 1823
+ CError_FATAL();
+ }
+ }
+ }
+ if (nd->type == IROLinearFunccall && !flag)
+ flag = FunctionCallMightUseOrKillAnyAddressedVar(nd);
+
+ nd = nd->next;
+ }
+
+ if (flag)
+ DisableAddressedEntries();
+
+ for (irec = IRO_FirstIndirectRecord; irec; irec = irec->next) {
+ if (!(irec->flags & 1)) {
+ IROList list1;
+ IROList list2;
+
+ obj = create_temp_object(irec->type);
+ var = IRO_FindVar(obj, 1, 1);
+ for (match = irec->matches; match; match = match->otherMatches) {
+ IRO_InitList(&list1);
+ IRO_InitList(&list2);
+ IRO_DuplicateExpr(match->nd, &list1);
+ IRO_DuplicateExpr(match->nd, &list2);
+ if (match->nd->type == IROLinearOperand && match->nd->u.node->type == EOBJREF) {
+ tmp = IRO_LocateFather(match->nd);
+ if (irec->flags & 2) {
+ tmp->flags |= IROLF_BitfieldIndirect;
+ var->x1A = match->nd->rtype;
+ var->x1E = list2.tail;
+ }
+ match->nd->u.node = create_objectrefnode(obj);
+ irec->x26 = list2.tail;
+ } else {
+ tmp = IRO_LocateFather(match->nd);
+ if (irec->flags & 2) {
+ tmp->flags |= IROLF_BitfieldIndirect;
+ var->x1A = match->nd->rtype;
+ var->x1E = list2.tail;
+ }
+ irec->x26 = list2.tail;
+
+ IRO_NopOut(tmp->u.monadic);
+ tmp->u.monadic = IRO_NewLinear(IROLinearOperand);
+ tmp->u.monadic->u.node = create_objectrefnode(obj);
+ tmp->u.monadic->rtype = match->nd->rtype;
+ tmp->u.monadic->index = ++IRO_NumLinear;
+ tmp->u.monadic->flags |= IROLF_Ind | IROLF_Reffed;
+ IRO_NopOut(match->nd);
+ IRO_PasteAfter(tmp->u.monadic, tmp->u.monadic, match->nd);
+ }
+ }
+
+ if (ObjectIsArg(irec->var->object)) {
+ IROLinear *op1;
+ IROLinear *op2;
+ IROLinear *op3;
+ IROLinear *op4;
+ IROLinear *op5;
+
+ op1 = IRO_NewLinear(IROLinearOperand);
+ op1->u.node = create_objectrefnode(obj);
+ op1->rtype = op1->u.node->data.objref->type;
+ op1->index = ++IRO_NumLinear;
+ op1->flags |= IROLF_Ind | IROLF_Assigned;
+
+ op2 = list1.tail;
+
+ op3 = IRO_NewLinear(IROLinearOp1Arg);
+ op3->nodetype = EINDIRECT;
+ op3->rtype = irec->type;
+ op3->u.monadic = op1;
+ op3->index = ++IRO_NumLinear;
+ op3->flags |= IROLF_Assigned;
+
+ op4 = IRO_NewLinear(IROLinearOp1Arg);
+ op4->nodetype = EINDIRECT;
+ op4->rtype = irec->type;
+ op4->u.monadic = op2;
+ op4->index = ++IRO_NumLinear;
+ op4->flags |= IROLF_Reffed;
+
+ op5 = IRO_NewLinear(IROLinearOp2Arg);
+ op5->nodetype = EASS;
+ op5->u.diadic.left = op3;
+ op5->u.diadic.right = op4;
+ op5->rtype = irec->type;
+ op5->index = ++IRO_NumLinear;
+
+ op2->next = op4;
+ op4->next = op1;
+ op1->next = op3;
+ op3->next = op5;
+
+ IRO_PasteAfter(list1.head, op5, IRO_FirstLinear);
+ }
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) {
+ IROLinear *inner;
+ VarRecord *var;
+ Boolean result;
+
+ inner = nd->u.monadic;
+ if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD)
+ inner = inner->u.monadic;
+
+ result = 0;
+
+ if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) {
+ if (IS_TYPE_CLASS(inner->u.node->data.objref->type) || IS_TYPE_STRUCT(inner->u.node->data.objref->type) ||
+ 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);
+ CheckAddressConsistency(nd, var, 0, nd->rtype);
+ result = 1;
+ }
+ }
+ } else if (
+ inner->type == IROLinearOp2Arg &&
+ inner->nodetype == EADD &&
+ inner->u.diadic.left->type == IROLinearOperand &&
+ inner->u.diadic.left->u.node->type == EOBJREF) {
+ if (
+ inner->u.diadic.right->type == IROLinearOperand &&
+ inner->u.diadic.right->u.node->type == EINTCONST &&
+ inner->u.diadic.right->u.node->data.intval.hi == 0) {
+ if (
+ IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) ||
+ IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) ||
+ IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type)
+ ) {
+ 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);
+ CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype);
+ result = 1;
+ }
+ }
+ } else {
+ if (
+ IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) ||
+ IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) ||
+ IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type)
+ ) {
+ if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) {
+ var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1);
+ CheckAddressConsistency(nd, var, -1, nd->rtype);
+ result = 1;
+ }
+ }
+ }
+ }
+
+ if (!result && !*resultFlag) {
+ *resultFlag = IndirectMightUseOrKillAnyAddressedVar(nd);
+ }
+
+ return 0;
+}
+
+static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type) {
+ IndirectRecord *rp;
+ IndirectRecordMatch *match;
+ UInt32 flag;
+ IROLinear *inner;
+ UInt32 start_bit;
+ UInt32 end_bit;
+
+ flag = 0;
+ inner = nd->u.monadic;
+ if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) {
+ start_bit = TYPE_BITFIELD(inner->rtype)->unkA + 8 * addend;
+ end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->unkB - 1;
+ } else {
+ start_bit = 8 * addend;
+ end_bit = start_bit + 8 * type->size - 1;
+ }
+
+ if (var->xB && !copts.opt_pointer_analysis)
+ return 0;
+
+ if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS))
+ addend = -1;
+ if (is_volatile_object(var->object))
+ addend = -1;
+
+ for (rp = IRO_FirstIndirectRecord; rp; rp = rp->next) {
+ if (rp->var->index == var->index) {
+ if (rp->flags & 1)
+ return 0;
+
+ if (addend == -1) {
+ flag = 1;
+ break;
+ }
+
+ if (IRO_TypesEqual(rp->type, type) && rp->startbit == start_bit && rp->endbit == end_bit) {
+ match = oalloc(sizeof(IndirectRecordMatch));
+ match->nd = inner;
+ match->otherMatches = NULL;
+ if (!rp->matches) {
+ rp->matches = match;
+ } else {
+ match->otherMatches = rp->matches;
+ rp->matches = match;
+ }
+
+ IRO_Dump("Exact Match of Type and bits at %d and %d\n", rp->linear->index, nd->index);
+ IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
+ return 1;
+ }
+
+ if (rp->startbit == start_bit && rp->endbit == end_bit && !IRO_TypesEqual(rp->type, type)) {
+ IRO_Dump("match on bits but mismatch on type %d and %d\n", rp->linear->index, nd->index);
+ IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
+ flag = 1;
+ break;
+ }
+
+ if (rp->startbit >= start_bit && end_bit >= rp->startbit) {
+ IRO_Dump("Overlap detected --1 %d and %d\n", rp->linear->index, nd->index);
+ IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
+ flag = 1;
+ break;
+ }
+
+ if (rp->startbit < start_bit && rp->endbit >= start_bit) {
+ IRO_Dump("Overlap detected --2 %d and %d\n", rp->linear->index, nd->index);
+ IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
+ flag = 1;
+ break;
+ }
+ }
+ }
+
+ if (flag) {
+ DisableEntries(rp);
+ if (addend >= 0)
+ return 0;
+ }
+
+ IRO_Dump("Create Entry at %d\n", nd->index);
+ IRO_Dump("start_bit=%d,end_bit=%d\n", start_bit, end_bit);
+
+ rp = oalloc(sizeof(IndirectRecord));
+ rp->linear = nd;
+ rp->flags = 0;
+ rp->var = var;
+ rp->addend = addend;
+ rp->size = type->size;
+ rp->type = type;
+ rp->next = NULL;
+ rp->matches = oalloc(sizeof(IndirectRecordMatch));
+ rp->matches->nd = inner;
+ rp->matches->otherMatches = NULL;
+ rp->startbit = start_bit;
+ rp->endbit = end_bit;
+
+ if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT &&
+ nd->u.monadic->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EBITFIELD)
+ rp->flags |= 2;
+
+ if (!(IS_TYPE_FLOAT(type) || IS_TYPE_INT(type) || IS_TYPE_POINTER_ONLY(type)) ||
+ addend == -1 || ((inner->flags & IROLF_4000) && ObjectIsArg(var->object)))
+ rp->flags |= 1;
+
+ if (IRO_FirstIndirectRecord)
+ IRO_LastIndirectRecord->next = rp;
+ else
+ IRO_FirstIndirectRecord = rp;
+ IRO_LastIndirectRecord = rp;
+ return 1;
+}
+
+static void DisableEntries(IndirectRecord *irec) {
+ IndirectRecord *scan;
+
+ for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) {
+ if (irec->var->index == scan->var->index)
+ scan->flags |= 1;
+ }
+}
+
+static void DisableAddressedEntries(void) {
+ IndirectRecord *scan;
+
+ for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) {
+ if (scan->var->xB)
+ scan->flags |= 1;
+ }
+}
+
+static UInt32 ObjectIsArg(Object *obj) {
+ ObjectList *scan;
+
+ for (scan = arguments; scan; scan = scan->next) {
+ if (scan->object == obj)
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/compiler_and_linker/unsorted/LiveInfo.c b/compiler_and_linker/unsorted/LiveInfo.c
new file mode 100644
index 0000000..779efed
--- /dev/null
+++ b/compiler_and_linker/unsorted/LiveInfo.c
@@ -0,0 +1,167 @@
+#include "compiler/LiveInfo.h"
+#include "compiler/BitVectors.h"
+#include "compiler/Coloring.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/Registers.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler/CParser.h"
+
+LiveInfo *liveinfo;
+
+static void allocateliveinfo(void) {
+ UInt32 regs;
+ LiveInfo *info;
+ int i;
+
+ regs = used_virtual_registers[coloring_class];
+
+ liveinfo = oalloc(sizeof(LiveInfo) * pcblockcount);
+ for (i = 0, info = liveinfo; i < pcblockcount; i++, info++) {
+ bitvectorinitialize(info->vec0 = oalloc(4 * ((regs + 31) >> 5)), regs, 0);
+ bitvectorinitialize(info->vec4 = oalloc(4 * ((regs + 31) >> 5)), regs, 0);
+ bitvectorinitialize(info->vec8 = oalloc(4 * ((regs + 31) >> 5)), regs, 0);
+ bitvectorinitialize(info->vecC = oalloc(4 * ((regs + 31) >> 5)), regs, 0);
+ }
+}
+
+static void computelocalusedef(void) {
+ LiveInfo *info;
+ PCodeBlock *block;
+ PCode *instr;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ PCodeArg *op;
+ int i;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ info = &liveinfo[block->blockIndex];
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectRead) &&
+ !bitvectorgetbit(op->data.reg.reg, vec4)
+ )
+ bitvectorsetbit(op->data.reg.reg, vec0);
+ op++;
+ }
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == coloring_class &&
+ (op->data.reg.effect & EffectWrite) &&
+ !bitvectorgetbit(op->data.reg.reg, vec0)
+ )
+ bitvectorsetbit(op->data.reg.reg, vec4);
+ op++;
+ }
+ }
+ }
+}
+
+static void computeglobalinout(void) {
+ UInt32 regs;
+ LiveInfo *info;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ UInt32 *vec8;
+ UInt32 *vecC;
+ int bitvecsize;
+ int blockIndex;
+ int i;
+ int flag;
+ PCodeBlock *block;
+ PCLink *link;
+ UInt32 val;
+
+ regs = used_virtual_registers[coloring_class];
+ bitvecsize = (regs + 31) >> 5;
+ flag = 1;
+ while (flag) {
+ flag = 0;
+ blockIndex = pcblockcount;
+ while (blockIndex) {
+ if ((block = depthfirstordering[--blockIndex])) {
+ info = &liveinfo[block->blockIndex];
+ if ((link = block->successors)) {
+ vecC = info->vecC;
+ bitvectorcopy(vecC, liveinfo[link->block->blockIndex].vec8, regs);
+ for (link = link->nextLink; link; link = link->nextLink)
+ bitvectorunion(vecC, liveinfo[link->block->blockIndex].vec8, regs);
+ }
+
+ vecC = info->vecC;
+ vec8 = info->vec8;
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+ for (i = 0; i < bitvecsize; i++) {
+ val = *vec0 | (*vecC & ~*vec4);
+ if (val != *vec8) {
+ *vec8 = val;
+ flag = 1;
+ }
+ vec8++;
+ vecC++;
+ vec0++;
+ vec4++;
+ }
+ }
+ }
+ }
+}
+
+void computelivevariables(Object *proc) {
+ Type *returnType;
+
+ returnType = TYPE_FUNC(proc->type)->functype;
+ computedepthfirstordering();
+ allocateliveinfo();
+ computelocalusedef();
+
+ if (coloring_class == RegClass_GPR && TYPE_FITS_IN_REGISTER(returnType)) {
+ bitvectorsetbit(3, liveinfo[epilogue->blockIndex].vec0);
+ if (TYPE_IS_8BYTES(returnType))
+ bitvectorsetbit(4, liveinfo[pclastblock->blockIndex].vec0);
+ } else if (coloring_class == RegClass_FPR && IS_TYPE_FLOAT(returnType)) {
+ bitvectorsetbit(1, liveinfo[epilogue->blockIndex].vec0);
+ } else if (coloring_class == RegClass_VR && IS_TYPE_VECTOR(returnType)) {
+ bitvectorsetbit(2, liveinfo[epilogue->blockIndex].vec0);
+ }
+
+ computeglobalinout();
+}
+
+int dead(PCode *instr, char rclass, UInt32 *vec) {
+ int i;
+ PCodeArg *op;
+
+ if (instr->flags & (fPCodeFlag1 | fPCodeFlag4 | fPCodeFlag8 | fIsVolatile | fSideEffects))
+ return 0;
+ if (instr->block->flags & (fPCBlockFlag1 | fPCBlockFlag2))
+ return 0;
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (op->data.reg.effect & EffectWrite) &&
+ (rclass != (char) op->arg || bitvectorgetbit(op->data.reg.reg, vec))
+ )
+ return 0;
+ op++;
+ }
+
+ return copts.optimizationlevel > 0;
+}
diff --git a/compiler_and_linker/unsorted/LoadDeletion.c b/compiler_and_linker/unsorted/LoadDeletion.c
index e69de29..316e8c2 100644
--- a/compiler_and_linker/unsorted/LoadDeletion.c
+++ b/compiler_and_linker/unsorted/LoadDeletion.c
@@ -0,0 +1,46 @@
+#include "compiler/LoadDeletion.h"
+#include "compiler/CopyPropagation.h"
+#include "compiler/CParser.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+
+int deletedloads;
+
+static int is_load(PCode *instr) {
+ return
+ (instr->op == PC_LI || instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW)
+ &&
+ instr->args[0].data.reg.reg >= n_real_registers[(char) instr->args[0].arg];
+}
+
+static int loadpropagatestouse(int candidateID, int useID) {
+ return 0;
+}
+
+static void deleteload(int id) {
+ Candidate *candidate;
+
+ candidate = Candidates + id;
+ if (candidate->list || (candidate->pcode->flags & fSideEffects))
+ return;
+ if (candidate->pcode->args[0].data.reg.reg < n_real_registers[(char) candidate->pcode->args[0].arg])
+ return;
+
+ deletepcode(candidate->pcode);
+ deletedloads = 1;
+}
+
+static Propagation load_immediate_prop = {
+ &is_load,
+ &loadpropagatestouse,
+ &deleteload,
+ "LOAD IMMEDIATE",
+ "LOAD_IMMEDIATES",
+ "l%ld",
+ 0
+};
+
+void deletedeadloads(Object *proc) {
+ propagateinstructions(proc, &load_immediate_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 0);
+ deletedloads = propagated_instructions;
+}
diff --git a/compiler_and_linker/unsorted/LoopDetection.c b/compiler_and_linker/unsorted/LoopDetection.c
index e69de29..54bc180 100644
--- a/compiler_and_linker/unsorted/LoopDetection.c
+++ b/compiler_and_linker/unsorted/LoopDetection.c
@@ -0,0 +1,889 @@
+#include "compiler/LoopDetection.h"
+#include "compiler/CFunc.h"
+#include "compiler/PCode.h"
+#include "compiler/TOC.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/BitVectors.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+
+Loop *loopsinflowgraph;
+int loopdetection_nblocks;
+static UInt32 **dominators;
+static BlockList *loopheaders;
+static int nloopheaders;
+static PCodeBlock **loopstack;
+BitVector *LoopTemp;
+void *LoopList_First;
+
+static void computedominators(void) {
+ int i;
+ PCodeBlock *block;
+ int blockCount;
+ int flag;
+ UInt32 *myvec;
+ PCLink *link;
+
+ blockCount = pcblockcount;
+ flag = 1;
+
+ dominators = oalloc(sizeof(UInt32 *) * pcblockcount);
+ for (i = 0; i < pcblockcount; i++)
+ dominators[i] = oalloc(4 * ((blockCount + 31) >> 5));
+
+ myvec = oalloc(4 * ((blockCount + 31) >> 5));
+
+ bitvectorinitialize(dominators[pcbasicblocks->blockIndex], blockCount, 0);
+ //dominators[pcbasicblocks->blockIndex][0] |= 1;
+ bitvectorsetbit(0, dominators[pcbasicblocks->blockIndex]);
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock)
+ bitvectorinitialize(dominators[block->blockIndex], blockCount, 0xFFFFFFFF);
+
+ computedepthfirstordering();
+
+ while (flag) {
+ flag = 0;
+ for (i = 0; i < pcblockcount; i++) {
+ block = depthfirstordering[i];
+ if (block && block->blockIndex != pcbasicblocks->blockIndex) {
+ bitvectorcopy(myvec, dominators[block->predecessors->block->blockIndex], blockCount);
+ for (link = block->predecessors->nextLink; link; link = link->nextLink)
+ bitvectorintersect(myvec, dominators[link->block->blockIndex], blockCount);
+ //myvec[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31);
+ bitvectorsetbit(block->blockIndex, myvec);
+
+ if (bitvectorchanged(dominators[block->blockIndex], myvec, blockCount))
+ flag = 1;
+ }
+ }
+ }
+}
+
+static BlockList *findloopheaders(void) {
+ PCodeBlock *block;
+ PCLink *link;
+ BlockList *list;
+
+ loopheaders = NULL;
+ nloopheaders = 0;
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
+ for (link = block->predecessors; link; link = link->nextLink) {
+ //if ((1 << (block->blockIndex & 31)) & dominators[link->block->blockIndex][block->blockIndex >> 5])
+ if (bitvectorgetbit(block->blockIndex, dominators[link->block->blockIndex]))
+ break;
+ }
+
+ if (link) {
+ list = oalloc(sizeof(BlockList));
+ list->block = block;
+ list->next = loopheaders;
+ loopheaders = list;
+ nloopheaders++;
+ }
+ }
+
+ return loopheaders;
+}
+
+void addblocktoloop(Loop *loop, PCodeBlock *block) {
+ BlockList *list = lalloc(sizeof(BlockList));
+
+ //loop->memberblocks[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31);
+ bitvectorsetbit(block->blockIndex, loop->memberblocks);
+
+ list->block = block;
+ list->next = loop->blocks;
+ loop->blocks = list;
+}
+
+static void findnaturalloop(Loop *loop) {
+ BlockList *list;
+ BlockList *list2;
+ PCLink *link;
+ PCodeBlock *block;
+ int i;
+
+ i = 0;
+ addblocktoloop(loop, loop->body);
+ for (link = loop->body->predecessors; link; link = link->nextLink) {
+ if (bitvectorgetbit(loop->body->blockIndex, dominators[link->block->blockIndex]) && link->block != loop->body) {
+ addblocktoloop(loop, link->block);
+ loopstack[i++] = link->block;
+ }
+ }
+
+ while (i) {
+ link = loopstack[--i]->predecessors;
+ while (link) {
+ if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ addblocktoloop(loop, link->block);
+ loopstack[i++] = link->block;
+ }
+ link = link->nextLink;
+ }
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ block = list->block;
+ for (link = block->successors; link; link = link->nextLink) {
+ if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ bitvectorsetbit(block->blockIndex, loop->vec24);
+ break;
+ }
+ }
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ for (list2 = loop->blocks; list2; list2 = list2->next) {
+ if (bitvectorgetbit(list2->block->blockIndex, loop->vec24) &&
+ !bitvectorgetbit(list->block->blockIndex, dominators[list2->block->blockIndex]))
+ break;
+ }
+
+ if (!list2)
+ bitvectorsetbit(list->block->blockIndex, loop->vec28);
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ for (link = loop->body->predecessors; link; link = link->nextLink) {
+ if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks) &&
+ !bitvectorgetbit(list->block->blockIndex, dominators[link->block->blockIndex]))
+ break;
+ }
+
+ if (!link)
+ bitvectorsetbit(list->block->blockIndex, loop->vec2C);
+ }
+}
+
+static void addlooptolist(Loop *loop, Loop **list) {
+ Loop **scan;
+ Loop *scanloop;
+
+ scan = list;
+ while ((scanloop = *scan)) {
+ if (bitvectorgetbit(loop->body->blockIndex, scanloop->memberblocks)) {
+ loop->parent = scanloop;
+ addlooptolist(loop, &scanloop->children);
+ return;
+ }
+
+ if (bitvectorgetbit(scanloop->body->blockIndex, loop->memberblocks)) {
+ *scan = scanloop->nextSibling;
+ scanloop->parent = loop;
+ scanloop->nextSibling = loop->children;
+ loop->children = scanloop;
+ } else {
+ scan = &scanloop->nextSibling;
+ }
+ }
+
+ loop->nextSibling = *list;
+ *list = loop;
+}
+
+static void findnaturalloops(void) {
+ Loop *loop;
+ int size;
+
+ loopdetection_nblocks = pcblockcount + 5 * nloopheaders;
+ loopstack = oalloc(sizeof(PCodeBlock *) * pcblockcount);
+ while (loopheaders) {
+ loop = lalloc(sizeof(Loop));
+ loop->parent = loop->nextSibling = loop->children = NULL;
+ loop->body = loopheaders->block;
+ loop->preheader = NULL;
+ loop->blocks = NULL;
+ loop->basicInductionVars = NULL;
+ loop->footer = NULL;
+ loop->pc18 = NULL;
+ loop->loopWeight = loop->body->loopWeight;
+
+ bitvectorinitialize(loop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+
+ findnaturalloop(loop);
+ addlooptolist(loop, &loopsinflowgraph);
+
+ loopheaders = loopheaders->next;
+ }
+}
+
+static PCodeBlock *makepreheaderblock(void) {
+ PCodeLabel *label;
+ PCodeBlock *block;
+
+ label = makepclabel();
+ block = lalloc(sizeof(PCodeBlock));
+ block->nextBlock = NULL;
+ block->prevBlock = NULL;
+ block->labels = NULL;
+ block->successors = NULL;
+ block->predecessors = NULL;
+ block->firstPCode = block->lastPCode = NULL;
+ block->pcodeCount = 0;
+ block->flags = 0;
+ block->blockIndex = pcblockcount++;
+ pclabel(block, label);
+ return block;
+}
+
+static void insertpreheaderbefore(PCodeBlock *a, PCodeBlock *b) {
+ a->nextBlock = b;
+ a->prevBlock = b->prevBlock;
+ b->prevBlock->nextBlock = a;
+ b->prevBlock = a;
+}
+
+void insertpreheaderblock(Loop *loop) {
+ PCodeBlock *preheader;
+ PCodeBlock *block29;
+ PCodeBlock *block28;
+ PCode *pcode27;
+ PCLink *link; // r26
+ PCLink **linkptr; // r25
+ PCodeLabel *newlabel; // r23
+ PCLink *innerlink;
+ PCodeBlock *block;
+ PCodeArg *arg;
+ int i;
+
+ preheader = loop->preheader = makepreheaderblock();
+ block29 = NULL;
+ block28 = loop->body;
+
+ if (!block28->labels)
+ pclabel(block28, makepclabel());
+
+ appendpcode(preheader, makepcode(PC_B, block28->labels));
+ preheader->loopWeight = loop->parent ? loop->parent->loopWeight : 1;
+
+ linkptr = &block28->predecessors;
+ while ((link = *linkptr)) {
+ if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ linkptr = &link->nextLink;
+ } else {
+ if (link->block->pcodeCount) {
+ pcode27 = link->block->lastPCode;
+ if (pcode27->op == PC_B) {
+#line 462
+ CError_ASSERT(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);
+ if (pcode27->args[2].data.label.label->block == block28)
+ pcode27->args[2].data.label.label = preheader->labels;
+ } else if (pcode27->op == PC_BCTR) {
+ if (pcode27->argCount > 1 && pcode27->args[1].kind == PCOp_MEMORY) {
+ Object *obj = pcode27->args[1].data.mem.obj;
+ PCodeLabel **array = (PCodeLabel **) obj->u.data.u.switchtable.data;
+ int i;
+ for (i = 0; i < obj->u.data.u.switchtable.size; i++) {
+ if (array[i]->block == block28)
+ array[i] = preheader->labels;
+ }
+ } else {
+ CodeLabelList *cll;
+ for (cll = codelabellist; cll; cll = cll->next) {
+ if (cll->label->pclabel->block == block28)
+ cll->label->pclabel = preheader->labels;
+ }
+ }
+ } else {
+#line 505
+ CError_ASSERT(link->block->nextBlock == block28);
+ }
+ }
+
+ for (innerlink = link->block->successors; innerlink; innerlink = innerlink->nextLink) {
+ if (innerlink->block == block28)
+ innerlink->block = preheader;
+ }
+
+ *linkptr = link->nextLink;;
+ link->nextLink = preheader->predecessors;
+ preheader->predecessors = link;
+ }
+ }
+
+ if (!bitvectorgetbit(block28->prevBlock->blockIndex, loop->memberblocks)) {
+ insertpreheaderbefore(preheader, block28);
+
+ if (
+ (!block28->nextBlock || !bitvectorgetbit(block28->nextBlock->blockIndex, loop->memberblocks)) &&
+ block28->lastPCode &&
+ (block28->lastPCode->flags & fPCodeFlag1) &&
+ block28->lastPCode->op != PC_BDNZ
+ ) {
+ i = block28->lastPCode->argCount;
+ arg = block28->lastPCode->args;
+ while (i && arg->kind != PCOp_LABEL) {
+ arg++;
+ i--;
+ }
+
+ if (i && arg->kind == PCOp_LABEL && arg->data.label.label->block == block28) {
+ block29 = makepreheaderblock();
+ insertpreheaderbefore(block29, block28);
+ newlabel = makepclabel();
+ pclabel(block29, newlabel);
+ arg->data.label.label = newlabel;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = block29->predecessors;
+ block29->predecessors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = block29->successors;
+ block29->successors = link;
+
+ for (link = block28->successors; link; link = link->nextLink) {
+ if (link->block == block28)
+ link->block = block29;
+ }
+ for (link = block28->predecessors; link; link = link->nextLink) {
+ if (link->block == block28)
+ link->block = block29;
+ }
+
+ bitvectorsetbit(block29->blockIndex, loop->vec2C);
+ addblocktoloop(loop, block29);
+ }
+ }
+ } else {
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (bitvectorgetbit(block->blockIndex, loop->memberblocks))
+ break;
+ }
+ insertpreheaderbefore(preheader, block);
+ }
+
+ link = lalloc(sizeof(PCLink));
+ link->block = preheader;
+ link->nextLink = block28->predecessors;
+ block28->predecessors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = preheader->successors;
+ preheader->successors = link;
+
+ for (loop = loop->parent; loop; loop = loop->parent) {
+ addblocktoloop(loop, preheader);
+ if (bitvectorgetbit(block28->blockIndex, loop->vec28)) {
+ bitvectorsetbit(preheader->blockIndex, loop->vec28);
+ if (block29)
+ bitvectorsetbit(block29->blockIndex, loop->vec28);
+ }
+ if (bitvectorgetbit(block28->blockIndex, loop->vec2C)) {
+ bitvectorsetbit(preheader->blockIndex, loop->vec2C);
+ if (block29)
+ bitvectorsetbit(block29->blockIndex, loop->vec2C);
+ }
+ }
+}
+
+static void insertpreheaderblocks(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ insertpreheaderblocks(loop->children);
+ insertpreheaderblock(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void findloopsinflowgraph(void) {
+ loopsinflowgraph = NULL;
+ computedominators();
+ if (findloopheaders()) {
+ findnaturalloops();
+ insertpreheaderblocks(loopsinflowgraph);
+ }
+ freeoheap();
+}
+
+static int checklooplimits(SInt32 opcode, SInt32 condition, SInt32 c, SInt32 d, SInt32 addend, SInt32 *result) {
+ if (opcode == PC_BT) {
+ if (condition == 0) {
+ if (addend <= 0)
+ return 0;
+ if (c < d)
+ *result = (d - c + addend - 1) / addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend >= 0)
+ return 0;
+ if (c > d)
+ *result = (c - d - addend - 1) / -addend;
+ else
+ *result = 0;
+ } else {
+ return 0;
+ }
+ } else {
+ if (condition == 0) {
+ if (addend >= 0)
+ return 0;
+ if (c >= d)
+ *result = (c - d - addend) / -addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend <= 0)
+ return 0;
+ if (c <= d)
+ *result = (d - c + addend) / addend;
+ else
+ *result = 0;
+ } else if (c < d) {
+ if (addend <= 0)
+ return 0;
+ if ((d - c) % addend)
+ return 0;
+ *result = (d - c) / addend;
+ } else if (c > d) {
+ if (addend >= 0)
+ return 0;
+ if ((c - d) % -addend)
+ return 0;
+ *result = (c - d) / -addend;
+ } else {
+ *result = 0;
+ }
+ }
+
+ return 1;
+}
+
+static int checkunsignedlooplimits(SInt32 opcode, SInt32 condition, UInt32 c, UInt32 d, SInt32 addend, UInt32 *result) {
+ if (opcode == PC_BT) {
+ if (condition == 0) {
+ if (addend <= 0)
+ return 0;
+ if (c < d)
+ *result = (d - c + addend - 1) / addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend >= 0)
+ return 0;
+ if (c > d)
+ *result = (c - d - addend - 1) / -addend;
+ else
+ *result = 0;
+ } else {
+ return 0;
+ }
+ } else {
+ if (condition == 0) {
+ if (addend >= 0)
+ return 0;
+ if (c >= d)
+ *result = (c - d - addend) / -addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend <= 0)
+ return 0;
+ if (c <= d)
+ *result = (d - c + addend) / addend;
+ else
+ *result = 0;
+ } else if (c < d) {
+ if (addend <= 0)
+ return 0;
+ if ((d - c) % addend)
+ return 0;
+ *result = (d - c) / addend;
+ } else if (c > d) {
+ if (addend >= 0)
+ return 0;
+ if ((c - d) % -addend)
+ return 0;
+ *result = (c - d) / -addend;
+ } else {
+ *result = 0;
+ }
+ }
+
+ return (*result & 0x80000000) == 0;
+}
+
+static int checkunknownloop(int a, int b, int c, unsigned char *op) {
+ if (a == PC_BT) {
+ if (b == 0) {
+ if (c <= 0)
+ return 0;
+ *op = ELESS;
+ } else if (b == 1) {
+ if (c >= 0)
+ return 0;
+ *op = EGREATER;
+ } else {
+ return 0;
+ }
+ } else {
+ if (b == 0) {
+ if (c >= 0)
+ return 0;
+ *op = EGREATEREQU;
+ } else if (b == 1) {
+ if (c <= 0)
+ return 0;
+ *op = ELESSEQU;
+ } else if (c == 1) {
+ *op = ENOTEQU;
+ } else if (c == -1) {
+ *op = ENOTEQU;
+ } else {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void checkcountingloop(Loop *loop) {
+ RegUseOrDef *list;
+ PCode *lastpcode;
+ PCode *prevpcode;
+ PCode *pc8;
+ PCode *check;
+ short op12;
+ short reg11;
+ SInt16 reg4;
+ short reg11b;
+ Loop *child;
+
+ if (!(lastpcode = loop->body->lastPCode))
+ return;
+ if (lastpcode->op != PC_BT && lastpcode->op != PC_BF)
+ return;
+ if (lastpcode->args[2].kind != PCOp_LABEL)
+ return;
+
+ if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks))
+ return;
+ if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks))
+ return;
+
+ reg11 = lastpcode->args[0].data.reg.reg;
+ reg4 = lastpcode->args[1].data.imm.value;
+ prevpcode = lastpcode->prevPCode;
+ if (!prevpcode)
+ return;
+
+ op12 = prevpcode->op;
+ if (op12 == PC_ADDI && prevpcode->args[2].kind == PCOp_IMMEDIATE) {
+ pc8 = prevpcode;
+ prevpcode = prevpcode->prevPCode;
+ if (!prevpcode)
+ return;
+
+ op12 = prevpcode->op;
+ if (pc8->args[0].data.reg.reg != pc8->args[1].data.reg.reg)
+ return;
+ if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI)
+ return;
+ if (prevpcode->args[1].data.reg.reg == pc8->args[0].data.reg.reg)
+ return;
+ if ((loop->step = pc8->args[2].data.imm.value) == 0)
+ return;
+ }
+
+ if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI)
+ return;
+
+ if (prevpcode->args[0].data.reg.reg != reg11)
+ return;
+
+ reg11b = prevpcode->args[1].data.reg.reg;
+ if (reg11b < 32)
+ return;
+
+ if (loop->preheader->nextBlock != lastpcode->args[2].data.label.label->block)
+ return;
+
+ if (op12 == PC_CMPI) {
+ if (prevpcode->prevPCode)
+ return;
+ loop->upper = prevpcode->args[2].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (op12 == PC_CMPLI) {
+ if (prevpcode->prevPCode)
+ return;
+ loop->upper = prevpcode->args[2].data.imm.value & 0xFFFF;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (op12 == PC_CMP || op12 == PC_CMPL) {
+ if (prevpcode->prevPCode) {
+ if (
+ prevpcode->prevPCode->op == PC_LI &&
+ prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[1].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ prevpcode->prevPCode->op == PC_LIS &&
+ prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[1].data.imm.value << 16;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ prevpcode->prevPCode->op == PC_ADDI &&
+ prevpcode->prevPCode->args[2].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ prevpcode->prevPCode->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ prevpcode->prevPCode->prevPCode &&
+ prevpcode->prevPCode->prevPCode->op == PC_LIS &&
+ prevpcode->prevPCode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[2].data.imm.value +
+ (prevpcode->prevPCode->prevPCode->args[1].data.imm.value << 16);
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else {
+ return;
+ }
+ } else {
+ pc8 = NULL;
+ for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks))
+ return;
+ }
+ for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) {
+ if (!pc8) {
+ pc8 = Defs[list->id].pcode;
+ if (
+ pc8->op == PC_LI &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->upper = pc8->args[1].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_LIS &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->upper = pc8->args[1].data.imm.value << 16;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_ADDI &&
+ pc8->args[2].kind == PCOp_IMMEDIATE &&
+ pc8->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ pc8->prevPCode &&
+ pc8->prevPCode->op == PC_LIS &&
+ pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ pc8->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg
+ ) {
+ loop->upper = pc8->args[2].data.imm.value +
+ (pc8->prevPCode->args[1].data.imm.value << 16);
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else {
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ } else {
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ }
+ }
+
+ if (loop->upperType == LOOP_BOUND_INDETERMINATE)
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ }
+ }
+
+ pc8 = NULL;
+
+ for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) {
+ check = Defs[list->id].pcode;
+ if (bitvectorgetbit(check->block->blockIndex, loop->memberblocks)) {
+ if (!pc8) {
+ pc8 = check;
+ if (check->op != PC_ADDI)
+ return;
+ if (check->args[1].data.reg.reg != reg11b)
+ return;
+ if (check->args[2].kind != PCOp_IMMEDIATE)
+ return;
+ if ((loop->step = check->args[2].data.imm.value) == 0)
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ if (!pc8)
+ return;
+
+ if (pc8->block != prevpcode->block && !bitvectorgetbit(prevpcode->block->blockIndex, loop->vec2C))
+ return;
+
+ if (loop->children) {
+ for (child = loop->children; child; child = child->nextSibling) {
+ if (bitvectorgetbit(pc8->block->blockIndex, child->memberblocks))
+ return;
+ }
+ }
+
+ loop->pc18 = pc8;
+
+ pc8 = NULL;
+
+ for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) {
+ if (!pc8) {
+ pc8 = Defs[list->id].pcode;
+ if (
+ pc8->op == PC_LI &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->lower = pc8->args[1].data.imm.value;
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_LIS &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->lower = pc8->args[1].data.imm.value << 16;
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_ADDI &&
+ pc8->args[2].kind == PCOp_IMMEDIATE &&
+ pc8->args[1].data.reg.reg == reg11b &&
+ pc8->prevPCode &&
+ pc8->prevPCode->op == PC_LIS &&
+ pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ pc8->prevPCode->args[0].data.reg.reg == reg11b
+ ) {
+ loop->lower = pc8->args[2].data.imm.value +
+ (pc8->prevPCode->args[1].data.imm.value << 16);
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else {
+ loop->lowerType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ } else {
+ loop->lowerType = LOOP_BOUND_INDETERMINATE;
+ break;
+ }
+ }
+ }
+
+ if (loop->lowerType == LOOP_BOUND_INDETERMINATE)
+ loop->lowerType = LOOP_BOUND_VARIABLE;
+
+ if (loop->lowerType == LOOP_BOUND_CONSTANT && loop->upperType == LOOP_BOUND_CONSTANT) {
+ if (op12 == PC_CMP || op12 == PC_CMPI) {
+ if (!checklooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, &loop->iterationCount))
+ return;
+ } else {
+ if (!checkunsignedlooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, (UInt32 *) &loop->iterationCount))
+ return;
+ }
+ loop->isKnownCountingLoop = 1;
+ } else if (loop->lowerType != LOOP_BOUND_INDETERMINATE || loop->upperType != LOOP_BOUND_INDETERMINATE) {
+ if (!checkunknownloop(lastpcode->op, reg4, loop->step, &loop->unknownCondition))
+ return;
+ loop->isUnknownCountingLoop = 1;
+ }
+}
+
+void analyzeForCountableLoops(Loop *loop) {
+ if (!loop)
+ return;
+
+ while (loop) {
+ if (loop->children)
+ analyzeForCountableLoops(loop->children);
+ checkcountingloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void analyzeloop(Loop *loop) {
+ BlockList *list;
+ PCodeBlock *block;
+ PCode *pcode;
+
+ loop->bodySize = 0;
+ loop->x4D = 0;
+ loop->x4E = 0;
+ loop->x4F = 1;
+ loop->isKnownCountingLoop = 0;
+ loop->isUnknownCountingLoop = 0;
+ loop->lowerType = LOOP_BOUND_INDETERMINATE;
+ loop->upperType = LOOP_BOUND_INDETERMINATE;
+ loop->iterationCount = -1;
+ loop->x57 = 0;
+ loop->x52 = 0;
+
+ for (list = loop->blocks; list; list = list->next) {
+ block = list->block;
+ if (!loop->children)
+ block->flags |= fPCBlockFlag2000;
+ loop->bodySize += block->pcodeCount;
+
+ if (block != loop->body) {
+ if (!block->successors || !block->predecessors || block->successors->nextLink || block->predecessors->nextLink)
+ loop->x4F = 0;
+ }
+
+ if ((block->flags & fPCBlockFlag4000) == fPCBlockFlag4000)
+ loop->x52 = 1;
+
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (PCODE_FLAG_SET_T(pcode) & fLink)
+ loop->x4D = 1;
+
+ if (pcode->op == PC_BCTRL || pcode->op == PC_BCTR || pcode->op == PC_BCCTR || pcode->op == PC_MTCTR || pcode->op == PC_MFCTR) {
+ loop->x4E = 1;
+ } else if (pcode->flags & fPCodeFlag2) {
+ if (pcode->op == PC_LBZX || pcode->op == PC_LHZX || pcode->op == PC_LHAX || pcode->op == PC_LWZX || pcode->op == PC_LFSX || pcode->op == PC_LFDX)
+ loop->x53 = 1;
+ } else if (pcode->flags & fPCodeFlag4) {
+ if (pcode->op == PC_STBX || pcode->op == PC_STHX || pcode->op == PC_STWX || pcode->op == PC_STFSX || pcode->op == PC_STFDX)
+ loop->x54 = 1;
+ } else {
+ if (pcode->op == PC_EIEIO || pcode->op == PC_SYNC || pcode->op == PC_ISYNC)
+ loop->x57 = 1;
+ }
+ }
+ }
+
+ if (!loop->children && !loop->x4D && loop->bodySize < 32) {
+ for (list = loop->blocks; list; list = list->next)
+ list->block->flags |= fPCBlockFlag2000;
+ }
+}
+
+static void analyzeloops(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ analyzeloops(loop->children);
+ analyzeloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void analyzeloopsinflowgraph(void) {
+ if (loopsinflowgraph)
+ analyzeloops(loopsinflowgraph);
+}
+
diff --git a/compiler_and_linker/unsorted/LoopOptimization.c b/compiler_and_linker/unsorted/LoopOptimization.c
index e69de29..6472119 100644
--- a/compiler_and_linker/unsorted/LoopOptimization.c
+++ b/compiler_and_linker/unsorted/LoopOptimization.c
@@ -0,0 +1,1565 @@
+#include "compiler/LoopOptimization.h"
+#include "compiler/CFunc.h"
+#include "compiler/CParser.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/LoopDetection.h"
+#include "compiler/PCode.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+int optimizedloops;
+int optimizedloop_full_unroll;
+int optimizedloop_trans_regs;
+static UInt32 *liveonexit;
+static UInt32 *inductionvariables;
+static int last_virtual_GPR;
+
+static int ispowerof2(SInt32 value) {
+ int bit = getbit(value);
+ return (bit > 0 && bit < 31) ? bit : 0;
+}
+
+static void insertupdateinstructions(Loop *loop) {
+ // nothing
+}
+
+static void computeliveonexit(Loop *loop) {
+ UInt32 *usevec;
+ UInt32 *defvec;
+ BlockList *blocklist;
+ RegUseOrDef *list;
+ int gpr;
+
+ bitvectorinitialize(usevec = oalloc(4 * ((number_of_Uses + 31) >> 5)), number_of_Uses, 0);
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ if (bitvectorgetbit(blocklist->block->blockIndex, loop->vec24))
+ bitvectorunion(usevec, usedefinfo[blocklist->block->blockIndex].usevec1C, number_of_Uses);
+ }
+
+ bitvectorinitialize(defvec = oalloc(4 * ((number_of_Defs + 31) >> 5)), number_of_Defs, 0);
+ if (loop->preheader)
+ bitvectorunion(defvec, usedefinfo[loop->preheader->blockIndex].defvec8, number_of_Defs);
+
+ bitvectorinitialize(liveonexit, last_virtual_GPR, 0);
+
+ for (gpr = 32; gpr < last_virtual_GPR; gpr++) {
+ for (list = reg_Defs[RegClass_GPR][gpr]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, defvec)) {
+ if (!Defs[list->id].pcode->block || bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) {
+ bitvectorsetbit(gpr, liveonexit);
+ break;
+ }
+ }
+ }
+
+ for (list = reg_Uses[RegClass_GPR][gpr]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usevec)) {
+ if (!Uses[list->id].pcode->block || !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) {
+ bitvectorsetbit(gpr, liveonexit);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void eliminateinductionvariables(Loop *loop) {
+ BlockList *blocklist;
+ PCode *instr;
+ PCode *nextInstr;
+ PCodeArg *op;
+ int i;
+
+ bitvectorinitialize(inductionvariables, last_virtual_GPR, 0xFFFFFFFF);
+
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ for (instr = blocklist->block->firstPCode; instr; instr = instr->nextPCode) {
+ if (
+ instr->op != PC_ADDI ||
+ instr->args[0].data.reg.reg < 32 ||
+ instr->args[0].data.reg.reg >= last_virtual_GPR ||
+ instr->args[1].data.reg.reg != instr->args[0].data.reg.reg
+ ) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg >= n_real_registers[RegClass_GPR] &&
+ op->data.reg.reg < last_virtual_GPR
+ )
+ bitvectorclearbit(op->data.reg.reg, inductionvariables);
+ op++;
+ }
+ }
+ }
+ }
+
+ if (loop->parent) {
+ for (instr = loop->preheader->firstPCode; instr; instr = nextInstr) {
+ nextInstr = instr->nextPCode;
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg >= n_real_registers[RegClass_GPR] &&
+ op->data.reg.reg < last_virtual_GPR
+ )
+ bitvectorsetbit(op->data.reg.reg, liveonexit);
+ op++;
+ }
+ }
+ }
+
+ for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) {
+ for (instr = blocklist->block->firstPCode; instr; instr = nextInstr) {
+ nextInstr = instr->nextPCode;
+ if (
+ instr->op == PC_ADDI &&
+ instr->args[0].data.reg.reg >= 32 &&
+ instr->args[0].data.reg.reg < last_virtual_GPR &&
+ instr->args[1].data.reg.reg == instr->args[0].data.reg.reg &&
+ bitvectorgetbit(instr->args[0].data.reg.reg, inductionvariables) &&
+ !bitvectorgetbit(instr->args[0].data.reg.reg, liveonexit)
+ ) {
+ deletepcode(instr);
+ optimizedloops = 1;
+ }
+ }
+ }
+}
+
+static void skiplooptest(Loop *loop) {
+ PCodeBlock *preheader;
+ PCodeLabel *label;
+ PCLink **ptr;
+ PCLink *link;
+ PCode *lastInstr;
+ PCode *instr;
+
+ preheader = loop->preheader;
+ lastInstr = loop->body->lastPCode;
+#line 340
+ CError_ASSERT(lastInstr->args[2].kind == PCOp_LABEL);
+
+ label = lastInstr->args[2].data.label.label;
+ preheader->lastPCode->args[0].data.label.label = label;
+ preheader->successors->block = label->block;
+
+ ptr = &loop->body->predecessors;
+ while ((link = *ptr)) {
+ if (link->block == preheader) {
+ *ptr = link->nextLink;
+ break;
+ }
+ ptr = &link->nextLink;
+ }
+
+ link->nextLink = label->block->predecessors;
+ label->block->predecessors = link;
+
+ while (1) {
+ instr = loop->body->firstPCode;
+#line 369
+ CError_ASSERT(instr);
+
+ if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL)
+ break;
+
+ deletepcode(instr);
+ insertpcodebefore(loop->preheader->lastPCode, instr);
+ loop->bodySize--;
+ }
+
+ for (instr = instr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode)
+ insertpcodebefore(loop->preheader->lastPCode, copypcode(instr));
+}
+
+static void unrollloop(Loop *loop) {
+ PCodeBlock *newBlock;
+ int i;
+ int factor;
+ PCode *instr;
+ PCodeBlock *block;
+ PCode *firstInstr;
+ PCode *nextInstr;
+
+ for (factor = copts.ppc_unroll_factor_limit; factor > 1; factor--) {
+ if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.ppc_unroll_instructions_limit)
+ break;
+ }
+
+ if (factor == 1)
+ return;
+ if ((loop->iterationCount / factor) != 1 && loop->bodySize < 4)
+ return;
+
+ newBlock = oalloc(sizeof(PCodeBlock));
+ 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();
+ }
+
+ for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode)
+ appendpcode(newBlock, copypcode(instr));
+
+ for (block = loop->preheader->successors->block; block != loop->body; block = block->successors->block) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->op != PC_B)
+ appendpcode(newBlock, copypcode(instr));
+ }
+ }
+ }
+
+ block = loop->body->predecessors->block;
+ for (instr = newBlock->firstPCode; instr; instr = nextInstr) {
+ nextInstr = instr->nextPCode;
+ appendpcode(block, instr);
+ }
+ loop->iterationCount /= factor;
+}
+
+void pccomputepredecessors1(PCodeBlock *block) {
+ PCLink *succ;
+ PCLink *pred;
+
+ for (succ = block->successors; succ; succ = succ->nextLink) {
+ if (!succ->block) {
+#line 496
+ CError_FATAL();
+ } else {
+ for (pred = succ->block->predecessors; pred; pred = pred->nextLink) {
+ if (pred->block == block)
+ break;
+ }
+
+ if (!pred) {
+ pred = lalloc(sizeof(PCLink));
+ pred->block = block;
+ pred->nextLink = succ->block->predecessors;
+ succ->block->predecessors = pred;
+ }
+ }
+ }
+}
+
+static PCodeBlock *insertnewpcblock(PCodeBlock *block, int loopWeight) {
+ PCodeBlock *newBlock;
+ PCodeBlock *nextBlock;
+ PCodeLabel *label;
+ PCLink *prev;
+ PCLink *link;
+
+ label = makepclabel();
+ newBlock = lalloc(sizeof(PCodeBlock));
+
+ nextBlock = block->nextBlock;
+ newBlock->nextBlock = nextBlock;
+ block->nextBlock = newBlock;
+
+ newBlock->prevBlock = block;
+ nextBlock->prevBlock = newBlock;
+
+ newBlock->labels = NULL;
+ newBlock->predecessors = newBlock->successors = NULL;
+ newBlock->firstPCode = newBlock->lastPCode = NULL;
+ newBlock->pcodeCount = 0;
+ newBlock->loopWeight = loopWeight;
+ newBlock->flags = 0;
+ newBlock->blockIndex = pcblockcount++;
+ pclabel(newBlock, label);
+
+ prev = NULL;
+ for (link = block->successors; link; link = link->nextLink) {
+ if (link->block == nextBlock) {
+ if (!prev)
+ block->successors = link->nextLink;
+ else
+ prev->nextLink = link->nextLink;
+ link->nextLink = NULL;
+ newBlock->successors = link;
+ break;
+ }
+ prev = link;
+ }
+
+ prev = NULL;
+ for (link = nextBlock->predecessors; link; link = link->nextLink) {
+ if (link->block == block) {
+ if (!prev)
+ nextBlock->predecessors = link->nextLink;
+ else
+ prev->nextLink = link->nextLink;
+ link->nextLink = NULL;
+ newBlock->predecessors = link;
+ break;
+ }
+ prev = link;
+ }
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newBlock;
+ link->nextLink = block->successors;
+ block->successors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newBlock;
+ link->nextLink = nextBlock->predecessors;
+ nextBlock->predecessors = link;
+
+ return newBlock;
+}
+
+static void unrollloopconditional(Loop *loop) {
+ PCodeBlock *lastBlock;
+ PCodeLabel *label24;
+ PCode *instr;
+ PCode *instrCopy;
+ int outputBlockCount;
+ int inputBlockCount;
+ PCodeBlock **blocks;
+ PCodeBlock **blocks2;
+ PCodeBlock **blocks3;
+ PCode *firstInstr;
+ int factor;
+ PCodeBlock *block;
+ PCLink *link;
+ PCLink *prev;
+ int i;
+ int j;
+ int k;
+ int instructionCount;
+
+ label24 = NULL;
+ outputBlockCount = 0;
+ instructionCount = 0;
+
+ for (factor = copts.ppc_unroll_factor_limit; factor > 1; factor--) {
+ if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.ppc_unroll_instructions_limit)
+ break;
+ }
+
+ if (factor == 1)
+ return;
+
+ inputBlockCount = 0;
+ for (block = loop->preheader->successors->block; block != loop->body; block = block->nextBlock) {
+ inputBlockCount++;
+ if (!bitvectorgetbit(block->blockIndex, loop->memberblocks))
+ instructionCount += block->pcodeCount;
+ }
+
+ if ((loop->bodySize - instructionCount - 2) < instructionCount || instructionCount > 8)
+ return;
+
+ blocks = oalloc(inputBlockCount * sizeof(PCodeBlock *));
+ blocks2 = oalloc(inputBlockCount * sizeof(PCodeBlock *));
+ blocks3 = oalloc(factor * (inputBlockCount * sizeof(PCodeBlock *)));
+ memclrw(blocks, inputBlockCount * sizeof(PCodeBlock *));
+ memclrw(blocks2, inputBlockCount * sizeof(PCodeBlock *));
+ memclrw(blocks3, factor * (inputBlockCount * sizeof(PCodeBlock *)));
+
+ block = loop->preheader->nextBlock;
+ for (i = 0; i < inputBlockCount; i++) {
+ blocks[i] = block;
+ block = block->nextBlock;
+ }
+
+ lastBlock = blocks[inputBlockCount - 1];
+ for (i = 0; i < factor - 1; i++) {
+ for (j = 0; j < inputBlockCount; j++) {
+ blocks2[j] = insertnewpcblock(lastBlock, loop->loopWeight);
+ blocks3[outputBlockCount++] = blocks2[j];
+ lastBlock = blocks2[j];
+ }
+ if (label24) {
+ pclabel(blocks2[0], label24);
+ label24 = NULL;
+ }
+
+ for (j = 0; j < inputBlockCount; j++) {
+ for (instr = blocks[j]->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->flags & fPCodeFlag1) {
+ PCodeArg *op;
+ int opID;
+ instrCopy = copypcode(instr);
+ op = NULL;
+ for (opID = 0; opID < instr->argCount; opID++) {
+ if (instr->args[opID].kind == PCOp_LABEL) {
+ op = &instr->args[opID];
+ break;
+ }
+ }
+
+ if (op) {
+ if (op->data.label.label->block == loop->body) {
+ if (!label24)
+ label24 = makepclabel();
+ instrCopy->args[opID].data.label.label = label24;
+ } else {
+ for (k = 0; k < inputBlockCount; k++) {
+ if (op->data.label.label->block == blocks[k]) {
+ instrCopy->args[opID].data.label.label = blocks2[k]->labels;
+ break;
+ }
+ }
+ }
+ }
+
+ appendpcode(blocks2[j], instrCopy);
+ if (op)
+ pcbranch(blocks2[j], instrCopy->args[opID].data.label.label);
+ } else {
+ appendpcode(blocks2[j], copypcode(instr));
+ }
+ }
+ }
+
+ 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();
+ }
+
+ for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode)
+ appendpcode(blocks2[inputBlockCount - 1], copypcode(instr));
+
+ for (j = 0; j < inputBlockCount; j++) {
+ for (link = blocks[j]->successors; link; link = link->nextLink) {
+ if (link->block == blocks[j]->nextBlock)
+ break;
+ }
+
+ if (!link) {
+ for (link = blocks2[j]->successors, prev = NULL; link; link = link->nextLink) {
+ if (link->block == blocks2[j]->nextBlock) {
+ if (prev)
+ prev->nextLink = link->nextLink;
+ else
+ blocks2[j]->successors = link->nextLink;
+ } else {
+ prev = link;
+ }
+ }
+
+ for (link = blocks2[j]->nextBlock->predecessors, prev = NULL; link; link = link->nextLink) {
+ if (link->block == blocks2[j]) {
+ if (prev)
+ prev->nextLink = link->nextLink;
+ else
+ blocks2[j]->nextBlock->predecessors = link->nextLink;
+ } else {
+ prev = link;
+ }
+ }
+ }
+ }
+ }
+
+ if (label24)
+ pclabel(loop->body, label24);
+
+ for (i = 0; i < inputBlockCount; i++) {
+ for (instr = blocks[i]->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->flags & fPCodeFlag1) {
+ PCodeArg *op;
+ int opID;
+ op = NULL;
+ for (opID = 0; opID < instr->argCount; opID++) {
+ if (instr->args[opID].kind == PCOp_LABEL) {
+ op = &instr->args[opID];
+ break;
+ }
+ }
+
+ if (op && op->data.label.label->block == loop->body) {
+ instr->args[opID].data.label.label = blocks3[0]->labels;
+
+ for (link = blocks[i]->successors, prev = NULL; link; link = link->nextLink) {
+ if (link->block == loop->body) {
+ if (prev)
+ prev->nextLink = link->nextLink;
+ else
+ blocks[i]->successors = link->nextLink;
+ } else {
+ prev = link;
+ }
+ }
+
+ for (link = loop->body->predecessors, prev = NULL; link; link = link->nextLink) {
+ if (link->block == blocks[i]) {
+ if (prev)
+ prev->nextLink = link->nextLink;
+ else
+ loop->body->predecessors = link->nextLink;
+ } else {
+ prev = link;
+ }
+ }
+
+ link = blocks[i]->successors;
+ while (link && link->block != blocks3[0])
+ link = link->nextLink;
+
+ if (!link) {
+ pcbranch(blocks[i], op->data.label.label);
+ pccomputepredecessors1(blocks[i]);
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < outputBlockCount; i++)
+ pccomputepredecessors1(blocks3[i]);
+
+ loop->iterationCount /= factor;
+}
+
+static void unrollunknownBDNZ(Loop *loop) {
+ int factor; // r29
+ PCodeBlock *preheader; // r17
+ PCodeBlock *blockA; // r23
+ PCodeBlock *postheader; // r22
+ PCodeBlock *newblock1; // r26
+ PCodeBlock *newblock2; // r31
+ PCodeBlock *newblock3; // r19
+ PCodeBlock *newblock4; // r20
+ PCodeBlock *newblock5; // r24
+ PCode *mtctr; // r21
+ int mtctr_reg; // r27
+ PCode *instr28; // r28
+ PCode *instr6; // r6
+ PCodeBlock *block;
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+ int val;
+ short mtctr_shifted_reg; // r16
+ short reg25; // r25
+ PCLink *link;
+
+ if (loop->bodySize < 4)
+ return;
+
+ factor = 128;
+ while (factor > copts.ppc_unroll_factor_limit)
+ factor >>= 1;
+ while (factor > 1 && (loop->bodySize - 2) * factor > copts.ppc_unroll_instructions_limit)
+ factor >>= 1;
+
+ if (factor < 2)
+ return;
+
+ preheader = loop->preheader;
+ blockA = loop->body->nextBlock;
+ postheader = preheader->nextBlock;
+
+ newblock1 = insertnewpcblock(preheader, loop->loopWeight);
+ newblock2 = insertnewpcblock(newblock1, loop->loopWeight);
+ newblock3 = insertnewpcblock(newblock2, loop->loopWeight);
+ newblock4 = insertnewpcblock(newblock3, loop->loopWeight);
+ newblock5 = insertnewpcblock(newblock4, loop->loopWeight);
+ addblocktoloop(loop, newblock1);
+ addblocktoloop(loop, newblock2);
+ addblocktoloop(loop, newblock3);
+ addblocktoloop(loop, newblock4);
+ addblocktoloop(loop, newblock5);
+
+ for (instr = preheader->lastPCode; instr; instr = instr->prevPCode) {
+ if (instr->op == PC_MTCTR) {
+ mtctr = instr;
+ mtctr_reg = instr->args[0].data.reg.reg;
+ }
+ }
+
+ if (!mtctr)
+ return;
+
+ instr28 = NULL;
+ for (block = postheader; block != loop->body; block = block->successors->block) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->op != PC_B) {
+ appendpcode(newblock2, copypcode(instr));
+ if (instr == loop->pc18)
+ instr28 = newblock2->lastPCode;
+ }
+ }
+ }
+
+ if (!instr28) {
+ appendpcode(newblock2, copypcode(loop->pc18));
+ instr28 = newblock2->lastPCode;
+ }
+
+ instr6 = NULL;
+ for (instr = newblock2->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr != instr28) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg == loop->pc18->args[0].data.reg.reg &&
+ (op->data.reg.effect & (EffectRead | EffectWrite))
+ ) {
+ instr6 = instr;
+ break;
+ }
+ op++;
+ }
+ }
+ if (instr6)
+ break;
+ }
+
+ if (!instr6) {
+ deletepcode(instr28);
+ deletepcode(loop->pc18);
+ if (loop->footer)
+ blockA = loop->footer;
+ else
+ blockA = insertnewpcblock(loop->body, loop->loopWeight);
+ } else {
+ instr28 = NULL;
+ }
+
+ for (i = 1; i < factor; i++) {
+ for (block = postheader; block != loop->body; block = block->successors->block) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->op != PC_B)
+ appendpcode(newblock2, copypcode(instr));
+ }
+ }
+ }
+
+ mtctr_shifted_reg = used_virtual_registers[RegClass_GPR]++;
+ appendpcode(newblock1, makepcode(
+ PC_RLWINM,
+ mtctr_shifted_reg,
+ mtctr_reg,
+ 32 - ispowerof2(factor),
+ ispowerof2(factor),
+ 31));
+
+ appendpcode(newblock1, makepcode(PC_CMPLI, 0, mtctr_shifted_reg, 0));
+
+ if (instr28) {
+ reg25 = used_virtual_registers[RegClass_GPR]++;
+ if (loop->step == 1) {
+ instr = makepcode(PC_MR, reg25, mtctr_reg);
+ } else if (loop->step == -1) {
+ instr = makepcode(PC_NEG, reg25, mtctr_reg);
+ } else {
+ val = ispowerof2(abs(loop->step));
+ if (val > 0) {
+ instr = makepcode(PC_RLWINM, reg25, mtctr_reg, val, 0, 31 - val);
+ if (loop->step < 0) {
+ appendpcode(newblock1, instr);
+ instr = makepcode(PC_NEG, reg25, reg25);
+ }
+ } else {
+ instr = makepcode(PC_MULLI, reg25, mtctr_reg, loop->step);
+ }
+ }
+ appendpcode(newblock1, instr);
+ }
+
+ appendpcode(newblock1, makepcode(PC_MTCTR, mtctr_shifted_reg));
+ appendpcode(newblock1, makepcode(PC_BT, 0, 2, newblock5->labels));
+ pcbranch(newblock1, newblock5->labels);
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock1;
+ link->nextLink = newblock5->predecessors;
+ newblock5->predecessors = link;
+
+ appendpcode(newblock3, makepcode(PC_BDNZ, newblock2->labels));
+ pcbranch(newblock3, newblock2->labels);
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock3;
+ link->nextLink = newblock2->predecessors;
+ newblock2->predecessors = link;
+
+ appendpcode(newblock4, makepcode(PC_ANDI, mtctr_reg, mtctr_reg, factor - 1));
+ appendpcode(newblock4, makepcode(PC_BT, 0, 2, blockA->labels));
+ pcbranch(newblock4, blockA->labels);
+
+ link = lalloc(sizeof(PCLink));
+ link->block = newblock4;
+ link->nextLink = blockA->predecessors;
+ blockA->predecessors = link;
+
+ deletepcode(mtctr);
+ appendpcode(newblock5, mtctr);
+
+ if (instr28 && bitvectorgetbit(instr28->args[0].data.reg.reg, liveonexit)) {
+ instr = makepcode(PC_ADD, instr28->args[0].data.reg.reg, instr28->args[0].data.reg.reg, reg25);
+ if (blockA->firstPCode)
+ insertpcodebefore(blockA->firstPCode, instr);
+ else
+ appendpcode(blockA, instr);
+ }
+}
+
+static void deleteloop(Loop *loop) {
+ PCodeBlock *body;
+ PCodeBlock *preheader;
+ PCodeBlock *nextblock;
+ PCodeLabel *label;
+ PCode *instr;
+ PCLink **ptr;
+ PCLink *link;
+ PCodeBlock *block;
+
+ body = loop->body;
+ preheader = loop->preheader;
+ nextblock = body->nextBlock;
+ label = makepclabel();
+
+ while (1) {
+ instr = body->firstPCode;
+#line 1294
+ CError_ASSERT(instr != NULL);
+
+ if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL)
+ break;
+
+ deletepcode(instr);
+ insertpcodebefore(loop->preheader->lastPCode, instr);
+ loop->bodySize--;
+ }
+
+ pclabel(nextblock, label);
+ preheader->lastPCode->args[0].data.label.label = label;
+ preheader->successors->block = nextblock;
+
+ ptr = &nextblock->predecessors;
+ while ((link = *ptr)) {
+ if (link->block == body) {
+ link->block = preheader;
+ break;
+ }
+ ptr = &link->nextLink;
+ }
+
+ block = pcbasicblocks;
+ while ((nextblock = block->nextBlock)) {
+ if (bitvectorgetbit(nextblock->blockIndex, loop->memberblocks))
+ block->nextBlock = nextblock->nextBlock;
+ else
+ block = nextblock;
+ }
+}
+
+static void deleteloopheader(Loop *loop) {
+ PCLink *link;
+ PCLink **ptr;
+
+ ptr = &loop->body->successors;
+ while ((link = *ptr)) {
+ if (link->block == loop->body->lastPCode->args[2].data.label.label->block) {
+ *ptr = link->nextLink;
+ break;
+ }
+ ptr = &link->nextLink;
+ }
+
+ ptr = &loop->body->lastPCode->args[2].data.label.label->block->predecessors;
+ while ((link = *ptr)) {
+ if (link->block == loop->body) {
+ *ptr = link->nextLink;
+ break;
+ }
+ ptr = &link->nextLink;
+ }
+
+ deletepcode(loop->body->firstPCode);
+ deletepcode(loop->body->lastPCode);
+ optimizedloop_full_unroll = 1;
+}
+
+static void rewriteloopwithBDNZ(Loop *loop) {
+ PCode *instr;
+
+ if (!FITS_IN_SHORT(loop->iterationCount)) {
+ instr = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(loop->iterationCount));
+ insertpcodebefore(loop->preheader->lastPCode, instr);
+
+ if (loop->iterationCount != 0)
+ insertpcodeafter(instr, makepcode(PC_ADDI, instr->args[0].data.reg.reg, instr->args[0].data.reg.reg, 0, LOW_PART(loop->iterationCount)));
+ } else {
+ instr = makepcode(PC_LI, used_virtual_registers[RegClass_GPR]++, loop->iterationCount);
+ insertpcodebefore(loop->preheader->lastPCode, instr);
+ }
+
+ insertpcodebefore(loop->preheader->lastPCode, makepcode(PC_MTCTR, instr->args[0].data.reg.reg));
+
+ instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label);
+ deletepcode(loop->body->firstPCode);
+ deletepcode(loop->body->lastPCode);
+ appendpcode(loop->body, instr);
+
+ for (loop = loop->parent; loop; loop = loop->parent)
+ loop->x4E = 1;
+}
+
+static void rewriteunknownloopwithBDNZ(Loop *loop) {
+ SInt32 value1; // r24
+ SInt32 value2; // r30
+ Opcode branchOpcode; // r19
+ SInt32 absStep; // r28
+ int branchCondition; // r20
+ int counterReg; // r27
+ int reg1; // r26
+ int reg2; // r22
+ unsigned char mode; // r23
+ PCodeBlock *afterLoop; // r25
+ PCode *addiInstr;
+ PCode *instr;
+ PCLink *link;
+ PCLink **ptr;
+
+ absStep = abs(loop->step);
+ afterLoop = NULL;
+
+ for (addiInstr = loop->body->lastPCode->prevPCode; addiInstr->op == PC_ADDI; addiInstr = loop->body->lastPCode->prevPCode) {
+ deletepcode(addiInstr);
+ if (loop->body->lastPCode->args[2].data.label.label->block->firstPCode)
+ insertpcodebefore(loop->body->lastPCode->args[2].data.label.label->block->firstPCode, addiInstr);
+ else
+ appendpcode(loop->body->lastPCode->args[2].data.label.label->block, addiInstr);
+
+ afterLoop = insertnewpcblock(loop->body, loop->loopWeight);
+ appendpcode(afterLoop, copypcode(addiInstr));
+ loop->footer = afterLoop;
+ }
+
+ if (loop->unknownCondition == ELESS) {
+ branchOpcode = PC_BF;
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 1;
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1 - loop->lower;
+ mode = 0;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 0;
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep - 1 + loop->upper;
+ mode = 1;
+ } else {
+ branchCondition = 0;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1;
+ mode = 2;
+ }
+ } else if (loop->unknownCondition == ELESSEQU) {
+ branchOpcode = PC_BT;
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 0;
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - loop->lower;
+ mode = 0;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 1;
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep + loop->upper;
+ mode = 1;
+ } else {
+ branchCondition = 1;
+ value1 = 0;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep;
+ mode = 2;
+ }
+ } else if (loop->unknownCondition == EGREATER) {
+ branchOpcode = PC_BF;
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 0;
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1 + loop->lower;
+ mode = 1;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 1;
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep - 1 - loop->upper;
+ mode = 0;
+ } else {
+ branchCondition = 1;
+ value1 = 0;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1;
+ mode = 3;
+ }
+ } else if (loop->unknownCondition == EGREATEREQU) {
+ branchOpcode = PC_BT;
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 1;
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep + loop->lower;
+ mode = 1;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ branchCondition = 0;
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep - loop->upper;
+ mode = 0;
+ } else {
+ branchCondition = 0;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep;
+ mode = 3;
+ }
+ } else if (loop->unknownCondition == ENOTEQU) {
+ branchOpcode = PC_BT;
+ branchCondition = 2;
+ if (loop->step > 0) {
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1 - loop->lower;
+ mode = 0;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep - 1 + loop->upper;
+ mode = 1;
+ } else {
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1;
+ mode = 2;
+ }
+ } else {
+ if (loop->lowerType == LOOP_BOUND_CONSTANT) {
+ value1 = loop->lower;
+ reg1 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1 + loop->lower;
+ mode = 1;
+ } else if (loop->upperType == LOOP_BOUND_CONSTANT) {
+ value1 = loop->upper;
+ reg1 = addiInstr->args[1].data.reg.reg;
+ value2 = absStep - 1 - loop->upper;
+ mode = 0;
+ } else {
+ reg1 = addiInstr->args[1].data.reg.reg;
+ reg2 = addiInstr->args[2].data.reg.reg;
+ value2 = absStep - 1;
+ mode = 3;
+ }
+ }
+ }
+
+ while (1) {
+ instr = loop->body->firstPCode;
+#line 1857
+ CError_ASSERT(instr);
+
+ if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL)
+ break;
+
+ deletepcode(instr);
+ insertpcodebefore(loop->preheader->lastPCode, instr);
+ loop->bodySize--;
+ }
+
+ // build a value for mtctr
+ counterReg = used_virtual_registers[RegClass_GPR]++;
+
+ if (mode == 1) {
+ if (value2 == 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_NEG, counterReg, reg1));
+ } else if (FITS_IN_SHORT(value2)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBFIC, counterReg, reg1, value2));
+ } else {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_LIS, counterReg, 0, HIGH_PART(value2)));
+ if (value2 != 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2)));
+ }
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg1, counterReg));
+ }
+ } else if (mode == 0) {
+ if (value2 == 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_MR, counterReg, reg1));
+ } else if (FITS_IN_SHORT(value2)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, reg1, 0, value2));
+ } else {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2)));
+ if (value2 != 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2)));
+ }
+ }
+ } else if (mode == 2) {
+ if (value2 == 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg1, reg2));
+ } else if (FITS_IN_SHORT(value2)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, reg2, 0, value2));
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg1, counterReg));
+ } else {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDIS, counterReg, reg2, 0, HIGH_PART(value2)));
+ if (value2 != 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2)));
+ }
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg1, counterReg));
+ }
+ } else {
+ if (value2 == 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg2, reg1));
+ } else {
+ if (FITS_IN_SHORT(value2)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, reg1, 0, value2));
+ } else {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2)));
+ if (value2 != 0) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2)));
+ }
+ }
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_SUBF, counterReg, reg2, counterReg));
+ }
+ }
+
+ if (absStep > 1) {
+ unsigned char bits;
+ if ((bits = ispowerof2(absStep))) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_RLWINM, counterReg, counterReg, 32 - bits, bits, 31));
+ } else {
+ int reg = used_virtual_registers[RegClass_GPR]++;
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_LI, reg, absStep));
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_DIVWU, counterReg, counterReg, reg));
+ }
+ }
+
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_MTCTR, counterReg));
+
+ if (mode < 2) {
+ if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) {
+ if (FITS_IN_USHORT(value1)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMPLI, 0, reg1, value1));
+ } else {
+ PCode *tmp;
+ tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1));
+ insertpcodebefore(loop->preheader->lastPCode, tmp);
+
+ if (loop->iterationCount != 0)
+ insertpcodeafter(tmp,
+ makepcode(PC_ADDI,
+ tmp->args[0].data.reg.reg,
+ tmp->args[0].data.reg.reg,
+ 0, LOW_PART(value1)));
+
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMPL, 0, reg1, tmp->args[0].data.reg.reg));
+ }
+ } else {
+ if (FITS_IN_SHORT(value1)) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMPI, 0, reg1, value1));
+ } else {
+ PCode *tmp;
+ tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1));
+ insertpcodebefore(loop->preheader->lastPCode, tmp);
+
+ if (loop->iterationCount != 0)
+ insertpcodeafter(tmp,
+ makepcode(PC_ADDI,
+ tmp->args[0].data.reg.reg,
+ tmp->args[0].data.reg.reg,
+ 0, LOW_PART(value1)));
+
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMP, 0, reg1, tmp->args[0].data.reg.reg));
+ }
+ }
+ } else {
+ if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMPL, 0, reg1, reg2));
+ } else {
+ insertpcodebefore(loop->preheader->lastPCode,
+ makepcode(PC_CMP, 0, reg1, reg2));
+ }
+ }
+
+ if (!afterLoop)
+ afterLoop = loop->body->nextBlock;
+
+ instr = makepcode(branchOpcode, 0, branchCondition, afterLoop->labels);
+ deletepcode(loop->preheader->lastPCode);
+ appendpcode(loop->preheader, instr);
+
+ instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label);
+ deletepcode(loop->body->firstPCode);
+ deletepcode(loop->body->lastPCode);
+ appendpcode(loop->body, instr);
+
+ loop->preheader->successors = NULL;
+ ptr = &loop->body->predecessors;
+ while ((link = *ptr)) {
+ if (link->block == loop->preheader) {
+ *ptr = link->nextLink;
+ break;
+ }
+ ptr = &link->nextLink;
+ }
+
+ link = lalloc(sizeof(PCLink));
+ link->block = loop->preheader->nextBlock;
+ link->nextLink = loop->preheader->successors;
+ loop->preheader->successors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = loop->preheader;
+ link->nextLink = loop->preheader->nextBlock->predecessors;
+ loop->preheader->nextBlock->predecessors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = afterLoop;
+ link->nextLink = loop->preheader->successors;
+ loop->preheader->successors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = loop->preheader;
+ link->nextLink = afterLoop->predecessors;
+ afterLoop->predecessors = link;
+
+ for (loop = loop->parent; loop; loop = loop->parent)
+ loop->x4E = 1;
+}
+
+static void optimizeloop(Loop *loop) {
+ computeliveonexit(loop);
+
+ if (loop->x53 || loop->x54)
+ insertupdateinstructions(loop);
+
+ if (loop->isKnownCountingLoop) {
+ if (loop->iterationCount > 0) {
+ skiplooptest(loop);
+ if (!copts.optimize_for_size && !loop->x4D && !loop->x57) {
+ if (loop->x4F)
+ unrollloop(loop);
+ else if (!loop->x4E)
+ unrollloopconditional(loop);
+ }
+ }
+
+ if (loop->iterationCount != 0) {
+ if (loop->iterationCount == 1)
+ deleteloopheader(loop);
+ else if (!loop->x4E && !loop->x4D)
+ rewriteloopwithBDNZ(loop);
+ }
+
+ optimizedloops = 1;
+ } else if (loop->isUnknownCountingLoop && !loop->x4E && !loop->x4D) {
+ rewriteunknownloopwithBDNZ(loop);
+ if (copts.ppc_unroll_speculative && !copts.optimize_for_size) {
+ if (loop->x4F && !loop->x57 && !loop->x52)
+ unrollunknownBDNZ(loop);
+ }
+ optimizedloops = 1;
+ }
+
+ eliminateinductionvariables(loop);
+}
+
+typedef struct LocalArray {
+ struct LocalArray *next;
+ Object *object;
+ unsigned int invalid:1;
+ unsigned int isFloat:1;
+ unsigned int isSigned:1;
+ SInt32 elementSize;
+ SInt32 arraySize;
+ SInt32 elementCount;
+ int totalUses;
+ int elements[1];
+} LocalArray;
+
+static LocalArray *scanforlocalarrays(void) {
+ SInt32 elementCount;
+ LocalArray *head;
+ LocalArray *array;
+ ObjectList *list;
+ int i;
+ SInt32 arraySize;
+ SInt32 elementSize;
+
+ head = NULL;
+
+ for (list = locals; list; list = list->next) {
+ if (
+ list->object &&
+ !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) &&
+ list->object->type &&
+ IS_TYPE_ARRAY(list->object->type) &&
+ TPTR_TARGET(list->object->type) &&
+ TPTR_TARGET(list->object->type)->type < TYPESTRUCT
+ ) {
+ arraySize = list->object->type->size;
+ elementSize = TPTR_TARGET(list->object->type)->size;
+ elementCount = arraySize / elementSize;
+ if (elementCount > 0 && elementCount <= 8) {
+ array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalArray));
+ array->next = head;
+ head = array;
+
+ array->object = list->object;
+ array->elementSize = elementSize;
+ array->arraySize = arraySize;
+ array->elementCount = elementCount;
+ array->totalUses = 0;
+ array->isSigned = 1;
+ array->isFloat = IS_TYPE_FLOAT(TPTR_TARGET(list->object->type));
+ array->invalid = 0;
+ array->isSigned = 1;
+ if (!array->isFloat && is_unsigned(TPTR_TARGET(list->object->type)))
+ array->isSigned = 0;
+
+ for (i = 0; i < elementCount; i++) {
+ array->elements[i] = 0;
+ }
+ }
+ }
+ }
+
+ return head;
+}
+
+static LocalArray *lookup_array_object(LocalArray *arrays, Object *object) {
+ while (arrays) {
+ if (arrays->object == object)
+ return arrays;
+ arrays = arrays->next;
+ }
+ return NULL;
+}
+
+void changearraytoregisters(void) {
+ LocalArray *arrays;
+ PCodeBlock *block;
+ PCode *instr;
+ int i;
+ PCodeArg *op;
+ LocalArray **ptr;
+ LocalArray *array;
+ int intCounter;
+ int floatCounter;
+ int reg;
+ int reg2;
+ PCode *newInstr;
+
+ arrays = NULL;
+ if ((arrays = scanforlocalarrays())) {
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (!(instr->flags & fPCodeFlag1) && instr->argCount) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_MEMORY &&
+ (unsigned char) op->arg == 1 &&
+ (array = lookup_array_object(arrays, op->data.mem.obj)) &&
+ !array->invalid
+ ) {
+ if (
+ (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) &&
+ (op->data.mem.offset % array->elementSize) == 0 &&
+ op->data.mem.offset < array->arraySize
+ ) {
+ switch (instr->op) {
+ case PC_LBZ:
+ case PC_STB:
+ if (array->elementSize != 1)
+ array->invalid = 1;
+ break;
+ case PC_LHZ:
+ case PC_LHA:
+ case PC_STH:
+ if (array->elementSize != 2)
+ array->invalid = 1;
+ break;
+ case PC_LWZ:
+ case PC_STW:
+ if (array->elementSize != 4)
+ array->invalid = 1;
+ break;
+ case PC_LFD:
+ case PC_STFD:
+ if (array->elementSize != 8)
+ array->invalid = 1;
+ break;
+ default:
+ array->invalid = 1;
+ break;
+ }
+
+ if (!array->invalid)
+ array->elements[op->data.mem.offset / array->elementSize]++;
+ } else {
+ array->invalid = 1;
+ }
+ }
+ op++;
+ }
+ }
+ }
+ }
+
+ intCounter = 0;
+ floatCounter = 0;
+ ptr = &arrays;
+ array = *ptr;
+ while (array) {
+ if (array->invalid) {
+ *ptr = array = array->next;
+ continue;
+ }
+
+ if (array->isFloat)
+ floatCounter += array->elementCount;
+ if (!array->isFloat)
+ intCounter += array->elementCount;
+
+ for (i = 0; i < array->elementCount; i++)
+ array->totalUses += array->elements[i];
+
+ array = array->next;
+ }
+
+ if (arrays) {
+ while (intCounter > 8) {
+ LocalArray *best;
+ int score;
+ score = 0;
+ best = NULL;
+ for (array = arrays; array; array = array->next) {
+ if (!array->isFloat) {
+ if (best) {
+ if (array->totalUses < score) {
+ score = array->totalUses;
+ best = array;
+ }
+ } else {
+ best = array;
+ score = array->totalUses;
+ }
+ }
+ }
+
+ if (!best)
+ break;
+
+ if (best == arrays) {
+ arrays = best->next;
+ } else {
+ for (array = arrays; array; array = array->next) {
+ if (array->next == best) {
+ array->next = best->next;
+ break;
+ }
+ }
+ }
+
+ intCounter -= best->elementCount;
+ }
+
+ while (floatCounter > 8) {
+ LocalArray *best;
+ int score;
+ score = 0;
+ best = NULL;
+ for (array = arrays; array; array = array->next) {
+ if (array->isFloat) {
+ if (best) {
+ if (array->totalUses < score) {
+ score = array->totalUses;
+ best = array;
+ }
+ } else {
+ best = array;
+ score = array->totalUses;
+ }
+ }
+ }
+
+ if (!best)
+ break;
+
+ if (best == arrays) {
+ arrays = best->next;
+ } else {
+ for (array = arrays; array; array = array->next) {
+ if (array->next == best) {
+ array->next = best->next;
+ break;
+ }
+ }
+ }
+
+ floatCounter -= best->elementCount;
+ }
+
+#line 2394
+ CError_ASSERT(intCounter <= 8 && floatCounter <= 8);
+
+ if (!arrays)
+ return;
+
+ optimizedloop_trans_regs = 1;
+
+ for (array = arrays; array; array = array->next) {
+ for (i = 0; i < array->elementCount; i++) {
+ if (array->isFloat)
+ array->elements[i] = used_virtual_registers[RegClass_FPR]++;
+ else
+ array->elements[i] = used_virtual_registers[RegClass_GPR]++;
+ }
+ }
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (
+ !(instr->flags & fPCodeFlag1) &&
+ instr->argCount &&
+ (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) &&
+ instr->args[2].kind == PCOp_MEMORY &&
+ (unsigned char) instr->args[2].arg == 1 &&
+ (array = lookup_array_object(arrays, instr->args[2].data.mem.obj)) &&
+ !(array->invalid)
+ )
+ {
+ reg2 = instr->args[0].data.reg.reg;
+ reg = array->elements[instr->args[2].data.mem.offset / array->elementSize];
+ newInstr = NULL;
+ switch (instr->op) {
+ case PC_LBZ:
+ if (array->isSigned)
+ newInstr = makepcode(PC_MR, reg2, reg);
+ else
+ newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 24, 31);
+ break;
+ case PC_STB:
+ if (array->isSigned)
+ newInstr = makepcode(PC_EXTSB, reg, reg2);
+ else
+ newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 24, 31);
+ break;
+ case PC_LHZ:
+ newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 16, 31);
+ break;
+ case PC_LHA:
+ newInstr = makepcode(PC_EXTSH, reg2, reg);
+ break;
+ case PC_STH:
+ if (array->isSigned)
+ newInstr = makepcode(PC_EXTSH, reg, reg2);
+ else
+ newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 16, 31);
+ break;
+ case PC_LWZ:
+ newInstr = makepcode(PC_MR, reg2, reg);
+ break;
+ case PC_STW:
+ newInstr = makepcode(PC_MR, reg, reg2);
+ break;
+ case PC_LFD:
+ newInstr = makepcode(PC_FMR, reg2, reg);
+ break;
+ case PC_STFD:
+ newInstr = makepcode(PC_FMR, reg, reg2);
+ break;
+ default:
+#line 2494
+ CError_FATAL();
+ break;
+ }
+
+ if (newInstr) {
+ insertpcodebefore(instr, newInstr);
+ deletepcode(instr);
+ instr = newInstr;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ freeoheap();
+}
+
+static void optimizenestedloops(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ optimizenestedloops(loop->children);
+ optimizeloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void optimizeloops(void) {
+ optimizedloops = 0;
+ optimizedloop_full_unroll = 0;
+ optimizedloop_trans_regs = 0;
+ if (loopsinflowgraph) {
+ computeusedefchains(0);
+ last_virtual_GPR = used_virtual_registers[RegClass_GPR];
+ liveonexit = oalloc(4 * ((used_virtual_registers[RegClass_GPR] + 31) >> 5));
+ inductionvariables = oalloc(4 * ((last_virtual_GPR + 31) >> 5));
+ optimizenestedloops(loopsinflowgraph);
+ freeoheap();
+ }
+}
+
diff --git a/compiler_and_linker/unsorted/PCode.c b/compiler_and_linker/unsorted/PCode.c
index f53030b..c35cac4 100644
--- a/compiler_and_linker/unsorted/PCode.c
+++ b/compiler_and_linker/unsorted/PCode.c
@@ -60,7 +60,7 @@ PCode *copypcode(PCode *pcode) {
newpc->op = pcode->op;
newpc->flags = pcode->flags;
newpc->argCount = pcode->argCount;
- newpc->_18 = pcode->_18;
+ newpc->alias = pcode->alias;
for (i = 0; i < pcode->argCount; i++) {
newpc->args[i] = pcode->args[i];
}
diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c
index e69de29..2ebb3c1 100644
--- a/compiler_and_linker/unsorted/PCodeAssembly.c
+++ b/compiler_and_linker/unsorted/PCodeAssembly.c
@@ -0,0 +1,27 @@
+#include "compiler/PCodeAssembly.h"
+
+static UInt32 codebase;
+
+static void pcode_update_mem_labeldiff_imm() {
+}
+
+UInt32 assemblepcode(PCode *instr, UInt32 offset, PCodeArg *dummyArg) {
+}
+
+static void targetinstruction() {
+}
+
+static void invertybit() {
+}
+
+static void insertlongbranches() {
+}
+
+void optimizefinalbranches() {
+}
+
+static void insert_align_nops() {
+}
+
+void assemblefunction() {
+}
diff --git a/compiler_and_linker/unsorted/PCodeListing.c b/compiler_and_linker/unsorted/PCodeListing.c
index e69de29..9ce9621 100644
--- a/compiler_and_linker/unsorted/PCodeListing.c
+++ b/compiler_and_linker/unsorted/PCodeListing.c
@@ -0,0 +1,527 @@
+#include "compiler/PCodeListing.h"
+#include "compiler/CError.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/Alias.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/InterferenceGraph.h"
+#include "compiler/LiveInfo.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeAssembly.h"
+#include "compiler/Registers.h"
+#include "compiler/Scheduler.h"
+#include "compiler/objects.h"
+
+static FILE *pcfile;
+static int ptime;
+static int sourcetext;
+static int sourcetext_is_main;
+static int sourcelength;
+int pclist_bad_operand;
+
+static void formatdataflowset(char *name, UInt32 *vec, UInt32 size, char *format) {
+ UInt32 i;
+ UInt32 counter;
+ char *separator;
+
+ separator = "";
+ fprintf(pcfile, "%s = {", name);
+
+ for (i = 0, counter = 0; i < size; i++) {
+ if (bitvectorgetbit(i, vec)) {
+ if (i)
+ fprintf(pcfile, separator);
+ if (counter++ == 10) {
+ fprintf(pcfile, "\n\t\t");
+ counter = 0;
+ }
+ fprintf(pcfile, format, i);
+ separator = ",";
+ }
+ }
+
+ fprintf(pcfile, "}\n");
+}
+
+static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) {
+ PCLink *link;
+ PCodeLabel *label;
+ int cpu;
+ int chr; // r21
+ PCode *instr; // r20
+ int offset; // r19
+ int latency; // r18
+ UInt32 opcode;
+ MachineInfo *mi;
+ char buf[500];
+ PCodeArg dummyArg;
+
+ fprintf(pcfile, ":{%4.4x}::::::::::::::::::::::::::::::::::::::::LOOPWEIGHT=%ld\n", block->flags, block->loopWeight);
+ fprintf(pcfile, "B%ld: ", block->blockIndex);
+
+ fprintf(pcfile, "Successors = { ");
+ for (link = block->successors; link; link = link->nextLink) {
+ if (link->block)
+ fprintf(pcfile, "B%ld ", link->block->blockIndex);
+ }
+ fprintf(pcfile, "} ");
+
+ fprintf(pcfile, "Predecessors = { ");
+ for (link = block->predecessors; link; link = link->nextLink) {
+ if (link->block)
+ fprintf(pcfile, "B%ld ", link->block->blockIndex);
+ }
+
+ if (block->labels) {
+ fprintf(pcfile, "} Labels = { ");
+ for (label = block->labels; label; label = label->nextLabel)
+ fprintf(pcfile, "L%ld ", label->index);
+ }
+
+ fprintf(pcfile, "}\n\n");
+
+ cpu = copts.schedule_cpu;
+ if (cpu == 10) {
+ mi = &machine7450;
+ } else if (copts.altivec_model != 0 || cpu == 7) {
+ mi = &machine7400;
+ } else if (cpu == 2) {
+ mi = &machine603;
+ } else if (cpu == 5) {
+ mi = &machine603e;
+ } else if (cpu == 3) {
+ mi = &machine604;
+ } else if (cpu == 6) {
+ mi = &machine604;
+ } else if (cpu == 4) {
+ mi = &machine750;
+ } else if (cpu == 1) {
+ mi = &machine601;
+ } else if (cpu == 9) {
+ mi = &machine821;
+ } else {
+ mi = &machine603;
+ }
+
+ for (offset = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset += 4) {
+ latency = mi->latency(instr);
+ formatoperands(instr, buf, 1);
+ chr = (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) ? '.' : ' ';
+ if (coloring)
+ opcode = 0;
+ else
+ opcode = assemblepcode(instr, offset, &dummyArg);
+
+ fprintf(
+ pcfile,
+ " %.8lX %.8lX %4ld %-7s%c %s\n",
+ offset, opcode, latency,
+ opcodeinfo[instr->op].name, chr, buf
+ );
+
+ if (instr->alias)
+ dumpalias(instr->alias, 0, 1, 0);
+ }
+
+ if (vecSize) {
+ fprintf(pcfile, "............................................................\n");
+ formatdataflowset("use", liveinfo[block->blockIndex].vec0, vecSize, format);
+ formatdataflowset("def", liveinfo[block->blockIndex].vec4, vecSize, format);
+ formatdataflowset("in ", liveinfo[block->blockIndex].vec8, vecSize, format);
+ formatdataflowset("out", liveinfo[block->blockIndex].vecC, vecSize, format);
+ }
+
+ fflush(pcfile);
+
+ if (pclist_bad_operand) {
+#line 252
+ CError_FATAL();
+ }
+}
+
+static void pclistonoff(int flag) {
+ if (flag)
+ fprintf(pcfile, "On\n");
+ else
+ fprintf(pcfile, "Off\n");
+}
+
+void pcinitlisting(void) {
+ // unknown args, etc
+}
+
+void pccleanuplisting(void) {
+}
+
+void pclistblocks(char *name1, char *name2) {
+}
+
+void pclistdataflow(void) {
+ // unknown args
+}
+
+void pclistinterferences(char *class_format, int regcount) {
+}
+
+void pclistspill(void) {
+ // unknown args
+}
+
+void pclistcopypropitem(void) {
+ // unknown args
+}
+
+void pclistcoalesce(void) {
+ // unknown args
+}
+
+void pclistusedefs(void) {
+ // unknown args
+}
+
+void pclistpropinfo(void) {
+ // unknown args
+}
+
+static void listloop(void) {
+ // unknown args
+}
+
+static void listloops(void) {
+ // unknown args
+}
+
+void pclistloops(void) {
+ // unknown args
+}
+
+static void listswitchtables(void) {
+ // unknown args
+}
+
+void pclistswitchtables(void) {
+ // unknown args
+}
+
+void pclistdominators(void) {
+ // unknown args
+}
+
+void pclistbackedge(void) {
+ // unknown args
+}
+
+static char *GetInterferenceFlags(IGNode *node) {
+ char *buf;
+ Boolean first;
+
+ first = 1;
+ buf = oalloc(512);
+ buf[0] = 0;
+
+ if (node->flags & fSpilled) {
+ strcat(buf, "fSpilled");
+ first = 0;
+ }
+
+ if (node->flags & fPushed) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPushed");
+ first = 0;
+ }
+
+ if (node->flags & fCoalesced) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fCoalesced");
+ first = 0;
+ }
+
+ if (node->flags & fCoalescedInto) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fCoalescedInto");
+ first = 0;
+ }
+
+ if (node->flags & fPairHigh) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPairHigh");
+ first = 0;
+ }
+
+ if (node->flags & fPairLow) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPairLow");
+ first = 0;
+ }
+
+ if (!*buf)
+ strcat(buf, "no_flags");
+
+ return buf;
+}
+
+void pclistinterferencegraphnode(void) {
+ // unknown args
+}
+
+void pclistinterferencegraph(void) {
+ // unknown args
+}
+
+void pclistblock_scheduler(void) {
+ // unknown args
+}
+
+void pclistblocks_start_scheduler(char *str1, char *str2) {
+}
+
+void pclistblocks_end_scheduler(void) {
+ if (pclist_bad_operand) {
+#line 1318
+ CError_FATAL();
+ }
+}
+
+static void printheapsize(void) {
+ // unknown args
+}
+
+void pctotalheap(void) {
+ // unknown args
+}
+
+void pctotalmemory(void) {
+ // unknown args
+}
+
+void pcmessage(char *probably_a_string, ...) {
+}
+
+int formatalias(Alias *alias, char *buf, int bufSize) {
+ char *name;
+ char *typestr;
+ int len;
+ int len2;
+
+ if (bufSize < 16)
+ return sprintf(buf, "...");
+
+ switch (alias->type) {
+ case AliasType0:
+ case AliasType1:
+ name = CMangler_GetLinkName(alias->object)->name;
+ if (!strlen(name) || name[0] < 0) {
+#line 1458
+ CError_FATAL();
+ }
+
+ if (strlen(name) + 16 > bufSize)
+ return sprintf(buf, "...");
+
+ switch (alias->object->datatype) {
+ case DNONLAZYPTR:
+ typestr = "{NL}";
+ break;
+ case DDATA:
+ typestr = "{RW}";
+ break;
+ case DLOCAL:
+ typestr = "{SP}";
+ break;
+ default:
+ typestr = "";
+ }
+
+ len = sprintf(buf, "%0.*s%s", bufSize - 20, name, typestr, alias->size);
+ buf += len;
+ if (alias->type == AliasType0)
+ return len;
+
+ if (alias->offset == 0)
+ len2 = sprintf(buf, ":%d", alias->size);
+ else if (alias->offset > 0)
+ len2 = sprintf(buf, "+%d:%d", alias->offset, alias->size);
+ else
+ len2 = sprintf(buf, "-%d:%d", -alias->offset, alias->size);
+
+ return len + len2;
+
+ case AliasType2:
+ len = 0;
+
+ len2 = sprintf(buf, "{");
+ buf += len2;
+ len += len2;
+
+ len2 = sprintf(buf, "*");
+ buf += len2;
+ len += len2;
+
+ len2 = sprintf(buf, "}");
+ buf += len2;
+ len += len2;
+ return len;
+
+ default:
+#line 1543
+ CError_FATAL();
+ return 0;
+ }
+}
+
+int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) {
+ char *name;
+ char *typestr;
+ AliasMember *member;
+ Boolean notFirst;
+
+ if (!flag2 && alias == worst_case) {
+ fprintf(pcfile, " ALIAS = {worst_case}");
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return 0;
+ }
+
+ if (flag1) {
+ if (alias == worst_case)
+ fprintf(pcfile, "ALIAS worst_case = ");
+ else
+ fprintf(pcfile, " ALIAS = ");
+ }
+
+ switch (alias->type) {
+ case AliasType0:
+ case AliasType1:
+ name = CMangler_GetLinkName(alias->object)->name;
+ if (!strlen(name) || name[0] < 0) {
+#line 1581
+ CError_FATAL();
+ }
+
+ switch (alias->object->datatype) {
+ case DNONLAZYPTR:
+ typestr = "{NL}";
+ break;
+ case DDATA:
+ typestr = "{RW}";
+ break;
+ case DLOCAL:
+ typestr = "{SP}";
+ break;
+ default:
+ typestr = "";
+ }
+
+ len += fprintf(pcfile, "%0.80s%s", name, typestr);
+
+ if (alias->type == AliasType0) {
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return len;
+ }
+
+ if (alias->offset == 0)
+ len += fprintf(pcfile, ":%d", alias->size);
+ else if (alias->offset > 0)
+ len += fprintf(pcfile, "+%d:%d", alias->offset, alias->size);
+ else
+ len += fprintf(pcfile, "-%d:%d", -alias->offset, alias->size);
+
+ if (flag1)
+ fprintf(pcfile, "\n");
+
+ return len;
+
+ case AliasType2:
+ len += fprintf(pcfile, "{");
+ notFirst = 0;
+ for (member = alias->parents; member; member = member->nextParent) {
+ if (member->child->type == AliasType0) {
+ if (notFirst)
+ len += fprintf(pcfile, ",");
+ if (len > 60) {
+ fprintf(pcfile, "\n ");
+ len = 0;
+ }
+ len = dumpalias(member->child, len, 0, 0);
+ notFirst = 1;
+ }
+ }
+ for (member = alias->parents; member; member = member->nextParent) {
+ if (member->child->type != AliasType0) {
+ if (notFirst)
+ len += fprintf(pcfile, ",");
+ if (len > 60) {
+ fprintf(pcfile, "\n ");
+ len = 0;
+ }
+ len = dumpalias(member->child, len, 0, 0);
+ notFirst = 1;
+ }
+ }
+
+ len += fprintf(pcfile, "}");
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return len;
+
+ default:
+#line 1661
+ CError_FATAL();
+ return 0;
+ }
+}
+
+void pcformatset(void) {
+ // unknown args
+}
+
+int GetLineEndOffset(char *str, int lineNum, int len) {
+ int offset;
+ char *work;
+
+ offset = GetLineOffset(str, lineNum, len);
+ if (offset < 0)
+ return offset;
+
+ work = str + offset;
+ while (*work) {
+ if (*work == '\n')
+ return work - str - 1;
+ work++;
+ }
+ return -1;
+}
+
+int GetLineOffset(char *str, int lineNum, int len) {
+ char *work = str;
+ char *end;
+
+ if (lineNum < 0)
+ return -1;
+
+ end = str + len;
+ while (work < end) {
+ if (*work == '\n' && --lineNum <= 0)
+ return work - str;
+ work++;
+ }
+
+ return 0;
+}
+
+void DumpSourceCode(void) {
+ // unknown args
+}
+
+int DumpIR_SrcBreak(void) {
+ // unknown args
+ return 0;
+}
+
diff --git a/compiler_and_linker/unsorted/Scheduler.c b/compiler_and_linker/unsorted/Scheduler.c
index e69de29..5a26a20 100644
--- a/compiler_and_linker/unsorted/Scheduler.c
+++ b/compiler_and_linker/unsorted/Scheduler.c
@@ -0,0 +1,548 @@
+#include "compiler/Scheduler.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/Alias.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/Registers.h"
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct DGNode {
+ struct DGNode *x0;
+ struct DGNode *x4;
+ struct DGSuccessor *successors;
+ PCode *instr;
+ UInt16 x10;
+ UInt16 x12;
+ UInt16 x14;
+ UInt16 x16;
+ short predCount;
+} DGNode;
+
+typedef struct DGSuccessor {
+ struct DGSuccessor *next;
+ DGNode *node;
+ UInt16 x8;
+} DGSuccessor;
+
+typedef struct DGNodeList {
+ struct DGNodeList *next;
+ DGNode *node;
+} DGNodeList;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static DGNodeList **register_uses[RegClassMax];
+static DGNodeList **register_defs[RegClassMax];
+static DGNodeList *memory_uses;
+static DGNodeList *memory_defs;
+static DGNodeList *side_effects;
+static DGNodeList *volatile_refs;
+static DGNode *defaultsuccessor;
+static UInt16 criticalpath;
+static MachineInfo *MI;
+
+static void initresources(void) {
+ int rclass;
+ int i;
+
+ for (rclass = 0; (char) rclass < RegClassMax; rclass++) {
+ register_uses[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]);
+ register_defs[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]);
+ for (i = 0; i < used_virtual_registers[(char) rclass]; i++) {
+ register_uses[(char) rclass][i] = register_defs[(char) rclass][i] = NULL;
+ }
+ }
+
+ memory_uses = memory_defs = NULL;
+ side_effects = NULL;
+ volatile_refs = NULL;
+ criticalpath = 0;
+}
+
+static DGNode *makedgnode(PCode *instr) {
+ DGNode *node;
+
+ node = oalloc(sizeof(DGNode));
+ node->x0 = NULL;
+ node->x4 = NULL;
+ node->successors = NULL;
+ node->instr = instr;
+ node->x10 = node->x16 = MI->latency(instr);
+ node->x12 = 0;
+ node->x14 = 0;
+ node->predCount = 0;
+ return node;
+}
+
+static DGNode *adddgnode(DGNode *head, DGNode *node) {
+ if (head)
+ head->x4 = node;
+ node->x0 = head;
+ return node;
+}
+
+static DGNode *removedgnode(DGNode *head, DGNode *node) {
+ if (node->x4)
+ node->x4->x0 = node->x0;
+ else
+ head = node->x0;
+
+ if (node->x0)
+ node->x0->x4 = node->x4;
+
+ return head;
+}
+
+static void addtolist(DGNodeList **list, DGNode *node) {
+ DGNodeList *entry = oalloc(sizeof(DGNodeList));
+ entry->node = node;
+ entry->next = *list;
+ *list = entry;
+}
+
+static DGNodeList *makedglistnode(DGNode *node) {
+ DGNodeList *list = oalloc(sizeof(DGNodeList));
+ list->next = NULL;
+ list->node = node;
+ return list;
+}
+
+int is_same_operand(PCodeArg *a, PCodeArg *b) {
+ if (a->kind != b->kind)
+ return 0;
+
+ switch (a->kind) {
+ case PCOp_IMMEDIATE:
+ if (a->data.imm.value != b->data.imm.value)
+ return 0;
+ break;
+ case PCOp_REGISTER:
+ if ((char) a->arg != (char) b->arg)
+ return 0;
+ if (a->data.reg.reg != b->data.reg.reg)
+ return 0;
+ break;
+ case PCOp_MEMORY:
+ if (a->data.mem.offset != b->data.mem.offset)
+ return 0;
+ if (a->data.mem.obj != b->data.mem.obj)
+ return 0;
+ break;
+ case PCOp_LABEL:
+ if (a->data.label.label != b->data.label.label)
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+static void addsuccessor(DGNode *a, DGNode *b, Boolean flag) {
+ int v6;
+ int r29;
+ DGSuccessor *succ;
+
+ if (flag)
+ v6 = a->x10;
+ else
+ v6 = 0;
+
+ if (a != b) {
+ r29 = (v6 > 0) ? v6 : 0;
+ for (succ = a->successors; succ; succ = succ->next) {
+ if (succ->node == b) {
+ if (succ->x8 < r29) {
+ succ->x8 = r29;
+ if (b->x16 + succ->x8 > a->x16)
+ a->x16 = b->x16 + succ->x8;
+ }
+ return;
+ }
+ }
+
+ succ = oalloc(sizeof(DGSuccessor));
+ succ->node = b;
+ succ->next = a->successors;
+ a->successors = succ;
+ succ->x8 = r29;
+
+ if (flag && (succ->node->instr->flags & fPCodeFlag1))
+ succ->x8 += MI->x8;
+
+ b->predCount++;
+
+ if (b->x16 + succ->x8 > a->x16)
+ a->x16 = b->x16 + succ->x8;
+ }
+}
+
+static void serializeall(DGNode *nodes, DGNode *node) {
+ DGNode *scan;
+
+ for (scan = nodes; scan; scan = scan->x0)
+ addsuccessor(node, scan, 0);
+}
+
+static void serializelist(DGNode *node, DGNodeList *list) {
+ while (list) {
+ if (list->node != node)
+ addsuccessor(node, list->node, 0);
+ list = list->next;
+ }
+}
+
+static void serializeregister(int rclass, DGNode *node, DGNodeList **defs, DGNodeList **uses, int isWrite) {
+ DGNodeList *list;
+
+ if (isWrite) {
+ for (list = *uses; list; list = list->next) {
+ if (list->node != node)
+ addsuccessor(node, list->node, 1);
+ }
+ for (list = *defs; list; list = list->next) {
+ if (list->node != node)
+ addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0));
+ }
+
+ list = makedglistnode(node);
+ list->next = *defs;
+ *defs = list;
+ } else {
+ for (list = *defs; list; list = list->next) {
+ if (list->node != node)
+ addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0));
+ }
+
+ list = makedglistnode(node);
+ list->next = *uses;
+ *uses = list;
+ }
+}
+
+static void serialize_load(DGNode *node) {
+ DGNodeList *list;
+
+ for (list = memory_defs; list; list = list->next) {
+ if (may_alias(node->instr, list->node->instr))
+ addsuccessor(node, list->node, 1);
+ }
+
+ addtolist(&memory_uses, node);
+}
+
+static void serialize_store(DGNode *node) {
+ DGNodeList *list;
+
+ for (list = memory_uses; list; list = list->next) {
+ if (may_alias(node->instr, list->node->instr))
+ addsuccessor(node, list->node, 1);
+ }
+ for (list = memory_defs; list; list = list->next) {
+ if (may_alias(node->instr, list->node->instr))
+ addsuccessor(node, list->node, 1);
+ }
+
+ addtolist(&memory_defs, node);
+ if (node->instr->flags & fPCodeFlag40000)
+ addtolist(&memory_uses, node);
+}
+
+static void findsuccessors(DGNode *nodes, DGNode *node) {
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+
+ instr = node->instr;
+ for (i = 0, op = instr->args; i < instr->argCount; i++, op++) {
+ switch (op->kind) {
+ case PCOp_IMMEDIATE:
+ case PCOp_MEMORY:
+ break;
+ case PCOp_REGISTER:
+ if (
+ op->data.reg.reg < 0 ||
+ op->data.reg.reg > used_virtual_registers[(char) op->arg]
+ )
+ {
+#line 491
+ CError_FATAL();
+ }
+
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) {
+ if (op->data.reg.reg == Register2)
+ break;
+ if (op->data.reg.reg == Register0 && !(op->data.reg.effect & (EffectRead | EffectWrite)))
+ break;
+ }
+
+ serializeregister(
+ op->arg,
+ node,
+ &register_defs[(char) op->arg][op->data.reg.reg],
+ &register_uses[(char) op->arg][op->data.reg.reg],
+ op->data.reg.effect & EffectWrite
+ );
+
+ break;
+ }
+ }
+
+ if (instr->flags & (fPCodeFlag2 | fPCodeFlag20000))
+ serialize_load(node);
+ else if (instr->flags & (fPCodeFlag4 | fPCodeFlag40000))
+ serialize_store(node);
+
+ if (instr->flags & fIsVolatile) {
+ serializelist(node, volatile_refs);
+ addtolist(&volatile_refs, node);
+ }
+
+ if (
+ ((instr->flags & fPCodeFlag8 | fPCodeFlag1) && (instr->flags & fLink)) ||
+ (instr->flags & fSideEffects) ||
+ MI->serializes(instr)
+ )
+ {
+ serializeall(nodes, node);
+ addtolist(&side_effects, node);
+ }
+
+ if (side_effects)
+ serializelist(node, side_effects);
+
+ if (!node->successors && defaultsuccessor)
+ addsuccessor(node, defaultsuccessor, 0);
+
+ if (node->x16 > criticalpath)
+ criticalpath = node->x16;
+}
+
+static void computedeadlines(DGNode *nodes) {
+ while (nodes) {
+ nodes->x14 = criticalpath - nodes->x16;
+ nodes = nodes->x0;
+ }
+}
+
+static int uncovering(DGNode *node) {
+ int counter;
+ DGSuccessor *succ;
+
+ counter = 0;
+ for (succ = node->successors; succ; succ = succ->next) {
+ if (succ->node->predCount == 1)
+ counter++;
+ }
+
+ return counter;
+}
+
+static DGNode *selectinstruction(DGNode *nodes, UInt16 counter) {
+ DGNode *node;
+ DGNode *node2;
+ int a;
+ int b;
+
+ node = nodes;
+ while (node) {
+ if (node->predCount == 0 && node->x12 <= counter && MI->can_issue(node->instr))
+ break;
+ node = node->x0;
+ }
+
+ if (!node)
+ return NULL;
+
+ for (node2 = node->x0; node2; node2 = node2->x0) {
+ if (
+ node2->predCount == 0 &&
+ node2->x12 <= counter &&
+ MI->can_issue(node2->instr) &&
+ (node->x14 > counter || node2->x14 <= counter)
+ )
+ {
+ if (node->x14 > counter && node2->x14 <= counter) {
+ node = node2;
+ continue;
+ }
+
+ if ((a = uncovering(node)) > (b = uncovering(node2)))
+ continue;
+
+ if (a < b) {
+ node = node2;
+ continue;
+ }
+
+ if (node->x16 > node2->x16)
+ continue;
+
+ if (node->x16 < node2->x16) {
+ node = node2;
+ continue;
+ }
+
+ if (coloring) {
+ if (opcodeinfo[node->instr->op].x9 < opcodeinfo[node2->instr->op].x9)
+ continue;
+
+ if (opcodeinfo[node->instr->op].x9 > opcodeinfo[node2->instr->op].x9)
+ node = node2;
+ }
+ }
+ }
+
+ return node;
+}
+
+static void holdoffsuccessors(DGNode *node, UInt16 counter) {
+ DGSuccessor *succ;
+ DGNode *n;
+
+ for (succ = node->successors; succ; succ = succ->next) {
+ n = succ->node;
+ n->predCount--;
+ if (n->x12 < counter + succ->x8)
+ n->x12 = counter + succ->x8;
+ }
+}
+
+static void scheduleblock(PCodeBlock *block) {
+ DGNode *node;
+ UInt16 counter;
+ PCode *instr;
+ UInt16 i;
+ DGNode *head;
+
+ initresources();
+ defaultsuccessor = NULL;
+ head = NULL;
+
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ DGNode *n = makedgnode(instr);
+ findsuccessors(head, n);
+ if (instr->flags & fPCodeFlag1)
+ defaultsuccessor = n;
+ head = adddgnode(head, n);
+ }
+
+ computedeadlines(head);
+ block->firstPCode = block->lastPCode = NULL;
+ block->pcodeCount = 0;
+
+ MI->initialize();
+ counter = 0;
+ while (head != NULL) {
+ for (i = 0; i < MI->x0; i++) {
+ if (head == NULL)
+ break;
+
+ node = selectinstruction(head, counter);
+ if (!node)
+ break;
+
+ instr = node->instr;
+ if (node->successors)
+ holdoffsuccessors(node, counter);
+
+ appendpcode(block, instr);
+ MI->issue(instr);
+ head = removedgnode(head, node);
+ }
+
+ MI->advance_clock();
+ counter++;
+ }
+
+ freeoheap();
+}
+
+void scheduleinstructions(Boolean flag) {
+ PCodeBlock *block;
+ int cpu;
+
+ cpu = copts.schedule_cpu;
+ if (cpu == 10) {
+ MI = &machine7450;
+ } else if (copts.altivec_model != 0 || cpu == 7) {
+ MI = &machine7400;
+ } else if (cpu == 2) {
+ MI = &machine603;
+ } else if (cpu == 5) {
+ MI = &machine603e;
+ } else if (cpu == 3) {
+ MI = &machine604;
+ } else if (cpu == 6) {
+ MI = &machine604;
+ } else if (cpu == 4) {
+ MI = &machine750;
+ } else if (cpu == 1) {
+ MI = &machine601;
+ } else if (cpu == 9) {
+ MI = &machine821;
+ } else {
+ MI = &machine603;
+ }
+
+ gather_alias_info();
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (
+ block->pcodeCount > 2 &&
+ (flag || !(block->flags & (fPCBlockFlag1 | fPCBlockFlag2))) &&
+ !(block->flags & fPCBlockFlag8)
+ )
+ {
+ scheduleblock(block);
+ block->flags |= fPCBlockFlag8;
+ }
+ }
+}
+
+int is_dependent(PCode *a, PCode *b, char rclass) {
+ int i;
+ int reg;
+ PCodeArg *op;
+
+ if (
+ b &&
+ b->argCount >= 1 &&
+ b->args[0].kind == PCOp_REGISTER &&
+ (char) b->args[0].arg == rclass &&
+ (b->args[0].data.reg.effect & EffectWrite)
+ )
+ {
+ reg = b->args[0].data.reg.reg;
+ for (i = 0; i < a->argCount; i++) {
+ op = &a->args[i];
+ if (
+ op->kind == PCOp_REGISTER &&
+ (char) op->arg == rclass &&
+ (op->data.reg.effect & (EffectRead | EffectWrite)) &&
+ op->data.reg.reg == reg
+ )
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int uses_vpermute_unit(PCode *instr) {
+ int cpu;
+
+ cpu = copts.schedule_cpu;
+ if (cpu == 10)
+ return machine7450.uses_vpermute_unit(instr);
+ if (copts.altivec_model != 0 || cpu == 7)
+ return machine7400.uses_vpermute_unit(instr);
+ return 0;
+}
+
+int default_uses_vpermute_unit(PCode *instr) {
+ return 0;
+}
diff --git a/compiler_and_linker/unsorted/SpillCode.c b/compiler_and_linker/unsorted/SpillCode.c
index e69de29..e583613 100644
--- a/compiler_and_linker/unsorted/SpillCode.c
+++ b/compiler_and_linker/unsorted/SpillCode.c
@@ -0,0 +1,464 @@
+#include "compiler/SpillCode.h"
+#include "compiler/CError.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/Coloring.h"
+#include "compiler/InterferenceGraph.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Registers.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/objects.h"
+
+static int last_unused_vreg_before_spilling;
+static short rTEMP_for_VR_spill;
+
+void estimatespillcosts(void) {
+ PCodeBlock *block;
+ PCode *instr;
+ IGNode *node;
+ PCodeArg *op;
+ int i;
+ int weight;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (copts.optimize_for_size)
+ weight = 1;
+ else
+ weight = block->loopWeight;
+
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) {
+ node = interferencegraph[op->data.reg.reg];
+ if (node->instr8 || copts.optimize_for_size)
+ node->spillCost += weight;
+ else
+ node->spillCost += weight * 2;
+ }
+ op++;
+ }
+
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) {
+ node = interferencegraph[op->data.reg.reg];
+ if (node->instr8 || (instr->flags & fPCodeFlag8000))
+ node->spillCost -= weight;
+ else
+ node->spillCost += weight;
+ }
+ op++;
+ }
+ }
+ }
+}
+
+static Object *makespilltemporary(Type *type) {
+ Object *obj = lalloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+
+ obj->otype = OT_OBJECT;
+ obj->access = ACCESSPUBLIC;
+ obj->datatype = DLOCAL;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->u.var.info = CodeGen_GetNewVarInfo();
+ obj->u.var.uid = 0;
+
+ return obj;
+}
+
+static PCode *rematerialize_spilled_register(short reg, IGNode *node) {
+ PCode *instr = copypcode(node->instr8);
+
+#line 128
+ CError_ASSERT(instr->args[0].kind == PCOp_REGISTER);
+
+ instr->args[0].data.reg.reg = reg;
+ return instr;
+}
+
+static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) {
+ Type *type;
+ Opcode opcode;
+ Object *object;
+ PCode *newInstr;
+ PCode *newInstr2;
+ SInt32 offset;
+ Operand operand;
+
+ type = node->spillTemporary->type;
+ switch (coloring_class) {
+ case RegClass_CRFIELD:
+ case RegClass_GPR:
+ switch (type->size) {
+ case 1:
+ opcode = PC_LBZ;
+ break;
+ case 2:
+ opcode = is_unsigned(type) ? PC_LHZ : PC_LHA;
+ break;
+ case 4:
+ opcode = PC_LWZ;
+ break;
+ case 8:
+ opcode = PC_LWZ;
+ break;
+ default:
+#line 187
+ CError_FATAL();
+ }
+
+ memclrw(&operand, sizeof(Operand));
+ operand.optype = OpndType_Symbol;
+ operand.object = node->spillTemporary;
+#line 222
+ CError_ASSERT(node->spillTemporary->datatype == DLOCAL);
+
+ coerce_to_addressable(&operand);
+
+#line 233
+ CError_ASSERT(operand.optype == OpndType_GPR_ImmOffset);
+
+#line 237
+ CError_ASSERT(node->spillTemporary->datatype == DLOCAL);
+
+ if (node->flags & fPairLow)
+ offset = low_offset;
+ else if (node->flags & fPairHigh)
+ offset = high_offset;
+ else
+ offset = 0;
+ insertpcodebefore(instr, makepcode(opcode, reg, operand.reg, operand.object, operand.immOffset + offset));
+ break;
+
+ case RegClass_FPR:
+#line 253
+ CError_ASSERT(node->spillTemporary->datatype == DLOCAL);
+
+ if (node->flags & fPairLow)
+ offset = low_offset;
+ else if (node->flags & fPairHigh)
+ offset = high_offset;
+ else
+ offset = 0;
+
+ object = node->spillTemporary;
+ insertpcodebefore(
+ instr,
+ makepcode(
+ (type->size == 8) ? PC_LFD : PC_LFS,
+ reg,
+ local_base_register(object),
+ object,
+ offset
+ )
+ );
+ break;
+
+ case RegClass_VR:
+#line 320
+ CError_ASSERT(node->spillTemporary->datatype == DLOCAL);
+
+ object = node->spillTemporary;
+ newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0);
+ newInstr2 = makepcode(PC_LVX, reg, 0, rTEMP_for_VR_spill);
+ insertpcodebefore(instr, newInstr);
+ insertpcodeafter(newInstr, newInstr2);
+ break;
+
+ default:
+#line 333
+ CError_FATAL();
+ }
+}
+
+static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, IGNode *node) {
+ Object *object; // r31
+ Opcode opcode; // r30
+ SInt32 offset; // r26
+ PCode *newInstr2; // r26
+ PCode *newInstr; // r25
+ Type *type; // r25
+
+ object = node->spillTemporary;
+ type = object->type;
+
+ switch (coloring_class) {
+ case RegClass_CRFIELD:
+ case RegClass_GPR:
+ switch (type->size) {
+ case 1:
+ opcode = PC_STB;
+ break;
+ case 2:
+ opcode = PC_STH;
+ break;
+ case 4:
+ opcode = PC_STW;
+ break;
+ case 8:
+ opcode = PC_STW;
+ break;
+ default:
+#line 391
+ CError_FATAL();
+ }
+
+ if (node->flags & fPairLow)
+ offset = low_offset;
+ else if (node->flags & fPairHigh)
+ offset = high_offset;
+ else
+ offset = 0;
+
+ newInstr = makepcode(opcode, reg, local_base_register(object), object, offset);
+ if (flag)
+ insertpcodebefore(instr, newInstr);
+ else
+ insertpcodeafter(instr, newInstr);
+
+ break;
+
+ case RegClass_FPR:
+ newInstr = makepcode((type->size == 8) ? PC_STFD : PC_STFS, reg, local_base_register(object), object, 0);
+ if (flag)
+ insertpcodebefore(instr, newInstr);
+ else
+ insertpcodeafter(instr, newInstr);
+
+ break;
+
+ case RegClass_VR:
+ newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0);
+ newInstr2 = makepcode(PC_STVX, reg, 0, rTEMP_for_VR_spill);
+ if (flag)
+ insertpcodebefore(instr, newInstr);
+ else
+ insertpcodeafter(instr, newInstr);
+ insertpcodeafter(newInstr, newInstr2);
+
+ break;
+
+ default:
+#line 527
+ CError_FATAL();
+ }
+}
+
+static void spillinstruction(PCodeBlock *block, PCode *instr) {
+ int reg;
+ int reg2;
+ int regs;
+ IGNode *node;
+ PCodeArg *op;
+ int i;
+ PCodeArg *op2;
+ int j;
+ int readCounter;
+ int writeCounter;
+ Boolean flag;
+
+ 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);
+
+ if (
+ PC_OP_IS_ANY_REGISTER(op, coloring_class) &&
+ (reg = op->data.reg.reg) < regs &&
+ ((node = interferencegraph[op->data.reg.reg])->flags & fSpilled)
+ )
+ {
+ reg2 = used_virtual_registers[coloring_class]++;
+ readCounter = 0;
+ writeCounter = 0;
+
+ for (j = i, op2 = op; j < instr->argCount; j++, op2++) {
+ if (PC_OP_IS_REGISTER(op2, coloring_class, reg)) {
+ if (op2->data.reg.effect & EffectRead)
+ readCounter++;
+ if (op2->data.reg.effect & EffectWrite)
+ writeCounter++;
+ op2->data.reg.reg = reg2;
+ op2->data.reg.effect |= Effect40;
+ }
+ }
+
+ if (readCounter) {
+ if (node->instr8)
+ insertpcodebefore(instr, rematerialize_spilled_register(reg2, node));
+ else
+ insert_load_spilled_register(instr, reg2, node);
+ }
+
+ if (writeCounter) {
+ if (node->instr8 || (instr->flags & fPCodeFlag8000))
+ flag = 1;
+ else
+ insert_store_spilled_register(instr, 0, reg2, node);
+ }
+ }
+ }
+
+ if (flag)
+ deletepcode(instr);
+}
+
+static void spillcopy(PCodeBlock *block, PCode *instr) {
+ IGNode *node1;
+ IGNode *node2;
+ int reg;
+
+ node1 = interferencegraph[instr->args[1].data.reg.reg];
+ node2 = interferencegraph[instr->args[0].data.reg.reg];
+
+ if (node1->flags & fSpilled) {
+ if (node2->flags & fSpilled) {
+ reg = used_virtual_registers[coloring_class]++;
+ if (node1->instr8)
+ insertpcodebefore(instr, rematerialize_spilled_register(reg, node1));
+ else
+ insert_load_spilled_register(instr, reg, node1);
+ insert_store_spilled_register(instr, 1, reg, node2);
+ } else {
+ if (node1->instr8)
+ insertpcodebefore(instr, rematerialize_spilled_register(instr->args[0].data.reg.reg, node1));
+ else
+ insert_load_spilled_register(instr, instr->args[0].data.reg.reg, node1);
+ }
+ } else {
+ insert_store_spilled_register(instr, 1, instr->args[1].data.reg.reg, node2);
+ }
+
+ deletepcode(instr);
+}
+
+static void spillcall(PCodeBlock *block, PCode *instr) {
+ PCodeArg *opSrc;
+ PCodeArg *opDst;
+ int opCount;
+ int volatileCount;
+ int i;
+
+ opCount = instr->argCount;
+ volatileCount = branch_count_volatiles();
+
+ opDst = instr->args + volatileCount;
+ opSrc = instr->args + volatileCount;
+ for (i = volatileCount; i < opCount; i++) {
+ if (
+ PC_OP_IS_ANY_REGISTER(opSrc, coloring_class) &&
+ opSrc->data.reg.reg >= n_real_registers[coloring_class] &&
+ (interferencegraph[opSrc->data.reg.reg]->flags & fSpilled)
+ )
+ {
+ instr->argCount--;
+ } else {
+ *opDst = *opSrc;
+ opDst++;
+ }
+ opSrc++;
+ }
+
+ spillinstruction(block, instr);
+}
+
+static void assign_spill_locations(void) {
+ UInt32 i;
+ IGNode *node;
+ Type *type;
+
+ last_unused_vreg_before_spilling = used_virtual_registers[coloring_class];
+ for (i = n_real_registers[coloring_class]; i < last_unused_vreg_before_spilling; i++) {
+ node = interferencegraph[i];
+ if (node->flags & fCoalesced)
+ continue;
+ if (!(node->flags & fSpilled))
+ continue;
+
+ if (!node->spillTemporary) {
+ switch (coloring_class) {
+ case RegClass_GPR:
+ type = TYPE(&stunsignedlong);
+ break;
+ case RegClass_CRFIELD:
+ type = TYPE(&stunsignedlong);
+ break;
+ case RegClass_FPR:
+ type = TYPE(&stunsignedlong);
+ break;
+ case RegClass_VR:
+ type = TYPE(&stvectorunsignedchar);
+ break;
+ default:
+#line 771
+ CError_FATAL();
+ }
+
+ node->spillTemporary = makespilltemporary(type);
+ }
+
+ if (node->spillTemporary->datatype == DLOCAL && !(node->spillTemporary->u.var.info->flags & VarInfoFlag1))
+ assign_local_memory(node->spillTemporary);
+
+ if (node->flags & fPairHigh)
+ Registers_GetVarInfo(node->spillTemporary)->regHi = Register0;
+ else
+ Registers_GetVarInfo(node->spillTemporary)->reg = Register0;
+ }
+}
+
+void insertspillcode(void) {
+ PCodeBlock *block;
+ PCode *instr;
+ PCode *nextInstr;
+ PCodeArg *op;
+ UInt32 i;
+ int flag;
+
+ rTEMP_for_VR_spill = 0;
+ assign_spill_locations();
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (instr = block->firstPCode; instr; instr = nextInstr) {
+ nextInstr = instr->nextPCode;
+ flag = 0;
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ PC_OP_IS_ANY_REGISTER(op, coloring_class) &&
+ op->data.reg.reg < last_unused_vreg_before_spilling &&
+ (interferencegraph[op->data.reg.reg]->flags & fSpilled)
+ )
+ {
+ flag = 1;
+ break;
+ }
+ op++;
+ }
+
+ if (flag) {
+ if (coloring_class == RegClass_VR && rTEMP_for_VR_spill == 0)
+ rTEMP_for_VR_spill = used_virtual_registers[RegClass_GPR]++;
+
+ if (instr->flags & fPCodeFlag10)
+ spillcopy(block, instr);
+ else if (instr->flags & fPCodeFlag8)
+ spillcall(block, instr);
+ else
+ spillinstruction(block, instr);
+ }
+ }
+ }
+}
diff --git a/compiler_and_linker/unsorted/StrengthReduction.c b/compiler_and_linker/unsorted/StrengthReduction.c
index e69de29..9b6117d 100644
--- a/compiler_and_linker/unsorted/StrengthReduction.c
+++ b/compiler_and_linker/unsorted/StrengthReduction.c
@@ -0,0 +1,752 @@
+#include "compiler/StrengthReduction.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/LoopDetection.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/UseDefChains.h"
+
+int strengthreducedloops;
+
+static PCode *findinitializer(Loop *loop, short reg) {
+ UInt32 *vec;
+ PCode *best;
+ RegUseOrDef *list;
+
+ vec = usedefinfo[loop->body->blockIndex].defvec8;
+ best = NULL;
+
+ for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) {
+ if (
+ !(bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) &&
+ bitvectorgetbit(list->id, vec)
+ )
+ {
+ if (best)
+ return NULL;
+ best = Defs[list->id].pcode;
+ }
+ }
+
+ if (best) {
+ if (best->op == PC_LI || best->op == PC_ADDI || best->op == PC_ADD)
+ return best;
+ }
+
+ return NULL;
+}
+
+static int isbasicinductionvariable(Loop *loop, short reg, SInt32 step) {
+ RegUseOrDef *list;
+ PCode *instr;
+
+ for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) {
+ instr = Defs[list->id].pcode;
+ if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) {
+ if (instr->op != PC_ADDI)
+ return 0;
+ if (instr->args[1].data.reg.reg != reg)
+ return 0;
+ if (instr->args[2].data.imm.value != step)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void addbasicinductionvariable(Loop *loop, short reg, SInt32 step) {
+ BasicInductionVar *biv;
+ RegUseOrDef *list;
+ PCode *instr;
+ InstrList *instrList;
+
+ for (biv = loop->basicInductionVars; biv; biv = biv->next) {
+ if (biv->reg == reg)
+ return;
+ }
+
+ biv = oalloc(sizeof(BasicInductionVar));
+ biv->next = loop->basicInductionVars;
+ loop->basicInductionVars = biv;
+
+ biv->loop = loop;
+ biv->inductionVars = NULL;
+ biv->instrsC = NULL;
+ biv->step = step;
+ biv->reg = reg;
+
+ for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) {
+ instr = Defs[list->id].pcode;
+ if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) {
+ instrList = oalloc(sizeof(InstrList));
+ instrList->next = biv->instrsC;
+ biv->instrsC = instrList;
+ instrList->instr = instr;
+ }
+ }
+
+ biv->initializer = findinitializer(loop, reg);
+}
+
+static void findbasicinductionvariables(Loop *loop) {
+ SInt16 step;
+ BlockList *block;
+ PCode *instr;
+ short reg;
+
+ for (block = loop->blocks; block; block = block->next) {
+ for (instr = block->block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->op == PC_ADDI) {
+ if (
+ (reg = instr->args[0].data.reg.reg) >= 32 &&
+ instr->args[1].data.reg.reg == reg &&
+ isbasicinductionvariable(loop, reg, step = instr->args[2].data.imm.value)
+ )
+ addbasicinductionvariable(loop, reg, step);
+ }
+ }
+ }
+}
+
+static void findallbasicinductionvariables(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ findallbasicinductionvariables(loop->children);
+ findbasicinductionvariables(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+static int isinductionvariable(BasicInductionVar *biv, int useID, SInt32 *result1, short *result2, short *result3, Loop **result4) {
+ RegUseOrDef *list;
+ int counter;
+ Loop *loop;
+ Loop *scanloop;
+ PCode *instr;
+
+ instr = Uses[useID].pcode;
+ *result2 = 0;
+ *result3 = 0;
+ *result4 = NULL;
+
+ switch (instr->op) {
+ case PC_MULLI:
+ *result1 = instr->args[2].data.imm.value;
+ break;
+
+ case PC_RLWINM:
+ if (instr->args[3].data.imm.value)
+ return 0;
+ if (instr->args[2].data.imm.value > 15)
+ return 0;
+ if (instr->args[4].data.imm.value != (31 - instr->args[2].data.imm.value))
+ return 0;
+ if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000)
+ return 0;
+ *result1 = 1 << instr->args[2].data.imm.value;
+ break;
+
+ case PC_LBZX:
+ case PC_LHZX:
+ case PC_LHAX:
+ case PC_LWZX:
+ case PC_STBX:
+ case PC_STHX:
+ case PC_STWX:
+ case PC_LFSX:
+ case PC_LFDX:
+ case PC_STFSX:
+ case PC_STFDX:
+ *result2 = 0;
+ *result3 = 0;
+ if (instr->args[1].data.reg.reg == biv->reg) {
+ *result2 = 1;
+ *result3 = 2;
+ } else if (instr->args[2].data.reg.reg == biv->reg) {
+ *result2 = 2;
+ *result3 = 1;
+ }
+
+ counter = 0;
+ for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks))
+ counter++;
+ }
+ if (counter)
+ return 0;
+
+ loop = biv->loop;
+ for (scanloop = loop->parent; scanloop; scanloop = scanloop->parent) {
+ counter = 0;
+ for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, scanloop->memberblocks))
+ counter++;
+ }
+ if (!biv->initializer || bitvectorgetbit(biv->initializer->block->blockIndex, scanloop->memberblocks))
+ counter++;
+ if (counter)
+ break;
+ loop = scanloop;
+ }
+
+ *result4 = loop;
+ *result1 = 1;
+ return 1;
+
+ default:
+ return 0;
+ }
+
+ counter = 0;
+ for (list = reg_Defs[RegClass_GPR][instr->args[0].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks))
+ counter++;
+ }
+
+ return counter == 1;
+}
+
+static void addinductionvariable(BasicInductionVar *biv, PCode *instr, SInt32 val1, short val2, short val3, Loop *val4) {
+ InductionVar *iv;
+
+ iv = oalloc(sizeof(InductionVar));
+ iv->next = biv->inductionVars;
+ biv->inductionVars = iv;
+
+ iv->basicVar = biv;
+ iv->instr = instr;
+ iv->instrC = NULL;
+ iv->step = val1;
+ iv->x18 = val2;
+ iv->x1A = val3;
+ iv->someloop = val4;
+ if (instr->flags & (fPCodeFlag2 | fPCodeFlag4))
+ iv->x1C = -1;
+ else
+ iv->x1C = instr->args[0].data.reg.reg;
+ iv->x1E = -1;
+}
+
+static void findnonbasicinductionvariables(Loop *loop) {
+ BasicInductionVar *biv;
+ RegUseOrDef *list;
+ SInt32 result1;
+ short result2;
+ short result3;
+ Loop *result4;
+
+ for (biv = loop->basicInductionVars; biv; biv = biv->next) {
+ for (list = reg_Uses[RegClass_GPR][biv->reg]; list; list = list->next) {
+ if (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) {
+ if (isinductionvariable(biv, list->id, &result1, &result2, &result3, &result4))
+ addinductionvariable(biv, Uses[list->id].pcode, result1, result2, result3, result4);
+ }
+ }
+ }
+}
+
+static void findallnonbasicinductionvariables(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ findallnonbasicinductionvariables(loop->children);
+ if (loop->basicInductionVars)
+ findnonbasicinductionvariables(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+static void initializeinductionvariable(InductionVar *iv) {
+ BasicInductionVar *biv; // r31
+ PCode *instr; // r27
+ PCodeBlock *preheader; // r30
+ SInt32 value30; // r30
+ short reg29; // r29
+ short reg26; // r26
+
+ biv = iv->basicVar;
+ preheader = biv->loop->preheader;
+
+ if (iv->x1A) {
+ reg29 = iv->instr->args[iv->x1A].data.reg.reg;
+ reg26 = iv->instr->args[iv->x18].data.reg.reg;
+ instr = NULL;
+
+ if (
+ biv->initializer &&
+ biv->initializer->op == PC_LI &&
+ biv->initializer->block == preheader
+ )
+ {
+ if (biv->initializer->args[1].data.imm.value == 0)
+ instr = makepcode(PC_MR, iv->x1E, reg29);
+ else if (FITS_IN_SHORT(biv->initializer->args[1].data.imm.value))
+ instr = makepcode(PC_ADDI, iv->x1E, reg29, 0, biv->initializer->args[1].data.imm.value);
+ }
+
+ if (!instr)
+ instr = makepcode(PC_ADD, iv->x1E, reg29, reg26);
+
+ if (biv->initializer && instr->op != PC_ADD)
+ insertpcodeafter(biv->initializer, instr);
+ else if (iv->someloop && iv->someloop->preheader->lastPCode)
+ insertpcodebefore(iv->someloop->preheader->lastPCode, instr);
+ else
+ insertpcodebefore(preheader->lastPCode, instr);
+
+ iv->instrC = instr;
+ iv->x1C = reg29;
+ return;
+ }
+
+ if (!biv->initializer || biv->initializer->op != PC_LI) {
+ instr = copypcode(iv->instr);
+ instr->args[0].data.reg.reg = iv->x1E;
+ insertpcodebefore(preheader->lastPCode, instr);
+ } else {
+ value30 = biv->initializer->args[1].data.imm.value * iv->step;
+ if (!FITS_IN_SHORT(value30)) {
+ instr = makepcode(PC_LIS, iv->x1E, 0, HIGH_PART(value30));
+ insertpcodeafter(biv->initializer, instr);
+ if (value30 != 0)
+ insertpcodeafter(instr, makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value30)));
+ } else {
+ instr = makepcode(PC_LI, iv->x1E, value30);
+ insertpcodeafter(biv->initializer, instr);
+ }
+ }
+}
+
+static void incrementinductionvariable(InductionVar *iv) {
+ SInt32 value;
+ BasicInductionVar *biv;
+ PCode *instr;
+ InstrList *list;
+
+ biv = iv->basicVar;
+ value = iv->step * biv->step;
+ for (list = biv->instrsC; list; list = list->next) {
+ if (!FITS_IN_SHORT(value)) {
+ instr = makepcode(PC_ADDIS, iv->x1E, iv->x1E, 0, HIGH_PART(value));
+ insertpcodeafter(list->instr, instr);
+
+ if (value != 0) {
+ instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value));
+ insertpcodeafter(list->instr->nextPCode, instr);
+ }
+ } else {
+ instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, value);
+ insertpcodeafter(list->instr, instr);
+ }
+ }
+}
+
+static void copyinductionvariable(InductionVar *iv) {
+ if (iv->instr->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ iv->instr->op -= 2;
+ iv->instr->args[1].data.reg.reg = iv->x1E;
+ iv->instr->args[2].kind = PCOp_IMMEDIATE;
+ iv->instr->args[2].data.imm.value = 0;
+ iv->instr->args[2].data.imm.obj = NULL;
+ } else {
+ insertpcodeafter(iv->instr, makepcode(PC_MR, iv->x1C, iv->x1E));
+ deletepcode(iv->instr);
+ }
+}
+
+static int testnestediv(InductionVar *iv, SInt32 step1, int reg, SInt32 step2, Loop *loop1, Loop *loop2) {
+ SInt32 addend;
+ BlockList *list;
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+
+ if (iv->instrC && iv->x1C == reg) {
+ if (iv->instrC->op == PC_MR)
+ addend = 0;
+ else if (iv->instrC->op == PC_ADDI)
+ addend = iv->instrC->args[2].data.imm.value;
+ else
+ return 0;
+
+ if (step2 == (addend + (step1 * iv->step * loop2->iterationCount))) {
+ for (list = loop1->blocks; list && list->block != loop2->blocks->block; list = list->next) {
+ for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg == reg
+ )
+ return 0;
+ op++;
+ }
+ }
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void strengthreducenestediv(short reg, SInt32 step, PCode *initializer, Loop *loop) {
+ Loop *scanloop;
+ BasicInductionVar *biv;
+ InductionVar *iv;
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+
+ for (scanloop = loop->children; scanloop; scanloop = scanloop->nextSibling) {
+ if (
+ scanloop->isKnownCountingLoop &&
+ scanloop->x4F &&
+ bitvectorgetbit(scanloop->body->blockIndex, loop->vec2C)
+ )
+ {
+ for (biv = scanloop->basicInductionVars; biv; biv = biv->next) {
+ for (iv = biv->inductionVars; iv; iv = iv->next) {
+ if (testnestediv(iv, biv->step, reg, step, loop, scanloop)) {
+ deletepcode(iv->instrC);
+ if (initializer) {
+ insertpcodeafter(initializer, iv->instrC);
+ } else if (loop->body->lastPCode) {
+ for (instr = loop->body->lastPCode; instr; instr = instr->prevPCode) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (op->data.reg.effect & EffectWrite) &&
+ op->data.reg.reg == reg
+ )
+ break;
+ op++;
+ }
+ }
+
+ if (instr)
+ insertpcodeafter(instr, iv->instrC);
+ else
+ insertpcodebefore(loop->body->firstPCode, iv->instrC);
+ } else {
+ appendpcode(loop->body, iv->instrC);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void strengthreducenestedbiv(BasicInductionVar *biv) {
+ Loop *loop;
+ InductionVar *iv;
+
+ loop = biv->loop;
+ for (iv = biv->inductionVars; iv; iv = iv->next)
+ strengthreducenestediv(iv->x1E, iv->step * biv->step, iv->instrC, loop);
+
+ strengthreducenestediv(biv->reg, biv->step, biv->initializer, loop);
+}
+
+static void strengthreduceinductionvariable(BasicInductionVar *biv) {
+ int counter;
+ InductionVar *iv;
+ InductionVar *otherIv;
+ short reg;
+
+ counter = 0;
+ for (iv = biv->inductionVars; iv; iv = iv->next) {
+ if (iv->step == 1)
+ counter++;
+ }
+
+ for (iv = biv->inductionVars; iv; iv = iv->next) {
+ if (
+ (counter <= 4 || iv->step != 1) &&
+ iv->instr->block &&
+ (iv->x1A == 0 || iv->instr->args[2].kind != PCOp_IMMEDIATE)
+ )
+ {
+ if (iv->x1E == -1) {
+ iv->x1E = used_virtual_registers[RegClass_GPR]++;
+ initializeinductionvariable(iv);
+ incrementinductionvariable(iv);
+ if (iv->step == 1) {
+ reg = iv->instr->args[iv->x1A].data.reg.reg;
+ for (otherIv = iv->next; otherIv; otherIv = otherIv->next) {
+ if (otherIv->x1A != 0 && otherIv->instr->args[otherIv->x1A].data.reg.reg == reg)
+ otherIv->x1E = iv->x1E;
+ }
+ } else {
+ for (otherIv = iv->next; otherIv; otherIv = otherIv->next) {
+ if (otherIv->step == iv->step)
+ otherIv->x1E = iv->x1E;
+ }
+ }
+ }
+
+ copyinductionvariable(iv);
+ strengthreducedloops = 1;
+ }
+ }
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct BivInit {
+ SInt32 x0;
+ short x4;
+ short x6;
+ short x8;
+ Object *xA;
+} BivInit;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void calc_biv_init(BasicInductionVar *biv, BivInit *init) {
+ PCode *instr;
+ PCode *scan;
+ PCodeArg *op;
+ int i;
+
+ instr = biv->initializer;
+ init->x0 = 0;
+ init->x4 = -1;
+ init->x6 = -1;
+ init->x8 = 0;
+ init->xA = NULL;
+
+ if (!biv->initializer || (biv->initializer->op != PC_ADDI && biv->initializer->op != PC_ADD))
+ return;
+
+ if (instr->op == PC_ADDI) {
+ if (instr->args[1].data.reg.reg == biv->reg) {
+ init->x0 = instr->args[2].data.imm.value;
+ for (scan = instr->prevPCode; scan; scan = scan->prevPCode) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg == biv->reg &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ {
+ if (scan->op == PC_ADD) {
+ init->x4 = scan->args[1].data.reg.reg;
+ init->x6 = scan->args[2].data.reg.reg;
+ } else if (scan->op == PC_ADDI) {
+ if (scan->args[2].kind == PCOp_IMMEDIATE) {
+ init->x4 = scan->args[1].data.reg.reg;
+ init->x8 = scan->args[2].data.imm.value;
+ } else if (scan->args[2].kind == PCOp_MEMORY) {
+ init->x4 = scan->args[1].data.reg.reg;
+ init->x8 = scan->args[2].data.mem.offset;
+ init->xA = scan->args[2].data.mem.obj;
+ }
+ }
+ return;
+ }
+ op++;
+ }
+ }
+ } else {
+ if (instr->args[2].kind == PCOp_IMMEDIATE) {
+ init->x4 = instr->args[1].data.reg.reg;
+ init->x8 = instr->args[2].data.imm.value;
+ } else if (instr->args[2].kind == PCOp_MEMORY) {
+ init->x4 = instr->args[1].data.reg.reg;
+ init->x8 = instr->args[2].data.mem.offset;
+ init->xA = instr->args[2].data.mem.obj;
+ }
+ }
+ } else if (instr->op == PC_ADD) {
+ if (instr->args[1].data.reg.reg == biv->reg) {
+ init->x6 = instr->args[2].data.reg.reg;
+ for (scan = instr->prevPCode; scan; scan = scan->prevPCode) {
+ op = scan->args;
+ i = scan->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg == biv->reg &&
+ (op->data.reg.effect & EffectWrite) &&
+ scan->op == PC_ADDI
+ )
+ {
+ if (scan->args[2].kind == PCOp_IMMEDIATE) {
+ init->x4 = scan->args[1].data.reg.reg;
+ init->x8 = scan->args[2].data.imm.value;
+ } else if (scan->args[2].kind == PCOp_MEMORY) {
+ init->x4 = scan->args[1].data.reg.reg;
+ init->x8 = scan->args[2].data.mem.offset;
+ init->xA = scan->args[2].data.mem.obj;
+ }
+ return;
+ }
+ op++;
+ }
+ }
+ } else {
+ init->x4 = instr->args[1].data.reg.reg;
+ init->x6 = instr->args[2].data.reg.reg;
+ }
+ }
+}
+
+static void combineinductionvariables(Loop *loop, BasicInductionVar *biv1, BasicInductionVar *biv2, SInt32 difference) {
+ PCode *instr1; // r31
+ int reg1; // r30
+ int reg2; // r29
+ PCode *instr2; // r24
+ PCodeBlock *nextBlock; // r24
+ BlockList *list;
+ PCodeArg *op;
+ int i;
+ PCode *instr;
+
+ instr1 = NULL;
+ instr2 = NULL;
+
+ reg1 = biv1->reg;
+#line 930
+ CError_ASSERT(reg1 >= 0);
+
+ reg2 = biv2->reg;
+#line 934
+ CError_ASSERT(reg2 >= 0);
+
+ if (!FITS_IN_SHORT(difference))
+ return;
+
+ for (list = loop->blocks; list; list = list->next) {
+ for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr1) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ op->data.reg.reg == reg1
+ )
+ return;
+ op++;
+ }
+ }
+
+ if (instr->op == PC_ADDI) {
+ if (instr->args[0].data.reg.reg == reg1) {
+ if (instr1)
+ return;
+ instr1 = instr;
+ } else if (instr->args[0].data.reg.reg == reg2) {
+ if (instr2)
+ return;
+ instr2 = instr;
+ }
+ }
+ }
+ }
+
+ if (loop->body->lastPCode->flags & fPCodeFlag1) {
+ nextBlock = NULL;
+
+ for (i = 0; i < loop->body->lastPCode->argCount; i++) {
+ if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) {
+ nextBlock = loop->body->lastPCode->args[i].data.label.label->block;
+ break;
+ }
+ }
+
+ if (!nextBlock)
+ return;
+ } else {
+ nextBlock = loop->body->nextBlock;
+ }
+
+ deletepcode(instr1);
+ instr1->args[1].data.reg.reg = reg2;
+ instr1->args[2].data.imm.value = difference;
+
+ if (nextBlock->firstPCode)
+ insertpcodebefore(nextBlock->firstPCode, instr1);
+ else
+ appendpcode(nextBlock, instr1);
+
+ biv1->reg = -1;
+ strengthreducedloops = 1;
+}
+
+static void strengthreduceinductionvariables(Loop *loop) {
+ BasicInductionVar *biv1;
+ BasicInductionVar *biv2;
+ BivInit init1;
+ BivInit init2;
+
+ for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) {
+ if (biv1->inductionVars)
+ strengthreduceinductionvariable(biv1);
+ strengthreducenestedbiv(biv1);
+ }
+
+ for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) {
+ if (biv1->reg != -1) {
+ calc_biv_init(biv1, &init1);
+ if (init1.x4 != -1) {
+ for (biv2 = loop->basicInductionVars; biv2; biv2 = biv2->next) {
+ if (biv2->reg != -1 && biv2 != biv1) {
+ calc_biv_init(biv2, &init2);
+ if (
+ init2.x4 != -1 &&
+ init1.x4 == init2.x4 &&
+ init1.x6 == init2.x6 &&
+ init1.x8 == init2.x8 &&
+ init1.xA == init2.xA &&
+ biv1->step == biv2->step
+ )
+ {
+ if (init1.x0 < init2.x0) {
+ combineinductionvariables(loop, biv2, biv1, init2.x0 - init1.x0);
+ } else {
+ combineinductionvariables(loop, biv1, biv2, init1.x0 - init2.x0);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void strengthreduceallinductionvariables(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ strengthreduceallinductionvariables(loop->children);
+ if (loop->basicInductionVars)
+ strengthreduceinductionvariables(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void strengthreduceloops(void) {
+ strengthreducedloops = 0;
+ if (loopsinflowgraph) {
+ computeusedefchains(0);
+ findallbasicinductionvariables(loopsinflowgraph);
+ findallnonbasicinductionvariables(loopsinflowgraph);
+ strengthreduceallinductionvariables(loopsinflowgraph);
+ freeoheap();
+ }
+}
diff --git a/compiler_and_linker/unsorted/Switch.c b/compiler_and_linker/unsorted/Switch.c
index af62eb3..185ec71 100644
--- a/compiler_and_linker/unsorted/Switch.c
+++ b/compiler_and_linker/unsorted/Switch.c
@@ -2,13 +2,20 @@
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CInt64.h"
-#include "compiler/objects.h"
#include "compiler/CParser.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/Operands.h"
#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/TOC.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
ObjectList *switchtables;
-static void *caselabels;
-static void *caseranges;
+static SwitchCase **caselabels;
+static CaseRange *caseranges;
static SInt32 ncases;
static SInt32 nranges_minus1;
static CInt64 min;
@@ -20,25 +27,446 @@ static Type *selector_type;
static PCodeLabel *defaultlabel;
static CInt64 range;
-static void compare_cases() {
+static int compare_cases(const void *a, const void *b) {
+ const SwitchCase **casea = (const SwitchCase **) a;
+ const SwitchCase **caseb = (const SwitchCase **) b;
+
+ if (CInt64_Less((*casea)->min, (*caseb)->min))
+ return -1;
+ if (CInt64_Greater((*casea)->min, (*caseb)->min))
+ return 1;
+ return 0;
}
static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) {
+ SwitchCase **caseptr;
+ SInt32 i;
+ SwitchCase *curcase;
+ CaseRange *currange;
+
+ if (type->size == 8) {
+ min.lo = 0;
+ min.hi = 0x80000000;
+ max.lo = 0xFFFFFFFF;
+ max.hi = 0x7FFFFFFF;
+ } else if (type->size == 4) {
+ CInt64_SetLong(&min, 0x80000000);
+ CInt64_SetLong(&max, 0x7FFFFFFF);
+ } else if (is_unsigned(type)) {
+ min.hi = 0;
+ min.lo = 0;
+ max.hi = 0;
+ max.lo = 0xFFFF;
+ } else {
+ CInt64_SetLong(&min, -0x8000);
+ CInt64_SetLong(&max, 0x7FFF);
+ }
+
+ caselabels = lalloc(sizeof(SwitchCase *) * ncases);
+ caseptr = caselabels;
+ while (cases) {
+ *caseptr = cases;
+ cases = cases->next;
+ ++caseptr;
+ }
+
+ caseranges = lalloc(((ncases * 2) + 2) * sizeof(CaseRange));
+ if (type->size < 8) {
+ for (i = 0; i < ncases; i++)
+ CInt64_SetLong(&caselabels[i]->min, caselabels[i]->min.lo);
+ }
+
+ qsort(caselabels, ncases, sizeof(SwitchCase *), &compare_cases);
+
+ currange = caseranges;
+ currange->min = min;
+ currange->range = CInt64_Sub(max, min);
+ currange->label = label->pclabel;
+
+ for (i = 0; i < ncases; i++) {
+ curcase = caselabels[i];
+ if (CInt64_GreaterEqual(curcase->min, min) && CInt64_LessEqual(curcase->min, max)) {
+ if (CInt64_Equal(currange->min, min))
+ first = curcase->min;
+ range = CInt64_Sub(curcase->min, first);
+
+ if (CInt64_Greater(curcase->min, currange->min)) {
+ currange->range = CInt64_Sub(CInt64_Sub(curcase->min, currange->min), cint64_one);
+ (++currange)->min = curcase->min;
+ } else if (CInt64_Greater(currange->min, min) && curcase->label->pclabel == currange[-1].label) {
+ currange[-1].range = CInt64_Add(currange[-1].range, cint64_one);
+ if (CInt64_Equal(currange->range, cint64_zero)) {
+ currange--;
+ } else {
+ currange->min = CInt64_Add(currange->min, cint64_one);
+ currange->range = CInt64_Sub(currange->range, cint64_one);
+ }
+ continue;
+ }
+
+ currange->range = cint64_zero;
+ currange->label = curcase->label->pclabel;
+
+ if (CInt64_Less(curcase->min, max)) {
+ currange++;
+ currange->min = CInt64_Add(curcase->min, cint64_one);
+ currange->range = CInt64_Sub(max, currange->min);
+ currange->label = label->pclabel;
+ }
+ }
+ }
+
+ nranges_minus1 = currange - caseranges;
}
-static void treecompare() {
+static void treecompare(SInt32 start, SInt32 end) {
+ SInt32 r30;
+ SInt32 r29;
+ CaseRange *currange;
+ int count;
+
+ count = end - start;
+#line 175
+ CError_ASSERT(selector_type->size <= 4);
+
+ r29 = start + (count >> 1) + 1;
+ currange = caseranges + r29;
+
+ if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) {
+ currange--;
+ r29--;
+ }
+
+ r30 = r29 - 1;
+
+ if (selector_type->size < 4 && is_unsigned(selector_type)) {
+ emitpcode(PC_CMPLI, 0, selector_gpr, CInt64_GetULong(&currange->min));
+ } else if (FITS_IN_SHORT((SInt32) CInt64_GetULong(&currange->min))) {
+ emitpcode(PC_CMPI, 0, selector_gpr, CInt64_GetULong(&currange->min));
+ } else {
+ SInt32 value = CInt64_GetULong(&currange->min);
+ int reg = ALLOC_GPR();
+ load_immediate(reg, value);
+ emitpcode(PC_CMP, 0, selector_gpr, reg);
+ }
+
+ if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) {
+ branch_conditional(0, EEQU, 1, currange->label);
+ r29++;
+ }
+
+ if (r29 == end) {
+ if (start == r30) {
+ if (caseranges[start].label == caseranges[end].label) {
+ branch_always(caseranges[start].label);
+ } else {
+ branch_conditional(0, EGREATEREQU, 1, caseranges[end].label);
+ branch_always(caseranges[start].label);
+ }
+ } else {
+ branch_conditional(0, EGREATEREQU, 1, caseranges[end].label);
+ treecompare(start, r30);
+ }
+ } else {
+ if (start == r30) {
+ branch_conditional(0, ELESS, 1, caseranges[start].label);
+ treecompare(r29, end);
+ } else {
+ PCodeLabel *label = makepclabel();
+ branch_conditional(0, EGREATEREQU, 1, label);
+ treecompare(start, r30);
+ branch_label(label);
+ treecompare(r29, end);
+ }
+ }
}
-static void I8_treecompare() {
+static void I8_treecompare(SInt32 start, SInt32 end) {
+ SInt32 r30;
+ SInt32 r29;
+ CaseRange *currange;
+ int count;
+
+ count = end - start;
+
+ r29 = start + (count >> 1) + 1;
+ currange = caseranges + r29;
+
+ if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) {
+ currange--;
+ r29--;
+ }
+
+ r30 = r29 - 1;
+
+ if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ emitpcode(PC_XOR, a, selector_gpr, a);
+ emitpcode(PC_XOR, b, selector_gprHi, b);
+ emitpcode(PC_OR, b, a, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, currange->label);
+ r29++;
+ }
+
+ if (r29 == end) {
+ if (start == r30) {
+ if (caseranges[start].label == caseranges[end].label) {
+ branch_always(caseranges[start].label);
+ } else {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, c);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, caseranges[end].label);
+ branch_always(caseranges[start].label);
+ }
+ } else {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, c);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, caseranges[end].label);
+ I8_treecompare(start, r30);
+ }
+ } else {
+ if (start == r30) {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, selector_gpr, a);
+ emitpcode(PC_SUBFE, b, c, d);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, ENOTEQU, 1, caseranges[end].label);
+ I8_treecompare(r29, end);
+ } else {
+ PCodeLabel *label;
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, b);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ label = makepclabel();
+ branch_conditional(0, EEQU, 1, label);
+ I8_treecompare(start, r30);
+ branch_label(label);
+ I8_treecompare(r29, end);
+ }
+ }
}
static void generate_tree(ENode *expr) {
+ Operand op;
+
+ memclrw(&op, sizeof(Operand));
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ GEN_NODE(expr, &op);
+ coerce_to_register_pair(&op, expr->rtype, 0, 0);
+ selector_type = expr->rtype;
+ selector_gpr = op.reg;
+ selector_gprHi = op.regHi;
+ I8_treecompare(0, nranges_minus1);
+ } else {
+ GEN_NODE(expr, &op);
+ if (expr->rtype->size < 4)
+ extend32(&op, expr->rtype, 0);
+ ENSURE_GPR(&op, expr->rtype, 0);
+ selector_type = expr->rtype;
+ selector_gpr = op.reg;
+ treecompare(0, nranges_minus1);
+ }
}
-static void create_switch_table() {
+static Object *create_switch_table(void) {
+ Object *obj;
+ ObjectList *list;
+ CaseRange *currange;
+ UInt32 *outptr;
+ CInt64 value;
+
+ obj = galloc(sizeof(Object));
+ list = galloc(sizeof(ObjectList));
+ memclrw(obj, sizeof(Object));
+ memclrw(list, sizeof(ObjectList));
+
+ obj->otype = OT_OBJECT;
+ obj->access = ACCESSPUBLIC;
+ obj->datatype = DDATA;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->sclass = TK_STATIC;
+ obj->qual = Q_CONST;
+ obj->flags |= OBJECT_FLAGS_2 | OBJECT_FLAGS_4;
+ obj->u.data.linkname = obj->name;
+ obj->type = NULL;
+ createIndirect(obj, 0, 0);
+ obj->type = TYPE(&void_ptr);
+
+ obj->u.data.u.switchtable.size = CInt64_GetULong(&range) + 1;
+ obj->u.data.u.switchtable.data = lalloc(4 * obj->u.data.u.switchtable.size);
+
+ currange = caseranges;
+ outptr = (UInt32 *) obj->u.data.u.switchtable.data;
+ value = cint64_zero;
+ while (CInt64_LessEqual(value, range)) {
+ while (CInt64_Greater(CInt64_Add(first, value), CInt64_Add(currange->min, currange->range)))
+ currange++;
+ // HACK - this will not work properly on 64-bit systems
+ *outptr = (UInt32) currange->label;
+ value = CInt64_Add(value, cint64_one);
+ outptr++;
+ }
+
+ list->object = obj;
+ list->next = switchtables;
+ switchtables = list;
+ return list->object;
}
static void generate_table(ENode *expr, SwitchInfo *info) {
+ Object *table;
+ short reg;
+ short reg2;
+ short reg3;
+ SwitchCase *curcase;
+ Operand op1;
+ Operand op2;
+
+ CInt64 val3 = {0, 3};
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ if (CInt64_Greater(first, cint64_zero) && CInt64_Less(first, val3)) {
+ range = CInt64_Add(range, first);
+ first = cint64_zero;
+ }
+
+ table = create_switch_table();
+#line 553
+ CError_ASSERT(!TYPE_IS_8BYTES(expr->rtype));
+
+ GEN_NODE(expr, &op1);
+ if (expr->rtype->size < 4)
+ extend32(&op1, expr->rtype, 0);
+ ENSURE_GPR(&op1, expr->rtype, 0);
+
+ reg = op1.reg;
+ if (CInt64_NotEqual(first, cint64_zero)) {
+ SInt32 value;
+ SInt32 valueext;
+ reg = ALLOC_GPR();
+ value = -CInt64_GetULong(&first);
+ valueext = (SInt16) value;
+ if (value != valueext) {
+ emitpcode(PC_ADDIS, reg, op1.reg, 0, HIGH_PART(value));
+ if (value)
+ emitpcode(PC_ADDI, reg, reg, 0, valueext);
+ } else {
+ emitpcode(PC_ADDI, reg, op1.reg, 0, value);
+ }
+ }
+
+ if (FITS_IN_SHORT(CInt64_GetULong(&range))) {
+ short tmp = ALLOC_GPR();
+ load_immediate(tmp, CInt64_GetULong(&range));
+ emitpcode(PC_CMPL, 0, reg, tmp);
+ } else {
+ emitpcode(PC_CMPLI, 0, reg, CInt64_GetULong(&range));
+ }
+
+ branch_conditional(0, EGREATER, 0, defaultlabel);
+ if (table->toc) {
+ op2.optype = OpndType_Symbol;
+ op2.object = table->toc;
+ indirect(&op2, NULL);
+ } else {
+ op2.optype = OpndType_Symbol;
+ op2.object = table;
+ }
+
+ if (op2.optype != OpndType_GPR) {
+ reg2 = ALLOC_GPR();
+ Coerce_to_register(&op2, TYPE(&void_ptr), reg2);
+ }
+
+ if (op2.optype != OpndType_GPR) {
+#line 599
+ CError_FATAL();
+ } else {
+ if (op2.reg != reg2)
+ emitpcode(PC_MR, reg2, op2.reg);
+ }
+
+ if (CInt64_Equal(first, cint64_zero)) {
+ reg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, op1.reg, 2, 0, 29);
+ } else {
+ emitpcode(PC_RLWINM, reg, reg, 2, 0, 29);
+ }
+
+ reg3 = reg2;
+ emitpcode(PC_LWZX, reg3, reg3, reg);
+ for (curcase = info->cases; curcase; curcase = curcase->next)
+ pcbranch(pclastblock, curcase->label->pclabel);
+ pcbranch(pclastblock, info->defaultlabel->pclabel);
+ emitpcode(PC_MTCTR, reg3);
+ branch_indirect(table);
}
void switchstatement(ENode *expr, SwitchInfo *info) {
@@ -55,7 +483,7 @@ void switchstatement(ENode *expr, SwitchInfo *info) {
}
#line 656
- CError_ASSERT(ncases >= 0 && ncases <= 0x3333332);
+ CError_ASSERT(ncases >= 0 && ncases <= 0x3333332U);
if (!info->defaultlabel->pclabel)
info->defaultlabel->pclabel = makepclabel();
@@ -68,11 +496,30 @@ void switchstatement(ENode *expr, SwitchInfo *info) {
return;
}
- if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 1) + 4))
+ if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 2) + 4))
generate_tree(expr);
else
generate_table(expr, info);
}
void dumpswitchtables(Object *funcobj) {
+ Object *table;
+ ObjectList *list;
+ SInt32 size;
+ UInt32 *array;
+
+ for (list = switchtables; list; list = list->next) {
+ table = list->object;
+#line 694
+ CError_ASSERT(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;
+ while (size--) {
+ *array = CTool_EndianConvertWord32(((PCodeLabel *) *array)->block->codeOffset);
+ array++;
+ }
+
+ ObjGen_DeclareSwitchTable(table, funcobj);
+ }
}
diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c
index 0f3024f..94ecb27 100644
--- a/compiler_and_linker/unsorted/TOC.c
+++ b/compiler_and_linker/unsorted/TOC.c
@@ -8,6 +8,7 @@
#include "compiler/CMangler.h"
#include "compiler/CParser.h"
#include "compiler/CodeGen.h"
+#include "compiler/InstrSelection.h"
#include "compiler/Operands.h"
#include "compiler/PCode.h"
#include "compiler/PCodeInfo.h"
diff --git a/compiler_and_linker/unsorted/UseDefChains.c b/compiler_and_linker/unsorted/UseDefChains.c
index e69de29..1840548 100644
--- a/compiler_and_linker/unsorted/UseDefChains.c
+++ b/compiler_and_linker/unsorted/UseDefChains.c
@@ -0,0 +1,563 @@
+#include "compiler/UseDefChains.h"
+#include "compiler/Alias.h"
+#include "compiler/PCode.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler/BitVectors.h"
+
+int number_of_Defs;
+UseOrDef *Defs;
+RegUseOrDef **reg_Defs[RegClassMax];
+int number_of_Uses;
+UseOrDef *Uses;
+RegUseOrDef **reg_Uses[RegClassMax];
+UseDefInfo *usedefinfo;
+ObjectUseDef *objectusedefs;
+ObjectUseDef *objectusedeflist;
+
+ObjectUseDef *findobjectusedef(Object *object) {
+ ObjectUseDef *oud;
+
+ oud = objectusedefs;
+ while (oud) {
+ if (((unsigned long) object) < ((unsigned long) oud->object))
+ oud = oud->leftchild;
+ else if (((unsigned long) object) > ((unsigned long) oud->object))
+ oud = oud->rightchild;
+ else
+ return oud;
+ }
+
+ return NULL;
+}
+
+static void addobjectusedef(Object *object) {
+ ObjectUseDef **ptr;
+ ObjectUseDef *list;
+
+ ptr = &objectusedefs;
+ while (*ptr) {
+ if (((unsigned long) object) < ((unsigned long) (*ptr)->object))
+ ptr = &(*ptr)->leftchild;
+ else if (((unsigned long) object) > ((unsigned long) (*ptr)->object))
+ ptr = &(*ptr)->rightchild;
+ else
+ return;
+ }
+
+ list = oalloc(sizeof(ObjectUseDef));
+ list->leftchild = list->rightchild = NULL;
+ list->object = object;
+ list->uses = list->defs = NULL;
+ list->next = objectusedeflist;
+ objectusedeflist = list;
+ *ptr = list;
+}
+
+static void addaliasusedef(Alias *alias) {
+ AliasMember *member;
+
+ if (alias && alias != worst_case) {
+ if (alias->type == AliasType2) {
+ for (member = alias->parents; member; member = member->nextParent)
+ addaliasusedef(member->child);
+ } else {
+ addobjectusedef(alias->object);
+ }
+ }
+}
+
+static void addworstcase(void) {
+ addobjectusedef(&worst_case_obj);
+}
+
+static void precomputememoryusedefs(void) {
+ PCodeBlock *block;
+ PCode *pcode;
+
+ objectusedeflist = NULL;
+ objectusedefs = NULL;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ if (pcode->alias) {
+ if (pcode->alias->type == AliasType2 || pcode->alias->size != nbytes_loaded_or_stored_by(pcode))
+ pcode->flags |= fPCodeFlag20;
+ addaliasusedef(pcode->alias);
+ } else {
+ pcode->flags |= fPCodeFlag20;
+ }
+ }
+ }
+ }
+
+ addworstcase();
+}
+
+static void precomputeusedefcounts(int flag) {
+ PCodeBlock *block;
+ PCode *pcode;
+ PCodeArg *op;
+ int i;
+ ObjectUseDef *oud;
+
+ number_of_Defs = 0;
+ number_of_Uses = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ pcode->useID = number_of_Uses;
+ pcode->defID = number_of_Defs;
+ op = pcode->args;
+ i = pcode->argCount;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) {
+ if (op->data.reg.effect & EffectRead)
+ number_of_Uses++;
+ if (op->data.reg.effect & EffectWrite)
+ number_of_Defs++;
+ }
+ op++;
+ }
+
+ if (flag) {
+ if (pcode->flags & fPCodeFlag2) {
+ if (pcode->flags & fPCodeFlag20) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ if (may_alias_object(pcode, oud->object))
+ number_of_Uses++;
+ }
+ } else {
+ number_of_Uses++;
+ }
+ } else if (pcode->flags & fPCodeFlag4) {
+ if (pcode->flags & fPCodeFlag20) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ if (may_alias_object(pcode, oud->object))
+ number_of_Defs++;
+ }
+ } else {
+ number_of_Defs++;
+ }
+ } else if (pcode->flags & fPCodeFlag8) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ if (
+ oud->object->datatype == DDATA ||
+ oud->object->datatype == DNONLAZYPTR ||
+ (oud->object->datatype == DLOCAL && (
+ oud->object->u.var.info->noregister ||
+ IS_TYPE_ARRAY(oud->object->type) ||
+ IS_TYPE_NONVECTOR_STRUCT(oud->object->type) ||
+ IS_TYPE_CLASS(oud->object->type) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(oud->object->type)
+ ))
+ ) {
+ number_of_Uses++;
+ number_of_Defs++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void computeusedeflists(int flag) {
+ ObjectUseDef *oud;
+ RegUseOrDef *list;
+ PCodeBlock *block;
+ PCode *pcode;
+ PCodeArg *op;
+ int i;
+ UseOrDef *use;
+ UseOrDef *def;
+ int useID;
+ int defID;
+ ObjectUseDef *tmp;
+ Object *object;
+
+ Uses = oalloc(sizeof(UseOrDef) * number_of_Uses);
+ Defs = oalloc(sizeof(UseOrDef) * number_of_Defs);
+
+ reg_Uses[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]);
+ reg_Defs[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]);
+ for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) {
+ reg_Uses[RegClass_GPR][i] = NULL;
+ reg_Defs[RegClass_GPR][i] = NULL;
+ }
+
+ reg_Uses[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]);
+ reg_Defs[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]);
+ for (i = 0; i < used_virtual_registers[RegClass_FPR]; i++) {
+ reg_Uses[RegClass_FPR][i] = NULL;
+ reg_Defs[RegClass_FPR][i] = NULL;
+ }
+
+ reg_Uses[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]);
+ reg_Defs[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]);
+ for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) {
+ reg_Uses[RegClass_VR][i] = NULL;
+ reg_Defs[RegClass_VR][i] = NULL;
+ }
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ use = &Uses[useID = pcode->useID];
+ def = &Defs[defID = pcode->defID];
+
+ op = pcode->args;
+ i = pcode->argCount;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) {
+ if (op->data.reg.effect & EffectRead) {
+ use->pcode = pcode;
+ use->v.kind = op->kind;
+ use->v.arg = op->arg;
+ use->v.u.reg = op->data.reg.reg;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = useID;
+ list->next = reg_Uses[op->arg][op->data.reg.reg];
+ reg_Uses[op->arg][op->data.reg.reg] = list;
+ use++;
+ useID++;
+ }
+ if (op->data.reg.effect & EffectWrite) {
+ def->pcode = pcode;
+ def->v.kind = op->kind;
+ def->v.arg = op->arg;
+ def->v.u.reg = op->data.reg.reg;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = defID;
+ list->next = reg_Defs[op->arg][op->data.reg.reg];
+ reg_Defs[op->arg][op->data.reg.reg] = list;
+ def++;
+ defID++;
+ }
+ }
+ op++;
+ }
+
+ if (flag) {
+ if (pcode->flags & fPCodeFlag2) {
+ if (pcode->flags & fPCodeFlag20) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ if (may_alias_object(pcode, object = oud->object)) {
+ use->pcode = pcode;
+ use->v.kind = PCOp_MEMORY;
+ use->v.arg = 1;
+ use->v.u.object = object;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = useID;
+ list->next = oud->uses;
+ oud->uses = list;
+ use++;
+ useID++;
+ }
+ }
+ } else {
+ object = pcode->alias->object;
+ use->pcode = pcode;
+ use->v.kind = PCOp_MEMORY;
+ use->v.arg = 0;
+ use->v.u.object = object;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = useID;
+ tmp = findobjectusedef(object);
+ list->next = tmp->uses;
+ tmp->uses = list;
+ }
+ } else if (pcode->flags & fPCodeFlag4) {
+ if (pcode->flags & fPCodeFlag20) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ if (may_alias_object(pcode, object = oud->object)) {
+ def->pcode = pcode;
+ def->v.kind = PCOp_MEMORY;
+ def->v.arg = 1;
+ def->v.u.object = object;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = defID;
+ list->next = oud->defs;
+ oud->defs = list;
+ def++;
+ defID++;
+ }
+ }
+ } else {
+ object = pcode->alias->object;
+ def->pcode = pcode;
+ def->v.kind = PCOp_MEMORY;
+ def->v.arg = 0;
+ def->v.u.object = object;
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = useID;
+ tmp = findobjectusedef(object);
+ list->next = tmp->defs;
+ tmp->defs = list;
+ }
+ } else if (pcode->flags & fPCodeFlag8) {
+ for (oud = objectusedeflist; oud; oud = oud->next) {
+ object = oud->object;
+ if (
+ object->datatype == DDATA ||
+ object->datatype == DNONLAZYPTR ||
+ (object->datatype == DLOCAL && (
+ object->u.var.info->noregister ||
+ IS_TYPE_ARRAY(object->type) ||
+ IS_TYPE_NONVECTOR_STRUCT(object->type) ||
+ IS_TYPE_CLASS(oud->object->type) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(object->type)
+ ))
+ ) {
+ use->pcode = pcode;
+ use->v.kind = PCOp_MEMORY;
+ use->v.arg = 1;
+ use->v.u.object = object;
+
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = useID;
+ list->next = oud->uses;
+ oud->uses = list;
+
+ def->pcode = pcode;
+ def->v.kind = PCOp_MEMORY;
+ def->v.arg = 1;
+ def->v.u.object = object;
+
+ use++;
+ useID++;
+
+ list = oalloc(sizeof(RegUseOrDef));
+ list->id = defID;
+ list->next = oud->defs;
+ oud->defs = list;
+
+ def++;
+ defID++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void allocateusedefinfo(void) {
+ UseDefInfo *info;
+ int i;
+
+ usedefinfo = oalloc(pcblockcount * sizeof(UseDefInfo));
+ for (i = 0, info = usedefinfo; i < pcblockcount; i++, info++) {
+ info->defvec0 = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ info->defvec4 = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ info->defvec8 = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ info->defvecC = oalloc(4 * ((number_of_Defs + 31) >> 5));
+ info->usevec10 = oalloc(4 * ((number_of_Uses + 31) >> 5));
+ info->usevec14 = oalloc(4 * ((number_of_Uses + 31) >> 5));
+ info->usevec18 = oalloc(4 * ((number_of_Uses + 31) >> 5));
+ info->usevec1C = oalloc(4 * ((number_of_Uses + 31) >> 5));
+ }
+}
+
+static void computelocalusedefinfo(void) {
+ PCodeBlock *block; // r28
+ PCode *pcode; // r27
+ UInt32 *defvec0; // r26
+ UInt32 *defvec4; // r25
+ UInt32 *usevec10; // r24
+ UInt32 *usevec14; // r23
+ UseOrDef *use; // r22
+ UseOrDef *def; // r22
+ int useID; // r15
+ int defID; // r21
+ ObjectUseDef *oud; // r17
+ RegUseOrDef *list; // r16
+ UseDefInfo *info; // r15
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ info = &usedefinfo[block->blockIndex];
+ defvec0 = info->defvec0;
+ defvec4 = info->defvec4;
+ usevec10 = info->usevec10;
+ usevec14 = info->usevec14;
+ bitvectorinitialize(defvec0, number_of_Defs, 0);
+ bitvectorinitialize(defvec4, number_of_Defs, 0);
+ bitvectorinitialize(usevec10, number_of_Uses, 0);
+ bitvectorinitialize(usevec14, number_of_Uses, 0);
+ bitvectorinitialize(info->defvec8, number_of_Defs, 0);
+ bitvectorinitialize(info->defvecC, number_of_Defs, 0);
+ bitvectorinitialize(info->usevec18, number_of_Uses, 0);
+ bitvectorinitialize(info->usevec1C, number_of_Uses, 0);
+
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) {
+ for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) {
+ bitvectorsetbit(useID, usevec10);
+ if (use->v.kind == PCOp_REGISTER) {
+ for (list = reg_Defs[use->v.arg][use->v.u.reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, defvec0))
+ bitvectorclearbit(useID, usevec10);
+ }
+ } else {
+ for (list = findobjectusedef(use->v.u.object)->defs; list; list = list->next) {
+ if (uniquely_aliases(pcode, Defs[list->id].pcode)) {
+ if (Defs[list->id].v.arg == 0 && bitvectorgetbit(list->id, defvec0))
+ bitvectorclearbit(useID, usevec10);
+ }
+ }
+ }
+ }
+
+ for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; def++, defID++) {
+ if (def->v.kind == PCOp_REGISTER) {
+ for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next) {
+ if (Uses[list->id].pcode->block != block)
+ bitvectorsetbit(list->id, usevec14);
+ }
+ for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) {
+ if (Defs[list->id].pcode->block != block)
+ bitvectorsetbit(list->id, defvec4);
+ else
+ bitvectorclearbit(list->id, defvec0);
+ }
+ } else if (def->v.arg == 0) {
+ oud = findobjectusedef(use->v.u.object);
+ for (list = oud->uses; list; list = list->next) {
+ if (may_alias(pcode, Uses[list->id].pcode)) {
+ if (Uses[list->id].pcode->block != block)
+ bitvectorsetbit(list->id, usevec14);
+ }
+ }
+ for (list = oud->defs; list; list = list->next) {
+ if (uniquely_aliases(pcode, Defs[list->id].pcode)) {
+ if (Defs[list->id].pcode->block != block)
+ bitvectorsetbit(list->id, defvec4);
+ else
+ bitvectorclearbit(list->id, defvec0);
+ }
+ }
+ }
+
+ bitvectorsetbit(defID, defvec0);
+ }
+ }
+ }
+ }
+}
+
+static void computeglobalusedefinfo(void) {
+ UseDefInfo *udi;
+ UInt32 *defVec0;
+ UInt32 *defVec4;
+ UInt32 *defVec8;
+ UInt32 *defVecC;
+ int bitvecsize;
+ int i;
+ int j;
+ int flag;
+ PCLink *preds;
+ UInt32 val;
+
+ bitvecsize = (number_of_Defs + 31) >> 5;
+ flag = 1;
+ while (flag) {
+ flag = 0;
+ for (i = 0; i < pcblockcount; i++) {
+ if (depthfirstordering[i]) {
+ udi = &usedefinfo[depthfirstordering[i]->blockIndex];
+ if ((preds = depthfirstordering[i]->predecessors)) {
+ defVec8 = udi->defvec8;
+ bitvectorcopy(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs);
+ for (preds = preds->nextLink; preds; preds = preds->nextLink)
+ bitvectorunion(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs);
+ }
+
+ defVecC = udi->defvecC;
+ defVec8 = udi->defvec8;
+ defVec0 = udi->defvec0;
+ defVec4 = udi->defvec4;
+ for (j = 0; j < bitvecsize; j++) {
+ val = *defVec0 | (*defVec8 & ~*defVec4);
+ if (val != *defVecC) {
+ *defVecC = val;
+ flag = 1;
+ }
+ defVec8++;
+ defVecC++;
+ defVec4++;
+ defVec0++;
+ }
+ }
+ }
+ }
+}
+
+static void computeglobaldefuseinfo(void) {
+ UseDefInfo *udi;
+ UInt32 *useVec10;
+ UInt32 *useVec14;
+ UInt32 *useVec18;
+ UInt32 *useVec1C;
+ int bitvecsize;
+ int i;
+ int j;
+ int flag;
+ PCLink *succs;
+ UInt32 val;
+ PCodeBlock *block;
+
+ bitvecsize = (number_of_Uses + 31) >> 5;
+ flag = 1;
+ while (flag) {
+ flag = 0;
+ i = pcblockcount;
+ while (i) {
+ if ((block = depthfirstordering[--i])) {
+ udi = &usedefinfo[block->blockIndex];
+ if ((succs = block->successors)) {
+ useVec1C = udi->usevec1C;
+ bitvectorcopy(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses);
+ for (succs = succs->nextLink; succs; succs = succs->nextLink)
+ bitvectorunion(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses);
+ }
+
+ useVec1C = udi->usevec1C;
+ useVec18 = udi->usevec18;
+ useVec10 = udi->usevec10;
+ useVec14 = udi->usevec14;
+ for (j = 0; j < bitvecsize; j++) {
+ val = *useVec10 | (*useVec1C & ~*useVec14);
+ if (val != *useVec18) {
+ *useVec18 = val;
+ flag = 1;
+ }
+ useVec18++;
+ useVec1C++;
+ useVec14++;
+ useVec10++;
+ }
+ }
+ }
+ }
+}
+
+void computeusedefchains(int flag) {
+ if (flag) {
+ gather_alias_info();
+ precomputememoryusedefs();
+ }
+
+ precomputeusedefcounts(flag);
+ computeusedeflists(flag);
+ allocateusedefinfo();
+ computelocalusedefinfo();
+ computedepthfirstordering();
+ computeglobalusedefinfo();
+ computeglobaldefuseinfo();
+}
+
diff --git a/compiler_and_linker/unsorted/ValueNumbering.c b/compiler_and_linker/unsorted/ValueNumbering.c
index e69de29..e8e05c6 100644
--- a/compiler_and_linker/unsorted/ValueNumbering.c
+++ b/compiler_and_linker/unsorted/ValueNumbering.c
@@ -0,0 +1,664 @@
+#include "compiler/ValueNumbering.h"
+#include "compiler/Alias.h"
+#include "compiler/PCode.h"
+#include "compiler/Registers.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CError.h"
+
+typedef struct ValueLabel {
+ struct ValueLabel *next;
+ PCodeArg op;
+} ValueLabel;
+
+typedef struct AvailableValue {
+ struct AvailableValue *next;
+ ValueLabel *labelled;
+ PCode *pcode;
+ int killedregister;
+ int aliasnumber;
+ int opnumbers[0];
+} AvailableValue;
+
+typedef struct RegValue {
+ int number;
+ int x4;
+ AvailableValue *available;
+} RegValue;
+
+typedef struct State {
+ void *stackedvalues;
+ int valueceiling;
+} State;
+
+typedef struct StackedValue {
+ struct StackedValue *next;
+ PCodeArg op;
+ RegValue value;
+ Alias *alias;
+ PCode *valuepcode;
+} StackedValue;
+
+int removedcommonsubexpressions;
+int nextvaluenumber;
+static AvailableValue *opvalue[428];
+static RegValue *regvalue[RegClassMax];
+static StackedValue *stackedvalues;
+static int valueceiling;
+static int moreaggressiveoptimization;
+
+static void allocatecsedatastructures(void) {
+ char rclass;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ regvalue[(char) rclass] = oalloc(sizeof(RegValue) * used_virtual_registers[(char) rclass]);
+}
+
+static void initializecsedatastructures(void) {
+ RegValue *rv;
+ char rclass;
+ int i;
+
+ nextvaluenumber = 0;
+
+ for (i = 0; i < 428; i++)
+ opvalue[i] = NULL;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ rv = regvalue[(char) rclass];
+ for (i = 0; i < used_virtual_registers[(char) rclass]; i++, rv++) {
+ rv->number = nextvaluenumber++;
+ rv->x4 = 0;
+ rv->available = NULL;
+ }
+ }
+
+ initialize_alias_values();
+ stackedvalues = NULL;
+ valueceiling = 0x7FFFFFFF;
+}
+
+static void labelvalue(AvailableValue *av, PCodeArg *op) {
+ ValueLabel *label = oalloc(sizeof(ValueLabel));
+ label->op = *op;
+ label->next = av->labelled;
+ av->labelled = label;
+}
+
+static void unlabelvalue(AvailableValue *av, PCodeArg *op) {
+ ValueLabel *labelled;
+ ValueLabel **ptr;
+
+ ptr = &av->labelled;
+ while ((labelled = *ptr)) {
+ if (labelled->op.data.reg.reg == op->data.reg.reg)
+ *ptr = labelled->next;
+ else
+ ptr = &labelled->next;
+ }
+}
+
+static void stackregistervalue(PCodeArg *op, RegValue *value) {
+ StackedValue *stacked = oalloc(sizeof(StackedValue));
+ stacked->next = stackedvalues;
+ stackedvalues = stacked;
+
+ stacked->op = *op;
+ stacked->value = *value;
+}
+
+static void stackmemoryvalue(Alias *alias) {
+ StackedValue *stacked = oalloc(sizeof(StackedValue));
+ stacked->next = stackedvalues;
+ stackedvalues = stacked;
+
+ stacked->op.kind = PCOp_MEMORY;
+ stacked->alias = alias;
+ stacked->value.number = alias->valuenumber;
+ stacked->valuepcode = alias->valuepcode;
+}
+
+static void unstackvalue(StackedValue *stacked) {
+ PCodeArg *op = &stacked->op;
+ RegValue *value;
+
+ if (stacked->op.kind == PCOp_MEMORY) {
+ stacked->alias->valuenumber = stacked->value.number;
+ stacked->alias->valuepcode = stacked->valuepcode;
+ } else {
+ value = &regvalue[op->arg][op->data.reg.reg];
+ if (value->available)
+ unlabelvalue(value->available, op);
+ value->number = stacked->value.number;
+ value->x4 = stacked->value.x4;
+ value->available = stacked->value.available;
+ if (value->available)
+ labelvalue(value->available, op);
+ }
+}
+
+static int samevalue(PCodeArg *op1, PCodeArg *op2) {
+ return regvalue[op1->arg][op1->data.reg.reg].number == regvalue[op2->arg][op2->data.reg.reg].number;
+}
+
+static int killregister(PCodeArg *op) {
+ RegValue *value;
+
+ value = &regvalue[op->arg][op->data.reg.reg];
+ if (value->number < valueceiling && nextvaluenumber >= valueceiling)
+ stackregistervalue(op, value);
+
+ if (value->available)
+ unlabelvalue(value->available, op);
+ value->available = NULL;
+ value->x4 = 0;
+ return value->number = nextvaluenumber++;
+}
+
+void killmemory(Alias *alias, PCode *newValue) {
+ if (alias->valuenumber < valueceiling && nextvaluenumber >= valueceiling)
+ stackmemoryvalue(alias);
+
+ if (newValue) {
+ alias->valuenumber = regvalue[newValue->args[0].arg][newValue->args[0].data.reg.reg].number;
+ alias->valuepcode = newValue;
+ } else {
+ alias->valuenumber = nextvaluenumber++;
+ alias->valuepcode = NULL;
+ }
+}
+
+static void killspecificCSEs(short op) {
+ AvailableValue *av;
+ ValueLabel *labelled;
+
+ for (av = opvalue[op]; av; av = av->next) {
+ for (labelled = av->labelled; labelled; labelled = labelled->next)
+ killregister(&labelled->op);
+ }
+}
+
+static void killallCSEs(void) {
+ AvailableValue *av;
+ ValueLabel *labelled;
+ int i;
+
+ for (i = 0; i < 428; i++) {
+ for (av = opvalue[i]; av; av = av->next) {
+ for (labelled = av->labelled; labelled; labelled = labelled->next)
+ killregister(&labelled->op);
+ }
+ }
+}
+
+static void killregisters(PCode *pcode) {
+ PCodeArg *op;
+ int i;
+
+ for (i = 0, op = pcode->args; i < pcode->argCount; i++, op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite))
+ killregister(op);
+ }
+}
+
+static void copyregister(PCodeArg *src, PCodeArg *dest) {
+ RegValue *srcvalue;
+ RegValue *destvalue;
+
+ srcvalue = &regvalue[src->arg][src->data.reg.reg];
+ destvalue = &regvalue[dest->arg][dest->data.reg.reg];
+
+ if (destvalue->number < valueceiling && nextvaluenumber >= valueceiling)
+ stackregistervalue(dest, destvalue);
+
+ if (destvalue->available)
+ unlabelvalue(destvalue->available, dest);
+ destvalue->available = srcvalue->available;
+ if (destvalue->available)
+ labelvalue(destvalue->available, dest);
+
+ destvalue->number = srcvalue->number;
+
+ if (srcvalue->x4 && srcvalue->number == regvalue[src->arg][srcvalue->x4].number)
+ destvalue->x4 = srcvalue->x4;
+ else
+ destvalue->x4 = src->data.reg.reg;
+}
+
+static int matchvalues(AvailableValue *av, PCode *match) {
+ PCodeArg *avOp;
+ PCodeArg *matchOp;
+ int i;
+
+ for (avOp = &av->pcode->args[0], matchOp = &match->args[0], i = 0; i < match->argCount; i++, avOp++, matchOp++) {
+ if (i != 0) {
+ switch (avOp->kind) {
+ case PCOp_REGISTER:
+ if (av->opnumbers[i] != regvalue[matchOp->arg][matchOp->data.reg.reg].number)
+ return 0;
+ break;
+ case PCOp_MEMORY:
+ if (matchOp->kind != PCOp_MEMORY)
+ return 0;
+ if (matchOp->data.mem.obj != avOp->data.mem.obj)
+ return 0;
+ if (matchOp->data.mem.offset != avOp->data.mem.offset)
+ return 0;
+ if ((unsigned char) matchOp->arg != (unsigned char) avOp->arg)
+ return 0;
+ break;
+ case PCOp_IMMEDIATE:
+ if (matchOp->kind != PCOp_IMMEDIATE)
+ return 0;
+ if (matchOp->data.imm.value != avOp->data.imm.value)
+ return 0;
+ break;
+ case PCOp_LABEL:
+ if (matchOp->kind != PCOp_LABEL)
+ return 0;
+ if (matchOp->data.label.label != avOp->data.label.label)
+ return 0;
+ break;
+ case PCOp_SYSREG:
+#line 572
+ CError_FATAL();
+ }
+ }
+ }
+
+ if ((match->flags & (fPCodeFlag2 | fPCodeFlag20000)) && match->alias->valuenumber != av->aliasnumber)
+ return 0;
+
+ return 1;
+}
+
+static void chooselocation(AvailableValue *av, PCodeArg *op) {
+ ValueLabel *labelled;
+ PCodeArg *baseop;
+
+ baseop = &av->pcode->args[0];
+ labelled = av->labelled;
+ while (labelled) {
+ if (labelled->op.data.reg.reg == baseop->data.reg.reg) {
+ *op = labelled->op;
+ return;
+ }
+ labelled = labelled->next;
+ }
+
+ *op = av->labelled[0].op;
+}
+
+static int findavailablevalue(PCode *pcode, PCodeArg *op) {
+ AvailableValue *av;
+ PCodeArg tmp1;
+ PCodeArg tmp2;
+
+ for (av = opvalue[pcode->op]; av; av = av->next) {
+ if (av->labelled && av->pcode->flags == pcode->flags && av->pcode->argCount == pcode->argCount) {
+ if (!matchvalues(av, pcode)) {
+ if (!(pcode->flags & fCommutative))
+ continue;
+
+ tmp1 = pcode->args[1];
+ pcode->args[1] = pcode->args[2];
+ pcode->args[2] = tmp1;
+
+ if (!matchvalues(av, pcode)) {
+ tmp2 = pcode->args[1];
+ pcode->args[1] = pcode->args[2];
+ pcode->args[2] = tmp2;
+ continue;
+ }
+ }
+ chooselocation(av, op);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void addavailablevalue(PCode *pcode) {
+ AvailableValue *av;
+ PCodeArg *op;
+ int i;
+
+ av = oalloc(sizeof(AvailableValue) + sizeof(int) * pcode->argCount);
+ av->labelled = NULL;
+ av->pcode = pcode;
+ for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) {
+ if (op->kind == PCOp_REGISTER)
+ av->opnumbers[i] = regvalue[op->arg][op->data.reg.reg].number;
+ }
+
+ if (pcode->flags & (fPCodeFlag2 | fPCodeFlag20000))
+ av->aliasnumber = pcode->alias->valuenumber;
+
+ op = &pcode->args[0];
+ av->killedregister = killregister(op);
+ labelvalue(av, op);
+ regvalue[op->arg][op->data.reg.reg].available = av;
+ av->next = opvalue[pcode->op];
+ opvalue[pcode->op] = av;
+}
+
+static int isCSEop(PCode *pcode) {
+ PCodeArg *baseOp;
+ PCodeArg *op;
+ int i;
+
+ baseOp = &pcode->args[0];
+
+ switch (pcode->op) {
+ case PC_CMPI:
+ case PC_CMP:
+ case PC_CMPLI:
+ case PC_CMPL:
+ case PC_FCMPU:
+ case PC_FCMPO:
+ if (!moreaggressiveoptimization)
+ return 0;
+ break;
+ case PC_LI:
+ case PC_LIS:
+ if (!moreaggressiveoptimization)
+ return 0;
+ if (pcode->args[0].data.reg.reg < first_fe_temporary_register[RegClass_GPR] || pcode->args[0].data.reg.reg > last_temporary_register[RegClass_GPR])
+ return 0;
+ break;
+ }
+
+ if (PCODE_FLAG_SET_F(pcode) & (fIsVolatile | fSideEffects | fOverflow | fPCodeFlag10000000 | fPCodeFlag20000000))
+ return 0;
+
+ for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) {
+ if (op != baseOp &&
+ op->kind == baseOp->kind &&
+ op->arg == baseOp->arg &&
+ op->data.reg.reg == baseOp->data.reg.reg)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int isCSEload(PCode *pcode) {
+ PCodeArg *op;
+ int i;
+ int count;
+
+ count = 0;
+ for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite))
+ count++;
+ }
+
+ return count == 1;
+}
+
+static void registercopy(PCode *pcode) {
+ PCodeArg *op1;
+ PCodeArg *op2;
+
+ op1 = &pcode->args[0];
+ op2 = &pcode->args[1];
+ if (samevalue(op2, op1))
+ deletepcode(pcode);
+ else
+ copyregister(op2, op1);
+}
+
+static PCode *recentlystored(Alias *alias, PCodeArg *op) {
+ PCode *pc;
+ if ((pc = alias->valuepcode) && alias->valuenumber == regvalue[pc->args[0].arg][pc->args[0].data.reg.reg].number) {
+ *op = pc->args[0];
+ return pc;
+ } else {
+ return NULL;
+ }
+}
+
+static void simpleload(PCode *pcode) {
+ PCodeArg *origOp;
+ PCodeArg op;
+ PCode *rs;
+
+ origOp = &pcode->args[0];
+ if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) {
+ killregisters(pcode);
+ return;
+ }
+
+ if (findavailablevalue(pcode, &op)) {
+ if (!samevalue(origOp, &op)) {
+ insertpcodebefore(pcode, makecopyinstruction(&op, origOp));
+ copyregister(&op, origOp);
+ }
+ deletepcode(pcode);
+ removedcommonsubexpressions = 1;
+ } else if ((rs = recentlystored(pcode->alias, &op)) && can_reuse_stored_value(rs, pcode)) {
+ if (!samevalue(origOp, &op)) {
+ insertpcodebefore(pcode, makecopyinstruction(&op, origOp));
+ copyregister(&op, origOp);
+ }
+ deletepcode(pcode);
+ removedcommonsubexpressions = 1;
+ } else {
+ addavailablevalue(pcode);
+ }
+}
+
+static void simplestore(PCode *pcode) {
+ update_alias_value(pcode->alias, pcode);
+ killregisters(pcode);
+}
+
+static void pointerload(PCode *pcode) {
+ PCodeArg *op;
+ PCodeArg buf;
+
+ op = &pcode->args[0];
+
+ if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) {
+ killregisters(pcode);
+ return;
+ }
+
+ if (findavailablevalue(pcode, &buf)) {
+ if (!samevalue(op, &buf)) {
+ insertpcodebefore(pcode, makecopyinstruction(&buf, op));
+ copyregister(&buf, op);
+ }
+ deletepcode(pcode);
+ removedcommonsubexpressions = 1;
+ } else {
+ addavailablevalue(pcode);
+ }
+}
+
+static void pointerstore(PCode *pcode) {
+ update_alias_value(pcode->alias, NULL);
+ killregisters(pcode);
+}
+
+static void arithmeticop(PCode *pcode) {
+ PCodeArg *op;
+ PCodeArg buf;
+
+ op = &pcode->args[0];
+
+ if (findavailablevalue(pcode, &buf)) {
+ if (!samevalue(op, &buf)) {
+ insertpcodebefore(pcode, makecopyinstruction(&buf, op));
+ copyregister(&buf, op);
+ }
+ deletepcode(pcode);
+ removedcommonsubexpressions = 1;
+ } else {
+ addavailablevalue(pcode);
+ }
+}
+
+static void functioncall(PCode *pcode) {
+ killregisters(pcode);
+ if (coloring) {
+ update_all_alias_values();
+ killallCSEs();
+ } else {
+ update_alias_value(pcode->alias, NULL);
+ }
+}
+
+static void operatefrommemory(PCode *pcode) {
+#line 980
+ CError_FATAL();
+}
+
+static void operatetomemory(PCode *pcode) {
+#line 1011
+ CError_FATAL();
+}
+
+static void propagatecopiesto(PCode *pcode) {
+ PCodeArg *op;
+ int i;
+
+ for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (op->data.reg.effect & (EffectRead | EffectWrite | Effect8)) == EffectRead &&
+ op->data.reg.reg >= n_real_registers[op->arg] &&
+ regvalue[op->arg][op->data.reg.reg].x4 &&
+ regvalue[op->arg][op->data.reg.reg].x4 >= n_real_registers[op->arg] &&
+ regvalue[op->arg][op->data.reg.reg].number == regvalue[op->arg][regvalue[op->arg][op->data.reg.reg].x4].number
+ ) {
+ op->data.reg.reg = regvalue[op->arg][op->data.reg.reg].x4;
+ }
+ }
+}
+
+static void removecsesfrombasicblock(PCodeBlock *block) {
+ PCode *pcode;
+ PCode *next;
+
+ for (pcode = block->firstPCode; pcode; pcode = next) {
+ next = pcode->nextPCode;
+ propagatecopiesto(pcode);
+ if (pcode->flags & fPCodeFlag10) {
+ registercopy(pcode);
+ } else if ((pcode->flags & fPCodeFlag8) && (pcode->flags & (fLink | fSideEffects))) {
+ functioncall(pcode);
+ } else if (pcode->flags & fPCodeFlag2) {
+ if (pcode->flags & fPCodeFlag20)
+ pointerload(pcode);
+ else
+ simpleload(pcode);
+ } else if (pcode->flags & fPCodeFlag4) {
+ if (pcode->flags & fPCodeFlag20)
+ pointerstore(pcode);
+ else
+ simplestore(pcode);
+ } else if (pcode->flags & fPCodeFlag20000) {
+ operatefrommemory(pcode);
+ } else if (pcode->flags & fPCodeFlag40000) {
+ operatetomemory(pcode);
+ } else if ((pcode->flags & fIsCSE) && isCSEop(pcode)) {
+ arithmeticop(pcode);
+ } else {
+ killregisters(pcode);
+ }
+ }
+
+ block->flags |= fPCBlockFlag4;
+}
+
+static void getvaluestate(State *state) {
+ state->stackedvalues = stackedvalues;
+ state->valueceiling = valueceiling;
+}
+
+static void setvaluestate(State *state) {
+ stackedvalues = state->stackedvalues;
+ valueceiling = state->valueceiling;
+}
+
+static void forkvaluestate(int number) {
+ stackedvalues = NULL;
+ valueceiling = number;
+}
+
+static void regressvaluestate(void) {
+ AvailableValue *av;
+ AvailableValue **ptr;
+ int i;
+ StackedValue *stacked;
+
+ for (i = 0; i < 428; i++) {
+ ptr = &opvalue[i];
+ while ((av = *ptr)) {
+ if (av->killedregister >= valueceiling)
+ *ptr = av->next;
+ else
+ ptr = &av->next;
+ }
+ }
+
+ for (stacked = stackedvalues; stacked; stacked = stacked->next)
+ unstackvalue(stacked);
+}
+
+static void removecsesfromextendedbasicblock(PCodeBlock *block) {
+ PCLink *succ;
+ int counter;
+ State state;
+
+ removecsesfrombasicblock(block);
+ while (block->successors &&
+ !block->successors->nextLink &&
+ block->successors->block->predecessors &&
+ !block->successors->block->predecessors->nextLink) {
+ block = block->successors->block;
+ removecsesfrombasicblock(block);
+ }
+
+ counter = 0;
+ for (succ = block->successors; succ; succ = succ->nextLink) {
+ if (!(succ->block->flags & fPCBlockFlag4) && succ->block->predecessors && !succ->block->predecessors->nextLink)
+ counter++;
+ }
+
+ if (counter) {
+ getvaluestate(&state);
+ forkvaluestate(nextvaluenumber);
+ for (succ = block->successors; succ; succ = succ->nextLink) {
+ if (!(succ->block->flags & fPCBlockFlag4) && succ->block->predecessors && !succ->block->predecessors->nextLink) {
+ removecsesfromextendedbasicblock(succ->block);
+ regressvaluestate();
+ }
+ }
+ setvaluestate(&state);
+ }
+}
+
+void removecommonsubexpressions(Object *proc, int flag) {
+ PCodeBlock *block;
+
+ moreaggressiveoptimization = flag;
+ removedcommonsubexpressions = 0;
+ gather_alias_info();
+ allocatecsedatastructures();
+
+ for (block = pcbasicblocks; block; block = block->nextBlock)
+ block->flags &= ~fPCBlockFlag4;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (!(block->flags & fPCBlockFlag4)) {
+ initializecsedatastructures();
+ removecsesfromextendedbasicblock(block);
+ }
+ }
+
+ freeoheap();
+}
+
diff --git a/compiler_and_linker/unsorted/VectorArraysToRegs.c b/compiler_and_linker/unsorted/VectorArraysToRegs.c
index e69de29..3f95cac 100644
--- a/compiler_and_linker/unsorted/VectorArraysToRegs.c
+++ b/compiler_and_linker/unsorted/VectorArraysToRegs.c
@@ -0,0 +1,549 @@
+#include "compiler/VectorArraysToRegs.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/Registers.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+typedef struct LocalVectorArray {
+ struct LocalVectorArray *next;
+ Object *object;
+ unsigned int invalid:1;
+ SInt32 arraySize;
+ SInt32 elementCount;
+ int totalUses;
+ int elements[1];
+} LocalVectorArray;
+
+typedef struct VectorPropInfo {
+ UInt32 *vec0;
+ UInt32 *vec4;
+ UInt32 *vec8;
+ UInt32 *vecC;
+} VectorPropInfo;
+
+typedef struct ADDI {
+ PCode *instr;
+ RegUseOrDef *list;
+} ADDI;
+
+static int number_of_ADDIs;
+static ADDI *ADDIs;
+static VectorPropInfo *vectorpropinfo;
+static int *naddsinblock;
+static int *firstaddinblock;
+static Boolean converted_arrays;
+
+static LocalVectorArray *scanforlocalvectorarrays(void) {
+ SInt32 elementCount;
+ LocalVectorArray *head;
+ LocalVectorArray *array;
+ ObjectList *list;
+ int i;
+ SInt32 arraySize;
+
+ head = NULL;
+
+ for (list = locals; list; list = list->next) {
+ if (
+ list->object &&
+ !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) &&
+ list->object->type &&
+ IS_TYPE_ARRAY(list->object->type) &&
+ IS_TYPE_VECTOR(TPTR_TARGET(list->object->type))
+ ) {
+ arraySize = list->object->type->size;
+ elementCount = arraySize / 16;
+ if (elementCount > 0 && elementCount <= 8) {
+ array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalVectorArray));
+ array->next = head;
+ head = array;
+
+ array->object = list->object;
+ array->arraySize = arraySize;
+ array->elementCount = elementCount;
+ array->totalUses = 0;
+ array->invalid = 0;
+
+ for (i = 0; i < elementCount; i++) {
+ array->elements[i] = 0;
+ }
+ }
+ }
+ }
+
+ return head;
+}
+
+static LocalVectorArray *lookup_vector_array_object(LocalVectorArray *arrays, Object *object) {
+ while (arrays) {
+ if (arrays->object == object)
+ return arrays;
+ arrays = arrays->next;
+ }
+ return NULL;
+}
+
+static void scaninstructions(LocalVectorArray *arrays) {
+ PCodeBlock *block;
+ PCode *instr;
+ int counter;
+ int i;
+ PCodeArg *op;
+ LocalVectorArray *array;
+ int element;
+
+ naddsinblock = oalloc(sizeof(int) * pcblockcount);
+ memclrw(naddsinblock, sizeof(int) * pcblockcount);
+
+ firstaddinblock = oalloc(sizeof(int) * pcblockcount);
+ memclrw(firstaddinblock, sizeof(int) * pcblockcount);
+
+ number_of_ADDIs = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ firstaddinblock[block->blockIndex] = number_of_ADDIs;
+ counter = 0;
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (!(instr->flags & fPCodeFlag1) && instr->argCount) {
+ op = instr->args;
+ i = instr->argCount;
+ while (i--) {
+ if (
+ op->kind == PCOp_MEMORY &&
+ op->arg == PCOpMemory1 &&
+ (array = lookup_vector_array_object(arrays, op->data.mem.obj)) &&
+ !array->invalid
+ )
+ {
+ if (instr->op != PC_ADDI) {
+ array->invalid = 1;
+ } else if (instr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) {
+ array->invalid = 1;
+ } else {
+ number_of_ADDIs++;
+ counter++;
+ }
+
+ if (!array->invalid) {
+ element = op->data.mem.offset / 16;
+ if (element < array->elementCount)
+ array->elements[element]++;
+ else
+ array->invalid = 1;
+ }
+ }
+ op++;
+ }
+ }
+ }
+ naddsinblock[block->blockIndex] = counter;
+ }
+}
+
+static void computeaddilist(LocalVectorArray *arrays) {
+ PCodeBlock *block;
+ PCode *instr;
+ RegUseOrDef *list;
+ ADDI *addi;
+ UInt32 *vec;
+ LocalVectorArray *array;
+ UseOrDef *def;
+ int defID;
+ UseOrDef *use;
+ int useID;
+
+ ADDIs = oalloc(sizeof(ADDI) * number_of_ADDIs);
+ memclrw(ADDIs, sizeof(ADDI) * number_of_ADDIs);
+
+ vec = oalloc(4 * ((number_of_Uses + 31) >> 5));
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (naddsinblock[block->blockIndex]) {
+ bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses);
+ addi = &ADDIs[firstaddinblock[block->blockIndex] + naddsinblock[block->blockIndex] - 1];
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ if (!(instr->flags & fPCodeFlag1) && instr->argCount) {
+ int reg; // r18
+ if (
+ instr->op == PC_ADDI &&
+ (reg = instr->args[0].data.reg.reg) >= n_real_registers[RegClass_GPR] &&
+ instr->args[2].kind == PCOp_MEMORY &&
+ (unsigned char) instr->args[2].arg == 1 &&
+ (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) &&
+ !array->invalid
+ )
+ {
+ addi->instr = instr;
+ addi->list = NULL;
+ for (list = reg_Uses[RegClass_GPR][reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, vec)) {
+ RegUseOrDef *node = oalloc(sizeof(RegUseOrDef));
+ node->id = list->id;
+ node->next = addi->list;
+ addi->list = node;
+ }
+ }
+ addi--;
+ }
+
+ for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) {
+ if (def->v.kind == PCOp_REGISTER) {
+ RegUseOrDef *l;
+ for (l = reg_Uses[(char) def->v.arg][def->v.u.reg]; l; l = l->next)
+ bitvectorclearbit(l->id, vec);
+ }
+ }
+
+ for (use = &Uses[useID = instr->useID]; useID < number_of_Uses && use->pcode == instr; use++, useID++) {
+ if (use->v.kind == PCOp_REGISTER)
+ bitvectorsetbit(useID, vec);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void allocatevectorpropinfo(void) {
+ VectorPropInfo *info;
+ int i;
+
+ vectorpropinfo = oalloc(sizeof(VectorPropInfo) * pcblockcount);
+ for (i = 0, info = vectorpropinfo; i < pcblockcount; i++, info++) {
+ info->vec0 = oalloc(4 * ((number_of_ADDIs + 31) >> 5));
+ info->vec4 = oalloc(4 * ((number_of_ADDIs + 31) >> 5));
+ info->vec8 = oalloc(4 * ((number_of_ADDIs + 31) >> 5));
+ info->vecC = oalloc(4 * ((number_of_ADDIs + 31) >> 5));
+ }
+}
+
+static void computelocalvectorpropinfo(LocalVectorArray *arrays) {
+ VectorPropInfo *info;
+ PCodeBlock *block;
+ PCode *instr;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ int index;
+ PCodeArg *op;
+ int i;
+ int addi_i;
+ ADDI *addi;
+ LocalVectorArray *array;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ info = &vectorpropinfo[block->blockIndex];
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+ bitvectorinitialize(vec0, number_of_ADDIs, 0);
+ bitvectorinitialize(vec4, number_of_ADDIs, 0);
+ index = firstaddinblock[block->blockIndex];
+
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (!(instr->flags & fPCodeFlag1) && instr->argCount) {
+ i = instr->argCount;
+ op = instr->args;
+ while (i--) {
+ if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) {
+ for (addi_i = 0, addi = ADDIs; addi_i < number_of_ADDIs; addi_i++, addi++) {
+ if (
+ addi->instr &&
+ (char) addi->instr->args[0].arg == (char) op->arg &&
+ addi->instr->args[0].data.reg.reg == op->data.reg.reg
+ )
+ {
+ if (addi->instr->block == block)
+ bitvectorclearbit(addi_i, vec0);
+ else
+ bitvectorsetbit(addi_i, vec4);
+ }
+ }
+ }
+ op++;
+ }
+
+ if (
+ instr->op == PC_ADDI &&
+ instr->args[2].kind == PCOp_MEMORY &&
+ instr->args[2].arg == PCOpMemory1 &&
+ (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) &&
+ !array->invalid
+ )
+ {
+ bitvectorsetbit(index, vec0);
+ index++;
+ }
+ }
+ }
+ }
+}
+
+static void computeglobalvectorpropinfo(void) {
+ VectorPropInfo *info;
+ PCodeBlock *block;
+ UInt32 *vec0;
+ UInt32 *vec4;
+ UInt32 *vec8;
+ UInt32 *vecC;
+ int bitvecsize;
+ int blockIndex;
+ int i;
+ int j;
+ int flag;
+ PCLink *preds;
+ UInt32 val;
+
+ bitvecsize = (number_of_ADDIs + 31) >> 5;
+ flag = 1;
+ info = &vectorpropinfo[pcbasicblocks->blockIndex];
+ bitvectorinitialize(info->vec8, number_of_ADDIs, 0);
+ bitvectorcopy(info->vecC, info->vec0, number_of_ADDIs);
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
+ info = &vectorpropinfo[block->blockIndex];
+ vecC = info->vecC;
+ vec4 = info->vec4;
+ for (i = 0; i < bitvecsize; vecC++, vec4++, i++)
+ *vecC = ~*vec4;
+ }
+
+ while (flag) {
+ flag = 0;
+ for (blockIndex = 0; blockIndex < pcblockcount; blockIndex++) {
+ if (depthfirstordering[blockIndex]) {
+ info = &vectorpropinfo[depthfirstordering[blockIndex]->blockIndex];
+ if ((preds = depthfirstordering[blockIndex]->predecessors)) {
+ vec8 = info->vec8;
+ bitvectorcopy(vec8, vectorpropinfo[preds->block->blockIndex].vecC, number_of_ADDIs);
+ for (preds = preds->nextLink; preds; preds = preds->nextLink)
+ bitvectorintersect(vec8, vectorpropinfo[preds->block->blockIndex].vecC, number_of_ADDIs);
+ }
+
+ vecC = info->vecC;
+ vec8 = info->vec8;
+ vec0 = info->vec0;
+ vec4 = info->vec4;
+ for (j = 0; j < bitvecsize; j++) {
+ val = *vec0 | (*vec8 & ~*vec4);
+ if (val != *vecC) {
+ *vecC = val;
+ flag = 1;
+ }
+ vec8++;
+ vecC++;
+ vec4++;
+ vec0++;
+ }
+ }
+ }
+ }
+}
+
+static int precedes(PCode *a, PCode *b) {
+ PCode *scan;
+
+ for (scan = a->nextPCode; scan; scan = scan->nextPCode) {
+ if (scan == b)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int checkvectorstoreorload(int addiID, int useID) {
+ PCode *addiInstr;
+ UseOrDef *use;
+
+ addiInstr = ADDIs[addiID].instr;
+ use = Uses + useID;
+ if (!addiInstr)
+ return 0;
+
+ if (addiInstr->args[0].data.reg.reg < n_real_registers[RegClass_GPR])
+ return 0;
+
+ if (use->pcode->op != PC_LVX && use->pcode->op != PC_STVX)
+ return 0;
+
+ if (
+ use->pcode->args[1].kind != PCOp_REGISTER ||
+ use->pcode->args[1].arg != RegClass_GPR ||
+ use->pcode->args[1].data.reg.reg != 0
+ )
+ return 0;
+
+ return use->pcode->args[2].data.reg.reg == addiInstr->args[0].data.reg.reg;
+}
+
+static int checkalluses(LocalVectorArray *arrays, int addiID) {
+ RegUseOrDef *list;
+ PCode *instr;
+ LocalVectorArray *array;
+
+ instr = ADDIs[addiID].instr;
+ for (list = ADDIs[addiID].list; list; list = list->next) {
+ if (list && !checkvectorstoreorload(addiID, list->id)) {
+ array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj);
+ array->invalid = 1;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void convert_array_to_register(LocalVectorArray *arrays, int addiID) {
+ ADDI *addi;
+ int newReg;
+ RegUseOrDef *list;
+ PCode *instr;
+ PCode *useInstr;
+ LocalVectorArray *array;
+ int element;
+
+ addi = ADDIs + addiID;
+
+ if (!(instr = addi->instr))
+ return;
+
+ if (
+ !(array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) ||
+ array->invalid
+ )
+ return;
+
+ element = instr->args[2].data.mem.offset / 16;
+ if (element > array->elementCount)
+ return;
+
+ newReg = array->elements[element];
+ for (list = addi->list; list; list = list->next) {
+ useInstr = Uses[list->id].pcode;
+ if (useInstr->op == PC_LVX) {
+ converted_arrays = 1;
+ change_opcode(useInstr, PC_VMR);
+ change_num_operands(useInstr, 2);
+ useInstr->args[1].kind = PCOp_REGISTER;
+ useInstr->args[1].arg = RegClass_VR;
+ useInstr->args[1].data.reg.reg = newReg;
+ useInstr->args[1].data.reg.effect = EffectRead;
+ } else if (useInstr->op == PC_STVX) {
+ converted_arrays = 1;
+ change_opcode(useInstr, PC_VMR);
+ change_num_operands(useInstr, 2);
+ useInstr->args[1] = useInstr->args[0];
+ useInstr->args[0].kind = PCOp_REGISTER;
+ useInstr->args[0].arg = RegClass_VR;
+ useInstr->args[0].data.reg.reg = newReg;
+ useInstr->args[0].data.reg.effect = EffectWrite;
+ } else {
+#line 661
+ CError_FATAL();
+ }
+ }
+ deletepcode(addi->instr);
+}
+
+static void convert_arrays_to_registers(LocalVectorArray *arrays) {
+ int i;
+ int counter;
+ LocalVectorArray **ptr;
+ LocalVectorArray *array;
+
+ for (i = 0; i < number_of_ADDIs; i++)
+ checkalluses(arrays, i);
+
+ counter = 0;
+ ptr = &arrays;
+ array = *ptr;
+ while (array) {
+ if (array->invalid) {
+ *ptr = array->next;
+ array = *ptr;
+ continue;
+ }
+
+ counter += array->elementCount;
+
+ for (i = 0; i < array->elementCount; i++)
+ array->totalUses += array->elements[i];
+
+ array = array->next;
+ }
+
+ if (arrays) {
+ while (counter > 32) {
+ LocalVectorArray *best;
+ int score;
+ score = 0;
+ best = NULL;
+ for (array = arrays; array; array = array->next) {
+ if (best) {
+ if (array->totalUses < score) {
+ score = array->totalUses;
+ best = array;
+ }
+ } else {
+ best = array;
+ score = array->totalUses;
+ }
+ }
+
+ if (!best)
+ break;
+
+ if (best == arrays) {
+ arrays = best->next;
+ } else {
+ for (array = arrays; array; array = array->next) {
+ if (array->next == best) {
+ array->next = best->next;
+ break;
+ }
+ }
+ }
+
+ counter -= best->elementCount;
+ }
+
+ if (!(array = arrays))
+ return;
+
+ while (array) {
+ for (i = 0; i < array->elementCount; i++)
+ array->elements[i] = used_virtual_registers[RegClass_VR]++;
+ array = array->next;
+ }
+
+ if (arrays) {
+ for (i = 0; i < number_of_ADDIs; i++)
+ convert_array_to_register(arrays, i);
+ }
+ }
+}
+
+int vectorarraystoregs(void) {
+ LocalVectorArray *arrays;
+
+ converted_arrays = 0;
+ if ((arrays = scanforlocalvectorarrays())) {
+ scaninstructions(arrays);
+ if (number_of_ADDIs > 0) {
+ computeusedefchains(0);
+ computeaddilist(arrays);
+ allocatevectorpropinfo();
+ computelocalvectorpropinfo(arrays);
+ computedepthfirstordering();
+ computeglobalvectorpropinfo();
+ convert_arrays_to_registers(arrays);
+ }
+ }
+
+ freeoheap();
+ return converted_arrays;
+}