#include "compiler/IroPointerAnalysis.h" #include "compiler/IroEval.h" #include "compiler/IroFlowgraph.h" #include "compiler/IroLinearForm.h" #include "compiler/IroMalloc.h" #include "compiler/IroUtil.h" #include "compiler/IroVars.h" #include "compiler/CDecl.h" #include "compiler/CExpr.h" #include "compiler/CFunc.h" #include "compiler/CMachine.h" #include "compiler/CParser.h" #include "compiler/CPrep.h" #include "compiler/CPrepTokenizer.h" #include "compiler/CScope.h" #include "compiler/InlineAsmPPC.h" #include "compiler/CompilerTools.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler_and_linker/unsorted/IroPointerAnalysisADTs.c" // forward decls static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag); static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag); static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo); static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype); static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result); static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode); static ObjectList *FunctionArguments(Object *proc); static IRONode **FunctionNodeTable(Object *proc); static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag); static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit); static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj); static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj); static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf); static void FindGlobalObjectAction(Object *object, void *refcon); static Boolean ObjectIsRestrictQualified(Object *obj) { return (CParser_GetTypeQualifiers(obj->type, obj->qual) & Q_RESTRICT) != 0; } static Boolean LocationIsVolatile(LocationSet *loc, Object *proc) { Boolean result; Type *rtype; 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); } }