diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c | 5734 |
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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + + 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(¶ms, 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, ¶ms); + + if (var && !params.x10) { + ExtendedParam_sub_4867B0(ep, var); + FillInAppropriateMappingsWithExtParamAction(var, ¶ms); + } + + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptfCopy = ptfCopy; + params.mapCopy = mapCopy; + params.stackPtr = &stCallingContextStack; + + PointsToFunction_ForEach(initial, MatchPTFAction1, ¶ms); + PointsToFunction_ForEach(initial, MatchPTFAction2, ¶ms); + + 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(¶ms, 0, sizeof(params)); + params.toBeRemoved = toBeRemoved; + params.toBeAdded = toBeAdded; + params.stackPtr = stackPtr; + params.map = map; + params.x10 = 0; + + LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, ¶ms); + + 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(¶ms, 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, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.last = NULL; + do { + params.lowest = NULL; + pmf_sub_487C70(map, CreateExtendedParamAction, ¶ms); + 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(¶ms, 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, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + 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(¶ms, 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, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + 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(¶ms, 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, ¶ms); + } + } + + 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(¶ms, 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, ¶ms); + + 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(¶ms, 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(¶ms2, 0, sizeof(params2)); + params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block)); + IRO_TruncateValueToType(¶ms2.x0, nd->u.diadic.right->rtype); + params2.nd = nd; + params2.xC = 0; + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + 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(¶ms2, 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(¶ms2.x0, type->size); + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + 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, ¶ms); + + 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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + + 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(¶ms, 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, ¶ms); + + 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(¶ms, 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, ¶ms); + result |= params.x10; + } + result |= EvalMeet(proc, fnode, Int, ptf); + pointsToFunc = Int->pointsToFunction; + x18 = 0; + } else if (!Int->pointsToFunction) { + if (pointsToFunc) + AssignEachInPointsToFunction(pointsToFunc, ¶ms); + 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(¶ms, 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, ¶ms); + } + } +} + +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(¶ms, 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, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + 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(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = NULL; + params.list = list; + LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, ¶ms); + } + } + + 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(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = map; + params.list = list; + PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, ¶ms); + } + 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); + } +} + |