summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c5734
1 files changed, 5734 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c
new file mode 100644
index 0000000..3f8989f
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c
@@ -0,0 +1,5734 @@
+#include "IroPointerAnalysis.h"
+#include "IroEval.h"
+#include "IroFlowgraph.h"
+#include "IroLinearForm.h"
+#include "IroMalloc.h"
+#include "IroUtil.h"
+#include "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 "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;
+
+ IRO_ASSERT(932, loc != NULL);
+ IRO_ASSERT(933, 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;
+
+ IRO_ASSERT(999, local != NULL);
+ IRO_ASSERT(1000, 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) {
+ IRO_ASSERT(1042, obj != NULL);
+
+ return Inline_IsObjectData(obj) ||
+ obj->datatype == DABSOLUTE ||
+ obj->datatype == DFUNC ||
+ obj->datatype == DVFUNC ||
+ obj->datatype == DINLINEFUNC;
+}
+
+static Boolean ObjectIsAFunction(Object *obj) {
+ IRO_ASSERT(1054, 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;
+
+ IRO_ASSERT(1073, ls != NULL);
+ IRO_ASSERT(1074, proc == NULL || proc != NULL);
+ IRO_ASSERT(1075, pointsToFunc == NULL || pointsToFunc != NULL);
+
+ result = 1;
+ if (LocationSet_IsUnknown(ls) || LocationSet_stride(ls)) {
+ result = 0;
+ } else {
+ mb = LocationSet_block(ls);
+ IRO_ASSERT(1084, 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;
+
+ IRO_ASSERT(1151, ls != NULL);
+ IRO_ASSERT(1152, !LocationSet_IsUnknown(ls));
+ IRO_ASSERT(1153, 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;
+
+ IRO_ASSERT(1188, ls != NULL);
+ IRO_ASSERT(1189, !LocationSet_IsUnknown(ls));
+ IRO_ASSERT(1190, 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;
+
+ IRO_ASSERT(1219, ls != NULL);
+ IRO_ASSERT(1220, 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;
+
+ IRO_ASSERT(1235, ls != NULL);
+ IRO_ASSERT(1236, 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;
+
+ IRO_ASSERT(1284, set == NULL || set != NULL);
+ IRO_ASSERT(1285, proc != NULL);
+ IRO_ASSERT(1286, Int != NULL);
+ IRO_ASSERT(1287, map == NULL || map != NULL);
+ IRO_ASSERT(1288, 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;
+
+ IRO_ASSERT(1302, Int != NULL);
+
+ if (IRO_IsAssignment(Int)) {
+ if (Int->type == IROLinearOp1Arg)
+ indirect = Int->u.monadic;
+ else
+ indirect = Int->u.diadic.left;
+ IRO_ASSERT(1310, 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) {
+ IRO_ASSERT(1338, 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;
+ IRO_ASSERT(1383, addr->objRefs->element->type == IROLinearOperand);
+ IRO_ASSERT(1384, addr->objRefs->element->u.node->type == EOBJREF);
+ obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref;
+ IRO_ASSERT(1387, 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) {
+ IRO_ASSERT(1536, 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;
+ IRO_ASSERT(1597, 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
+ CError_FATAL(1643);
+
+ 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(0, set == NULL || set != NULL);
+ IRO_ASSERT(0, proc != NULL);
+ IRO_ASSERT(0, Int != NULL);
+ IRO_ASSERT(0, map == NULL || map != NULL);
+ IRO_ASSERT(0, 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(0, 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(0, 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(0, 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(0, 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(0, 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
+ CError_FATAL(2146);
+
+ 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) {
+ IRO_ASSERT(2275, loc != NULL);
+ IRO_ASSERT(2276, 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;
+
+ IRO_ASSERT(2307, nd != NULL);
+ IRO_ASSERT(2308, nd->type == IROLinearFunccall);
+ IRO_ASSERT(2309, ptf != NULL);
+ IRO_ASSERT(2310, 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;
+
+ IRO_ASSERT(2352, obj != NULL);
+ IRO_ASSERT(2353, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(2357, params->map != NULL);
+ IRO_ASSERT(2358, params->ep != NULL);
+ IRO_ASSERT(2359, params->proc == NULL || params->proc != NULL);
+ IRO_ASSERT(2360, params->proc != &stUnknown);
+ IRO_ASSERT(2361, params->var == NULL || params->var != NULL);
+ IRO_ASSERT(2362, 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;
+
+ IRO_ASSERT(2398, map != NULL);
+ IRO_ASSERT(2399, var == NULL || var != NULL);
+ IRO_ASSERT(2400, var != &stUnknown);
+ IRO_ASSERT(2401, ep != NULL);
+ IRO_ASSERT(2402, proc == NULL || proc != NULL);
+ IRO_ASSERT(2403, 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;
+
+ IRO_ASSERT(2448, loc != NULL);
+ IRO_ASSERT(2449, !LocationSet_IsUnknown(loc));
+ IRO_ASSERT(2450, locs != NULL);
+ IRO_ASSERT(2451, proc != NULL);
+ IRO_ASSERT(2452, map != NULL);
+ IRO_ASSERT(2453, ptf != NULL);
+
+ initial = PartialTransferFunction_initialPointsToFn(ptf);
+ IRO_ASSERT(2456, initial != NULL);
+
+ IRO_ASSERT(2458, !LocationSet_IsUnknown(loc));
+
+ block = LocationSet_block(loc);
+ IRO_ASSERT(2460, block != NULL);
+
+ kind = PAMemoryBlock_kind(block);
+
+ if (kind == PAMEMORYBLOCKKIND_LOCALVAR) {
+ PALocalVar *local;
+
+ local = PAMemoryBlock_thing(block);
+ IRO_ASSERT(2466, 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);
+ IRO_ASSERT(2489, ep != NULL);
+
+ obj = NULL;
+ ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj);
+ if (obj && obj != &stUnknown)
+ FillInAppropriateMappingsWithExtParam(map, obj, ep, proc);
+ } else {
+ CError_FATAL(2500);
+ }
+
+ 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;
+
+ IRO_ASSERT(2525, tgtPTE != NULL);
+ IRO_ASSERT(2526, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(2530, params->proc != NULL);
+ IRO_ASSERT(2531, params->ptfCopy != NULL);
+ IRO_ASSERT(2532, 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) {
+ CError_FATAL(2547);
+ }
+ }
+ }
+}
+
+static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) {
+ MatchPTFActionParams *params;
+ LocationSet *loc;
+ LocationSetSet *locs;
+ PAMemoryBlock *block;
+ PAMemoryBlockKind kind;
+
+ IRO_ASSERT(2561, tgtPTE != NULL);
+ IRO_ASSERT(2562, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(2566, params->proc != NULL);
+ IRO_ASSERT(2567, params->ptfCopy != NULL);
+ IRO_ASSERT(2568, 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;
+
+ IRO_ASSERT(2593, tgtPTF != NULL);
+ IRO_ASSERT(2594, proc != NULL);
+ IRO_ASSERT(2595, map != NULL);
+ IRO_ASSERT(2596, nd != NULL);
+ IRO_ASSERT(2597, 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;
+
+ IRO_ASSERT(2650, obj != NULL);
+ IRO_ASSERT(2651, refcon != NULL);
+
+ procList = refcon;
+
+ if (obj == &stUnknown || ObjectIsAFunction(obj))
+ ObjectSet_sub_4867D0(procList, obj);
+}
+
+static void FindCallTargetsAction(LocationSet *ls, void *refcon) {
+ ObjectSet *procList;
+
+ IRO_ASSERT(2669, ls != NULL);
+ IRO_ASSERT(2670, 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;
+
+ IRO_ASSERT(2696, procList != NULL);
+ IRO_ASSERT(2697, proc != NULL);
+ IRO_ASSERT(2698, nd != NULL);
+ IRO_ASSERT(2699, nd->type == IROLinearFunccall);
+ IRO_ASSERT(2700, map != NULL);
+ IRO_ASSERT(2701, 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;
+
+ IRO_ASSERT(2728, set == NULL || set != NULL);
+ IRO_ASSERT(2729, ls != NULL);
+ IRO_ASSERT(2730, var != NULL);
+ IRO_ASSERT(2731, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(2732, proc != NULL);
+ IRO_ASSERT(2733, map == NULL || map != NULL);
+ IRO_ASSERT(2734, ptf == NULL || ptf != NULL);
+
+ result = 0;
+
+ ep = ExtendedParam_FindByObject(var);
+ if (!ep)
+ ep = CreateExtendedParam(stackPtr, map, var, &result);
+
+ IRO_ASSERT(2741, 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;
+
+ IRO_ASSERT(2821, set == NULL || set != NULL);
+ IRO_ASSERT(2822, (ls != NULL && var == NULL) || (ls == NULL && var != NULL));
+ IRO_ASSERT(2823, ls == NULL || !LocationSet_IsUnknown(ls));
+ IRO_ASSERT(2824, var != &stUnknown);
+ IRO_ASSERT(2825, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(2826, map == NULL || map != NULL);
+
+ result = 0;
+ block = NULL;
+ nd = 0;
+ ep = NULL;
+ mapping = NULL;
+
+ if (ls) {
+ block = LocationSet_block(ls);
+ IRO_ASSERT(2838, block != NULL);
+ IRO_ASSERT(2839, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ ep = PAMemoryBlock_thing(block);
+ IRO_ASSERT(2842, ep != NULL);
+
+ savedField = LocationSet_field(ls);
+ savedStride = LocationSet_stride(ls);
+ savedRtype = LocationSet_rtype(ls);
+ }
+
+ IRO_ASSERT(2848, ep == NULL || ep != NULL);
+
+ if (stackPtr && *stackPtr) {
+ StackElement *element = Stack_Top(stackPtr);
+ if (element && !map)
+ map = StackElement_map(element);
+ }
+
+ IRO_ASSERT(2859, map == NULL || map != NULL);
+
+ if (ep) {
+ IRO_ASSERT(2863, var == NULL);
+ ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var);
+ if (!var)
+ var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep));
+ if (!var)
+ var = &stUnknown;
+ }
+
+ IRO_ASSERT(2870, 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);
+
+ IRO_ASSERT(2884, mapping == NULL || mapping != NULL);
+
+ if (mapping)
+ nd = ParamMapping_actual(mapping);
+
+ if (!nd) {
+ if (!ls) {
+ IRO_ASSERT(2893, var != NULL);
+ IRO_ASSERT(2894, 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;
+ }
+
+ IRO_ASSERT(2925, 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;
+
+ IRO_ASSERT(3021, ls != NULL);
+ IRO_ASSERT(3022, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(3026, params->toBeRemoved != NULL);
+ IRO_ASSERT(3027, params->toBeAdded != NULL);
+ IRO_ASSERT(3028, params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL);
+ IRO_ASSERT(3029, 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;
+
+ IRO_ASSERT(3063, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(3064, map == NULL || map != NULL);
+ IRO_ASSERT(3065, 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;
+
+ IRO_ASSERT(3108, set != NULL);
+ IRO_ASSERT(3109, thingsPointedTo != NULL);
+ IRO_ASSERT(3110, dst != NULL);
+ IRO_ASSERT(3111, indRtype != NULL);
+
+ absLoc = LocationSetSet_FindFirst(thingsPointedTo);
+ IRO_ASSERT(3114, 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;
+
+ IRO_ASSERT(3192, ptf == NULL || ptf != NULL);
+ IRO_ASSERT(3193, dst != NULL);
+ IRO_ASSERT(3194, 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)) {
+ IRO_ASSERT(3208, 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;
+
+ IRO_ASSERT(3245, set == NULL || set != NULL);
+ IRO_ASSERT(3246, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(3247, proc == NULL || proc != NULL);
+ IRO_ASSERT(3248, map == NULL || map != NULL);
+ IRO_ASSERT(3249, ptf == NULL || ptf != NULL);
+ IRO_ASSERT(3250, dst != NULL);
+ IRO_ASSERT(3251, pointsToFunc == NULL || pointsToFunc != NULL);
+ IRO_ASSERT(3252, 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) {
+ IRO_ASSERT(3393, tgtPTF != NULL);
+ IRO_ASSERT(3394, 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;
+
+ IRO_ASSERT(3417, mapping != NULL);
+ IRO_ASSERT(3418, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(3422, params->last == NULL || params->last != NULL);
+ IRO_ASSERT(3423, 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;
+
+ IRO_ASSERT(3473, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(3474, map == NULL || map != NULL);
+ IRO_ASSERT(3475, lss != NULL);
+ IRO_ASSERT(3476, 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;
+
+ IRO_ASSERT(3518, map == NULL || map != NULL);
+ IRO_ASSERT(3519, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
+ IRO_ASSERT(3520, var != NULL);
+
+ mapping = NULL;
+ if (map)
+ mapping = ParamMappingFunction_FindMappingByFormal(map, var);
+
+ ep = ExtendedParam_FindByObject(var);
+ if (ep) {
+ if (mapping)
+ IRO_ASSERT(3535, 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);
+
+ IRO_ASSERT(3583, ep != NULL);
+
+ return ep;
+}
+
+#ifdef IRO_DEBUG
+void __assertion_failed(char *expr, char *filename, int line) {
+ CError_ASSERT(3605, filename);
+ CError_Internal(filename, line);
+}
+#endif
+
+static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) {
+ IRO_ASSERT(3628, nd != NULL);
+ IRO_ASSERT(3629, nd->type == IROLinearFunccall);
+ IRO_ASSERT(3630, proc != NULL);
+ IRO_ASSERT(3631, 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++) {
+ IRO_ASSERT(3643, 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) {
+ IRO_ASSERT(3676, loc != NULL);
+ IRO_ASSERT(3677, fnode != NULL);
+ IRO_ASSERT(3678, 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) {
+ IRO_ASSERT(3719, ls1 != NULL);
+ IRO_ASSERT(3720, 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;
+
+ IRO_ASSERT(3751, ls != NULL);
+ IRO_ASSERT(3752, 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;
+
+ IRO_ASSERT(3779, pte != NULL);
+ IRO_ASSERT(3780, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(3784, params->proc != NULL);
+ IRO_ASSERT(3785, params->fnode != NULL);
+ IRO_ASSERT(3786, params->nd != NULL);
+ IRO_ASSERT(3787, params->ptf != NULL);
+ IRO_ASSERT(3788, params->toBeKilled != NULL);
+ IRO_ASSERT(3789, params->dst == NULL);
+
+ loc = PointsToEntry_loc(pte);
+ IRO_ASSERT(3793, loc != NULL);
+ IRO_ASSERT(3794, !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;
+
+ IRO_ASSERT(3813, pte != NULL);
+ IRO_ASSERT(3814, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(3818, params->proc != NULL);
+ IRO_ASSERT(3819, params->fnode != NULL);
+ IRO_ASSERT(3820, params->nd != NULL);
+ IRO_ASSERT(3821, params->ptf != NULL);
+ IRO_ASSERT(3822, params->toBeKilled != NULL);
+ IRO_ASSERT(3823, params->dst != NULL);
+ IRO_ASSERT(3824, LocationSet_block(params->dst) != NULL);
+ IRO_ASSERT(3825, PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ loc = PointsToEntry_loc(pte);
+ IRO_ASSERT(3829, loc != NULL);
+ IRO_ASSERT(3830, !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;
+
+ IRO_ASSERT(3886, pte != NULL);
+ IRO_ASSERT(3887, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(3891, params->proc != NULL);
+ IRO_ASSERT(3892, params->fnode != NULL);
+ IRO_ASSERT(3893, params->nd != NULL);
+ IRO_ASSERT(3894, params->ptf != NULL);
+ IRO_ASSERT(3895, params->toBeKilled != NULL);
+ IRO_ASSERT(3896, params->dst == NULL);
+
+ loc = PointsToEntry_loc(pte);
+ IRO_ASSERT(3900, loc != NULL);
+ IRO_ASSERT(3901, !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;
+
+ IRO_ASSERT(3921, proc != NULL);
+ IRO_ASSERT(3922, fnode == NULL || fnode != NULL);
+ IRO_ASSERT(3923, nd == NULL || nd != NULL);
+ IRO_ASSERT(3924, 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;
+
+ IRO_ASSERT(3974, proc != NULL);
+ IRO_ASSERT(3975, fnode == NULL || fnode != NULL);
+ IRO_ASSERT(3976, nd == NULL || nd != NULL);
+ IRO_ASSERT(3977, ptf != NULL);
+ IRO_ASSERT(3978, 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;
+
+ IRO_ASSERT(4027, ptf != NULL);
+ IRO_ASSERT(4028, dst != NULL);
+ IRO_ASSERT(4029, srcs != NULL);
+ IRO_ASSERT(4030, proc != NULL);
+ IRO_ASSERT(4031, nd == NULL || nd != NULL);
+ IRO_ASSERT(4032, 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);
+ IRO_ASSERT(4056, !LocationSet_IsUnknown(dst));
+ IRO_ASSERT(4057, 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;
+
+ IRO_ASSERT(4123, pte != NULL);
+ IRO_ASSERT(4124, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(4128, params->proc != NULL);
+ IRO_ASSERT(4129, params->fnode != NULL);
+ IRO_ASSERT(4130, params->pred != NULL);
+ IRO_ASSERT(4131, params->nd != NULL);
+ IRO_ASSERT(4132, 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;
+
+ IRO_ASSERT(4163, proc != NULL);
+ IRO_ASSERT(4164, fnode != NULL);
+ IRO_ASSERT(4165, nd != NULL);
+ IRO_ASSERT(4166, 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;
+
+ IRO_ASSERT(4210, proc != NULL);
+ IRO_ASSERT(4211, proc->u.func.ptfList != NULL);
+ IRO_ASSERT(4212, nd == NULL || nd != NULL);
+ IRO_ASSERT(4213, 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) {
+ IRO_ASSERT(4229, 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;
+
+ IRO_ASSERT(4252, 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) {
+ IRO_ASSERT(4383, proc != NULL);
+
+ IRO_ASSERT(4391, proc == stCurrentProc);
+
+ return IRO_NodeTable;
+}
+
+static IRONode *FunctionFirstNode(Object *proc) {
+ IRO_ASSERT(4401, proc != NULL);
+
+ IRO_ASSERT(4409, 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;
+
+ IRO_ASSERT(4458, proc != NULL);
+ IRO_ASSERT(4459, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(4463, params->proc != NULL);
+ IRO_ASSERT(4464, params->fnode != NULL);
+ IRO_ASSERT(4465, params->nd != NULL);
+ IRO_ASSERT(4466, params->ptf != NULL);
+ IRO_ASSERT(4467, 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);
+
+ IRO_ASSERT(4490, 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;
+
+ IRO_ASSERT(4548, proc != NULL);
+ IRO_ASSERT(4549, fnode != NULL);
+ IRO_ASSERT(4550, nd != NULL);
+ IRO_ASSERT(4551, map != NULL);
+ IRO_ASSERT(4552, 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:
+ CError_FATAL(4604);
+ }
+
+ 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;
+
+ IRO_ASSERT(4657, ls != NULL);
+ IRO_ASSERT(4658, refcon != NULL);
+
+ params = refcon;
+
+ if (!params->xC && !LocationSet_IsUnknown(ls)) {
+ value = params->x0;
+ nd = params->nd;
+ IRO_ASSERT(4665, 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:
+ CError_FATAL(4746);
+ }
+
+ 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;
+
+ IRO_ASSERT(4797, dst != NULL);
+ IRO_ASSERT(4798, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(4802, params->proc != NULL);
+ IRO_ASSERT(4802, params->ptf != NULL);
+ IRO_ASSERT(4803, params->nd != NULL);
+ IRO_ASSERT(4804, params->fnode != NULL);
+ IRO_ASSERT(4805, 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;
+
+ IRO_ASSERT(4840, proc != NULL);
+ IRO_ASSERT(4841, nd != NULL);
+ IRO_ASSERT(4842, fnode != NULL);
+ IRO_ASSERT(4843, map != NULL);
+ IRO_ASSERT(4844, 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) {
+ IRO_ASSERT(4861, 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) {
+ IRO_ASSERT(4958, 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 {
+ CError_FATAL(5006);
+ }
+
+ 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;
+
+ IRO_ASSERT(5046, proc != NULL);
+ IRO_ASSERT(5047, nd != NULL);
+ IRO_ASSERT(5048, nd->type == IROLinearReturn);
+ IRO_ASSERT(5049, fnode != NULL);
+ IRO_ASSERT(5050, map != NULL);
+ IRO_ASSERT(5051, 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;
+
+ IRO_ASSERT(5108, mapping != NULL);
+ IRO_ASSERT(5109, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5113, params->tgtMap != NULL);
+ IRO_ASSERT(5114, params->proc != NULL);
+ IRO_ASSERT(5115, params->fnode != NULL);
+ IRO_ASSERT(5116, params->nd != NULL);
+ IRO_ASSERT(5117, params->nd->type == IROLinearFunccall);
+ IRO_ASSERT(5118, params->ptf != NULL);
+ IRO_ASSERT(5119, params->map != NULL);
+ IRO_ASSERT(5120, params->loc != NULL);
+ IRO_ASSERT(5121, params->locs != NULL);
+
+ block = LocationSet_block(params->loc);
+
+ IRO_ASSERT(5124, block != NULL);
+ IRO_ASSERT(5125, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
+
+ ep = PAMemoryBlock_thing(block);
+
+ IRO_ASSERT(5127, 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;
+
+ IRO_ASSERT(5175, pte != NULL);
+ IRO_ASSERT(5176, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5180, params->tgtMap != NULL);
+ IRO_ASSERT(5181, params->proc != NULL);
+ IRO_ASSERT(5182, params->fnode != NULL);
+ IRO_ASSERT(5183, params->nd != NULL);
+ IRO_ASSERT(5184, params->nd->type == IROLinearFunccall);
+ IRO_ASSERT(5185, params->ptf != NULL);
+ IRO_ASSERT(5186, params->map != NULL);
+
+ loc = PointsToEntry_loc(pte);
+
+ IRO_ASSERT(5189, loc != NULL);
+ IRO_ASSERT(5190, !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;
+
+ IRO_ASSERT(5208, tgtPTF != NULL);
+ IRO_ASSERT(5209, tgtMap != NULL);
+ IRO_ASSERT(5210, proc != NULL);
+ IRO_ASSERT(5211, fnode != NULL);
+ IRO_ASSERT(5212, nd != NULL);
+ IRO_ASSERT(5213, nd->type == IROLinearFunccall);
+ IRO_ASSERT(5214, ptf != NULL);
+ IRO_ASSERT(5215, 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) {
+ IRO_ASSERT(5331, 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;
+
+ IRO_ASSERT(5359, tgtPTF != NULL);
+ IRO_ASSERT(5360, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5364, params->map != NULL);
+ IRO_ASSERT(5365, params->proc != NULL);
+ IRO_ASSERT(5366, params->proc != &stUnknown);
+ IRO_ASSERT(5367, params->nd != NULL);
+ IRO_ASSERT(5368, params->ptf != NULL);
+ IRO_ASSERT(5369, 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;
+
+ IRO_ASSERT(5396, map != NULL);
+ IRO_ASSERT(5397, proc != NULL);
+ IRO_ASSERT(5398, nd != NULL);
+ IRO_ASSERT(5399, ptf != NULL);
+ IRO_ASSERT(5400, 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) {
+ IRO_ASSERT(5467, proc != NULL);
+ IRO_ASSERT(5468, fnode != NULL);
+
+ return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom);
+}
+
+static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) {
+ UInt16 i;
+
+ IRO_ASSERT(5479, proc != NULL);
+ IRO_ASSERT(5480, 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(0, proc != NULL);
+ IRO_ASSERT(0, 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;
+
+ IRO_ASSERT(5525, pte != NULL);
+ IRO_ASSERT(5526, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5530, params->proc != NULL);
+ IRO_ASSERT(5531, params->fnode != NULL);
+ IRO_ASSERT(5532, params->ptf != NULL);
+
+ dst = PointsToEntry_loc(pte);
+
+ IRO_ASSERT(5535, dst != NULL);
+ IRO_ASSERT(5536, !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;
+
+ IRO_ASSERT(5577, pte != NULL);
+ IRO_ASSERT(5578, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5582, params->proc != NULL);
+ IRO_ASSERT(5583, params->nd != NULL);
+ IRO_ASSERT(5584, params->fnode != NULL);
+ IRO_ASSERT(5585, 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;
+
+ IRO_ASSERT(5602, pointsTo != NULL);
+ IRO_ASSERT(5603, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(5607, 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;
+
+ IRO_ASSERT(5643, proc != NULL);
+ IRO_ASSERT(5644, proc != &stUnknown);
+ IRO_ASSERT(5645, 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;
+
+ IRO_ASSERT(5661, proc != NULL);
+ IRO_ASSERT(5662, proc != &stUnknown);
+ IRO_ASSERT(5663, 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) {
+ IRO_ASSERT(5699, var != NULL);
+ IRO_ASSERT(5700, stExceptionFNode != NULL);
+ IRO_ASSERT(5701, 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) {
+ IRO_ASSERT(5748, Int != NULL);
+ IRO_ASSERT(5749, 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;
+
+ IRO_ASSERT(5760, proc != NULL);
+ IRO_ASSERT(5761, fnode != NULL);
+ IRO_ASSERT(5762, map != NULL);
+ IRO_ASSERT(5763, 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;
+
+ IRO_ASSERT(5964, proc != NULL);
+ IRO_ASSERT(5965, map != NULL);
+ IRO_ASSERT(5966, 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)
+ CError_FATAL(6072);
+ } 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;
+
+ IRO_ASSERT(6161, loc != NULL);
+ IRO_ASSERT(6162, 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) {
+ IRO_ASSERT(6177, pte != NULL);
+ IRO_ASSERT(6178, refcon == NULL);
+
+ CleanseLocationSet(PointsToEntry_loc(pte), NULL);
+ LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL);
+}
+
+static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) {
+ IRO_ASSERT(6187, ptf != NULL);
+ IRO_ASSERT(6188, 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;
+
+ IRO_ASSERT(6302, 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;
+
+ IRO_ASSERT(6393, 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;
+
+ IRO_ASSERT(6763, loc != NULL);
+ IRO_ASSERT(6764, resultObj != NULL);
+ IRO_ASSERT(6765, 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))) {
+ IRO_ASSERT(6777, 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))
+ )
+ {
+ IRO_ASSERT(6801, 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;
+
+ IRO_ASSERT(6833, loc != NULL);
+ IRO_ASSERT(6834, !LocationSet_IsUnknown(loc));
+ IRO_ASSERT(6835, LocationSet_stride(loc) == 0);
+ IRO_ASSERT(6836, list != NULL);
+ IRO_ASSERT(6837, rtype != NULL);
+ IRO_ASSERT(6838, 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:
+ CError_FATAL(6894);
+ }
+
+ 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;
+
+ IRO_ASSERT(6926, loc != NULL);
+ IRO_ASSERT(6927, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(6931, params->proc != NULL);
+ IRO_ASSERT(6932, params->indirectType != NULL);
+ IRO_ASSERT(6933, 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;
+
+ IRO_ASSERT(6957, 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(0, loc != NULL);
+ IRO_ASSERT(0, !LocationSet_IsUnknown(loc));
+ IRO_ASSERT(0, LocationSet_stride(loc) == 0);
+ IRO_ASSERT(0, resultNode != NULL);
+ IRO_ASSERT(0, rtype != NULL);
+ IRO_ASSERT(0, 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:
+ CError_FATAL(7040);
+ }
+
+ 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(0, loc != NULL);
+ IRO_ASSERT(0, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(0, params->proc != NULL);
+ IRO_ASSERT(0, params->indirectType != NULL);
+ IRO_ASSERT(0, 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(0, 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, IROListNode **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;
+
+ IRO_ASSERT(7204, ls != NULL);
+ IRO_ASSERT(7205, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(7209, params->proc != NULL);
+ IRO_ASSERT(7210, params->ptf != NULL);
+ IRO_ASSERT(7211, params->funccall != NULL);
+ IRO_ASSERT(7212, params->map == NULL || params->map != NULL);
+ IRO_ASSERT(7213, 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))) {
+ IRO_ASSERT(7232, 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;
+
+ IRO_ASSERT(7264, pte != NULL);
+ IRO_ASSERT(7265, refcon != NULL);
+
+ params = refcon;
+
+ IRO_ASSERT(7269, params->proc != NULL);
+ IRO_ASSERT(7270, params->ptf != NULL);
+ IRO_ASSERT(7271, params->funccall != NULL);
+ IRO_ASSERT(7272, params->map != NULL);
+ IRO_ASSERT(7273, params->list != NULL);
+
+ loc = PointsToEntry_loc(pte);
+
+ IRO_ASSERT(7277, !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;
+
+ IRO_ASSERT(7398, proc != NULL);
+ IRO_ASSERT(7399, funccall != NULL);
+ IRO_ASSERT(7400, 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;
+
+ IRO_ASSERT(7446, proc != NULL);
+ IRO_ASSERT(7447, funccall != NULL);
+ IRO_ASSERT(7448, 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->preprocess) {
+ 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;
+
+ IRO_ASSERT(7552, loc != NULL);
+ IRO_ASSERT(7553, rtype == NULL || rtype != NULL);
+ IRO_ASSERT(7554, proc != NULL);
+ IRO_ASSERT(7555, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE);
+ IRO_ASSERT(7556, resultFailed != NULL);
+ IRO_ASSERT(7557, *resultFailed == false);
+ IRO_ASSERT(7558, proc != NULL);
+ IRO_ASSERT(7559, 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(%" PRId32 ")", obj->u.var.uid);
+ CError_Error(CErrorStr140, buf);
+ failed = 1;
+ }
+ } else {
+ ep = obj->extParam;
+ IRO_ASSERT(7687, 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;
+
+ IRO_ASSERT(7892, locs != NULL);
+ IRO_ASSERT(7893, rtype == NULL || rtype != NULL);
+ IRO_ASSERT(7894, proc != NULL);
+ IRO_ASSERT(7895, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE);
+ IRO_ASSERT(7896, resultFailed != NULL);
+ IRO_ASSERT(7897, *resultFailed == false);
+ IRO_ASSERT(7898, proc != NULL);
+ IRO_ASSERT(7899, 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;
+
+ IRO_ASSERT(7953, di != NULL);
+
+ if (di->storageclass != TK_TYPEDEF && IS_TYPE_FUNC(di->thetype)) {
+ Boolean flag;
+ proc = CDecl_GetFunctionObject(di, NULL, &flag, 1);
+ if (flag)
+ di->x64 = 1;
+ } else {
+ proc = NULL;
+ }
+
+ return proc;
+}
+
+void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di) {
+ Object *proc;
+ Boolean failed;
+ Boolean anotherFlag;
+
+ IRO_ASSERT(7982, di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+ IRO_ASSERT(7987, proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+ IRO_ASSERT(7996, 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;
+
+ IRO_ASSERT(8097, di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+ IRO_ASSERT(8102, proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+ IRO_ASSERT(8111, 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;
+
+ IRO_ASSERT(8211, di != NULL);
+
+ proc = GetFunctionObjectFromDeclInfo(di);
+ if (proc) {
+ IRO_ASSERT(8216, proc == NULL || ObjectIsAFunction(proc));
+
+ tk = lex();
+ IRO_ASSERT(8225, 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);
+ }
+}
+