MWCC/compiler_and_linker/unsorted/IroPointerAnalysis.c

5735 lines
189 KiB
C

#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(&params, 0, sizeof(params));
params.set = lss;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
if (Int->nodetype == EPOSTINC || Int->nodetype == EPOSTDEC)
params.pointsToFunc = indirect->pointsToFunction;
else
params.pointsToFunc = Int->pointsToFunction;
params.indRtype = indirect->rtype;
params.x1C = 0;
LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else if (Int->type == IROLinearFunccall) {
IRO_ASSERT(1338, Int->u.funccall.returnedLocs != NULL);
LocationSetSet_AddSet(lss, Int->u.funccall.returnedLocs);
} else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT) {
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf);
memset(&params, 0, sizeof(params));
params.set = lss;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
params.pointsToFunc = Int->pointsToFunction;
params.indRtype = Int->rtype;
params.x1C = 0;
LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else if (Int->type == IROLinearOp2Arg && Int->nodetype == EADD) {
IROAddrRecord *addr = IRO_InitAddrRecordPointer(Int);
IRO_DecomposeAddressExpression(Int, addr);
if (addr->numObjRefs > 1) {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
} else {
CInt64 value;
CInt64 max;
CInt64 work;
Boolean flag1;
Boolean flag2;
CInt64_SetLong(&value, 0);
flag1 = 0;
flag2 = 0;
if (addr->numObjRefs == 1) {
Object *obj;
IRO_ASSERT(1383, addr->objRefs->element->type == IROLinearOperand);
IRO_ASSERT(1384, addr->objRefs->element->u.node->type == EOBJREF);
obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref;
IRO_ASSERT(1387, obj != NULL);
result |= EvalExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf);
flag2 = 1;
}
if (addr->numMisc != 0) {
IROElmList *list;
IROLinear *nd;
max = cint64_max;
for (list = addr->misc; list; list = list->next) {
nd = list->element;
while (nd && nd->type == IROLinearOp1Arg && nd->nodetype == ETYPCON)
nd = nd->u.monadic;
if (nd) {
if (nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) {
if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) {
if (IRO_IsUnsignedType(nd->rtype))
work = CInt64_MulU(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
else
work = CInt64_Mul(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
value = CInt64_Add(value, work);
} else if (IRO_IsIntConstant(nd->u.diadic.left)) {
work = nd->u.diadic.left->u.node->data.intval;
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else if (IRO_IsIntConstant(nd->u.diadic.right)) {
work = nd->u.diadic.right->u.node->data.intval;
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else {
max = cint64_one;
}
} else if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) {
if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) {
work = CInt64_Shl(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval);
IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
value = CInt64_Add(value, work);
} else if (IRO_IsIntConstant(nd->u.diadic.right)) {
work = CInt64_Shl(cint64_one, nd->u.diadic.right->u.node->data.intval);
IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype);
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else {
max = cint64_one;
}
} else {
LocationSet *tmp;
PAMemoryBlock *mb;
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalExpr(lss2, proc, nd, stackPtr, map, ptf);
if (LocationSetSet_FindUnknown(lss2)) {
max = cint64_one;
} else if (
LocationSetSet_Count(lss2) == 1 &&
(tmp = LocationSetSet_FindFirst(lss2)) &&
(LocationSet_stride(tmp) == 0) &&
(mb = LocationSet_block(tmp)) &&
(PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT)
) {
value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb)));
} else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) {
if (flag1) {
LocationSetSet_RemoveAll(lss);
max = cint64_one;
}
LocationSetSet_AddSet(lss, lss2);
flag2 = 1;
} else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
} else if (!flag1) {
LocationSetSet_AddSet(lss, lss2);
flag1 = 1;
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
}
}
}
if (IS_TYPE_POINTER(Int->rtype))
CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size);
else if (IS_TYPE_MEMBERPOINTER(Int->rtype))
CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size);
else
work = cint64_zero;
if (CInt64_GreaterU(work, max))
max = work;
}
if (addr->numInts != 0) {
IROElmList *list;
IROLinear *addend;
for (list = addr->ints; list; list = list->next) {
addend = list->element;
if (addend) {
IRO_ASSERT(1536, IRO_IsIntConstant(addend));
value = CInt64_Add(value, addend->u.node->data.intval);
}
}
}
IRO_TruncateValueToType(&value, Int->rtype);
if (LocationSetSet_Count(lss) == 0) {
if (CInt64_Equal(max, cint64_max)) {
PAMemoryBlock *mb;
LocationSet *ls;
mb = PAMemoryBlock_New();
PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
ls = LocationSet_New();
LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
LocationSetSet_Add(lss, ls);
LocationSet_Term(ls);
LocationSet_Delete(ls);
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
} else {
if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value))
LocationSetSet_ForEach(lss, EvalExprAction, &value);
}
if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max))
LocationSetSet_ForEach(lss, EvalExprAction2, &max);
}
} else if (Int->type == IROLinearOperand) {
Object *obj;
void *thing;
PAMemoryBlockKind kind;
thing = NULL;
if (IRO_IsIntConstant(Int)) {
kind = PAMEMORYBLOCKKIND_INT;
thing = &Int->u.node->data.intval;
} else if (Int->u.node->type == ESTRINGCONST) {
kind = PAMEMORYBLOCKKIND_6;
thing = Int->u.node;
} else if (Int->u.node->type == EOBJREF) {
obj = Int->u.node->data.objref;
IRO_ASSERT(1597, obj != NULL);
if (ObjectIsAnExtendedParamCandidate(obj)) {
kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
thing = CreateExtendedParam(stackPtr, map, obj, &result);
} else {
kind = PAMEMORYBLOCKKIND_LOCALVAR;
thing = PALocalVar_New();
if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj))
PALocalVar_InitByName(thing, obj->name->name);
else
PALocalVar_InitByObject(thing, obj);
}
}
if (thing) {
PAMemoryBlock *mb;
LocationSet *ls;
mb = PAMemoryBlock_New();
PAMemoryBlock_Init(mb, kind, thing);
ls = LocationSet_New();
LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
LocationSetSet_Add(lss, ls);
LocationSet_Term(ls);
LocationSet_Delete(ls);
}
} else if (Int->type == IROLinearOp1Arg && Int->nodetype == EBITFIELD) {
LocationSet *ls;
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf);
if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2)))
LocationSetSet_AddUnknown(lss, NULL, NULL, ls);
else
CError_FATAL(1643);
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype);
if (set && lss)
LocationSetSet_AddSet(set, lss);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
return result;
}
static IROAddrRecord *IRO_InitENodeAddrRecordPointer(ENode *enode) {
IROAddrRecord *addr = IRO_malloc(sizeof(IROAddrRecord));
addr->numObjRefs = 0;
addr->objRefs = NULL;
addr->numMisc = 0;
addr->misc = NULL;
addr->numInts = 0;
addr->ints = NULL;
addr->x16 = 0;
addr->linear = (IROLinear *) enode;
return addr;
}
static void IRO_AddENodeElmToList(ENode *linear, IROElmList **list) {
IROElmList *elmlist = IRO_malloc(sizeof(IROElmList));
elmlist->element = linear;
elmlist->next = NULL;
if (!*list) {
*list = elmlist;
} else {
elmlist->next = *list;
*list = elmlist;
}
}
static void IRO_DecomposeENodeAddressExpression(ENode *node, IROAddrRecord *addr) {
if (node->data.diadic.left->type == EADD) {
IRO_DecomposeENodeAddressExpression(node->data.diadic.left, addr);
} else if (node->data.diadic.left->type == EINTCONST) {
addr->numInts++;
IRO_AddENodeElmToList(node->data.diadic.left, &addr->ints);
} else if (node->data.diadic.left->type == EOBJREF) {
addr->numObjRefs++;
IRO_AddENodeElmToList(node->data.diadic.left, &addr->objRefs);
} else {
addr->numMisc++;
IRO_AddENodeElmToList(node->data.diadic.left, &addr->misc);
}
if (node->data.diadic.right->type == EADD) {
IRO_DecomposeENodeAddressExpression(node->data.diadic.right, addr);
} else if (node->data.diadic.right->type == EINTCONST) {
addr->numInts++;
IRO_AddENodeElmToList(node->data.diadic.right, &addr->ints);
} else if (node->data.diadic.right->type == EOBJREF) {
addr->numObjRefs++;
IRO_AddENodeElmToList(node->data.diadic.right, &addr->objRefs);
} else {
addr->numMisc++;
IRO_AddENodeElmToList(node->data.diadic.right, &addr->misc);
}
}
static Boolean EvalENodeExpr(LocationSetSet *set, Object *proc, ENode *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) {
Boolean result;
LocationSetSet *lss;
LocationSetSet *lss2;
ENode *indirect;
EvalExprAction3Params params;
ENode *originalInt;
IRO_ASSERT(0, set == NULL || set != NULL);
IRO_ASSERT(0, proc != NULL);
IRO_ASSERT(0, Int != NULL);
IRO_ASSERT(0, map == NULL || map != NULL);
IRO_ASSERT(0, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
result = 0;
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
originalInt = Int;
while (Int && Int->type == ETYPCON)
Int = Int->data.monadic;
IRO_ASSERT(0, Int != NULL);
if (IRO_IsAssignOp[Int->type]) {
if (Int->type == EPOSTINC || Int->type == EPOSTDEC || Int->type == EPREINC || Int->type == EPREDEC)
indirect = Int->data.monadic;
else
indirect = Int->data.diadic.left;
IRO_ASSERT(0, indirect->type == EINDIRECT);
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalENodeExpr(lss2, proc, indirect->data.monadic, stackPtr, map, ptf);
memset(&params, 0, sizeof(params));
params.set = lss;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
if (Int->type == EPOSTINC || Int->type == EPOSTDEC)
params.pointsToFunc = indirect->pointsTo;
else
params.pointsToFunc = Int->pointsTo;
params.indRtype = indirect->rtype;
params.x1C = 0;
LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else if (Int->type == EINDIRECT) {
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf);
memset(&params, 0, sizeof(params));
params.set = lss;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
params.pointsToFunc = Int->pointsTo;
params.indRtype = Int->rtype;
params.x1C = 0;
LocationSetSet_ForEach(lss2, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else if (Int->type == EADD) {
IROAddrRecord *addr = IRO_InitENodeAddrRecordPointer(Int);
IRO_DecomposeENodeAddressExpression(Int, addr);
if (addr->numObjRefs > 1) {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
} else {
CInt64 value;
CInt64 max;
CInt64 work;
Boolean flag1;
Boolean flag2;
CInt64_SetLong(&value, 0);
flag1 = 0;
flag2 = 0;
if (addr->numObjRefs == 1) {
Object *obj;
// IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand);
// IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF);
obj = ((ENode *) addr->objRefs->element)->data.objref;
IRO_ASSERT(0, obj != NULL);
result |= EvalENodeExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf);
flag2 = 1;
}
if (addr->numMisc != 0) {
IROElmList *list;
ENode *nd;
max = cint64_max;
for (list = addr->misc; list; list = list->next) {
nd = list->element;
while (nd && nd->type == ETYPCON)
nd = nd->data.monadic;
if (nd) {
if (nd->type == EMUL) {
if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) {
if (IRO_IsUnsignedType(nd->rtype))
work = CInt64_MulU(nd->data.diadic.left->data.intval,
nd->data.diadic.right->data.intval);
else
work = CInt64_Mul(nd->data.diadic.left->data.intval,
nd->data.diadic.right->data.intval);
IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
value = CInt64_Add(value, work);
} else if (nd->data.diadic.left->type == EINTCONST) {
work = nd->data.diadic.left->data.intval;
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else if (nd->data.diadic.right->type == EINTCONST) {
work = nd->data.diadic.right->data.intval;
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else {
max = cint64_one;
}
} else if (nd->type == ESHL) {
if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) {
work = CInt64_Shl(nd->data.diadic.left->data.intval,
nd->data.diadic.right->data.intval);
IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
value = CInt64_Add(value, work);
} else if (nd->data.diadic.right->type == EINTCONST) {
work = CInt64_Shl(cint64_one, nd->data.diadic.right->data.intval);
IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype);
if (!CInt64_IsZero(&work) && CInt64_LessU(work, max))
max = work;
} else {
max = cint64_one;
}
} else {
LocationSet *tmp;
PAMemoryBlock *mb;
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalENodeExpr(lss2, proc, nd, stackPtr, map, ptf);
if (LocationSetSet_FindUnknown(lss2)) {
max = cint64_one;
} else if (
LocationSetSet_Count(lss2) == 1 &&
(tmp = LocationSetSet_FindFirst(lss2)) &&
(LocationSet_stride(tmp) == 0) &&
(mb = LocationSet_block(tmp)) &&
(PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT)
) {
value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb)));
} else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) {
if (flag1) {
LocationSetSet_RemoveAll(lss);
max = cint64_one;
}
LocationSetSet_AddSet(lss, lss2);
flag2 = 1;
} else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
} else if (!flag1) {
LocationSetSet_AddSet(lss, lss2);
flag1 = 1;
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
}
}
}
if (IS_TYPE_POINTER(Int->rtype))
CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size);
else if (IS_TYPE_MEMBERPOINTER(Int->rtype))
CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size);
else
work = cint64_zero;
if (CInt64_GreaterU(work, max))
max = work;
}
if (addr->numInts != 0) {
IROElmList *list;
ENode *addend;
for (list = addr->ints; list; list = list->next) {
addend = list->element;
if (addend) {
IRO_ASSERT(0, addend->type == EINTCONST);
value = CInt64_Add(value, addend->data.intval);
}
}
}
IRO_TruncateValueToType(&value, Int->rtype);
if (LocationSetSet_Count(lss) == 0) {
if (CInt64_Equal(max, cint64_max)) {
PAMemoryBlock *mb;
LocationSet *ls;
mb = PAMemoryBlock_New();
PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value);
ls = LocationSet_New();
LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
LocationSetSet_Add(lss, ls);
LocationSet_Term(ls);
LocationSet_Delete(ls);
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
} else {
if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value))
LocationSetSet_ForEach(lss, EvalExprAction, &value);
}
if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max))
LocationSetSet_ForEach(lss, EvalExprAction2, &max);
}
} else if (Int->type == EOBJREF || Int->type == EINTCONST || Int->type == ESTRINGCONST) {
Object *obj;
void *thing;
PAMemoryBlockKind kind;
thing = NULL;
if (Int->type == EINTCONST) {
kind = PAMEMORYBLOCKKIND_INT;
thing = &Int->data.intval;
} else if (Int->type == ESTRINGCONST) {
kind = PAMEMORYBLOCKKIND_6;
thing = Int;
} else if (Int->type == EOBJREF) {
obj = Int->data.objref;
IRO_ASSERT(0, obj != NULL);
if (ObjectIsAnExtendedParamCandidate(obj)) {
kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
thing = CreateExtendedParam(stackPtr, map, obj, &result);
} else {
kind = PAMEMORYBLOCKKIND_LOCALVAR;
thing = PALocalVar_New();
if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj))
PALocalVar_InitByName(thing, obj->name->name);
else
PALocalVar_InitByObject(thing, obj);
}
}
if (thing) {
PAMemoryBlock *mb;
LocationSet *ls;
mb = PAMemoryBlock_New();
PAMemoryBlock_Init(mb, kind, thing);
ls = LocationSet_New();
LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype);
LocationSetSet_Add(lss, ls);
LocationSet_Term(ls);
LocationSet_Delete(ls);
}
} else if (Int->type == EBITFIELD) {
LocationSet *ls;
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf);
if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2)))
LocationSetSet_AddUnknown(lss, NULL, NULL, ls);
else
CError_FATAL(2146);
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
} else {
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
}
LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype);
if (set && lss)
LocationSetSet_AddSet(set, lss);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
return result;
}
static Boolean EvalVarAddr(LocationSetSet *set, Object *proc, VarRecord *var, Stack **stackPtr, ParamMappingFunction *map) {
Boolean result;
PAMemoryBlockKind kind;
void *thing;
Object *obj;
PAMemoryBlock *block;
LocationSet *loc;
result = 0;
obj = var->object;
if (ObjectIsAnExtendedParamCandidate(obj)) {
kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM;
thing = CreateExtendedParam(stackPtr, map, obj, &result);
} else {
kind = PAMEMORYBLOCKKIND_LOCALVAR;
thing = PALocalVar_New();
if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj))
PALocalVar_InitByName(thing, obj->name->name);
else
PALocalVar_InitByObject(thing, obj);
}
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, kind, thing);
loc = LocationSet_New();
LocationSet_InitKnown(loc, block, cint64_zero, 0, CDecl_NewPointerType(obj->type));
LocationSetSet_Add(set, loc);
LocationSet_Term(loc);
LocationSet_Delete(loc);
return result;
}
static Boolean EvalVariable(LocationSetSet *set, Object *proc, VarRecord *var, PointsToFunction *pointsToFunc, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) {
LocationSetSet *locs;
Boolean result;
EvalExprAction3Params params;
locs = LocationSetSet_New();
LocationSetSet_Init(locs);
result = EvalVarAddr(locs, proc, var, stackPtr, map);
memset(&params, 0, sizeof(params));
params.set = set;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
params.pointsToFunc = pointsToFunc;
params.indRtype = var->object->type;
params.x1C = 0;
LocationSetSet_ForEach(locs, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(locs);
LocationSetSet_Delete(locs);
return result;
}
static void StoreReturnedLocationsAction(LocationSet *loc, void *refcon) {
IRO_ASSERT(2275, loc != NULL);
IRO_ASSERT(2276, refcon != NULL);
if (!LocationSet_IsUnknown(loc)) {
if (PAMemoryBlock_kind(LocationSet_block(loc)) == PAMEMORYBLOCKKIND_HEAPBLOCK) {
PAHeapBlock *hb;
PAMemoryBlock *mb;
CInt64 field;
UInt32 stride;
Type *rtype;
hb = CreateUniqueHeapAlloc_sub_486420();
InitUniqueHeapAlloc_sub_486410(hb, refcon);
mb = PAMemoryBlock_New();
PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_HEAPBLOCK, hb);
field = LocationSet_field(loc);
stride = LocationSet_stride(loc);
rtype = LocationSet_rtype(loc);
LocationSet_Term(loc);
LocationSet_InitKnown(loc, mb, field, stride, rtype);
}
}
}
static void StoreReturnedLocations(IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map) {
LocationSet *retLoc;
LocationSetSet *retLocs;
IRO_ASSERT(2307, nd != NULL);
IRO_ASSERT(2308, nd->type == IROLinearFunccall);
IRO_ASSERT(2309, ptf != NULL);
IRO_ASSERT(2310, map != NULL);
retLoc = PartialTransferFunction_returnLocation(ptf);
retLocs = nd->u.funccall.returnedLocs;
if (!retLocs) {
LocationSetSet_Init(retLocs = nd->u.funccall.returnedLocs = LocationSetSet_New());
} else {
LocationSetSet_RemoveAll(retLocs);
}
Lookup(retLocs, NULL, NULL, NULL, NULL, retLoc, PartialTransferFunction_finalPointsToFn(ptf), 0, NULL);
ExpandLocationSetSetToActuals(&stCallingContextStack, map, retLocs);
LocationSetSet_ForEach(retLocs, StoreReturnedLocationsAction, nd);
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EPParams {
ParamMappingFunction *map;
ExtendedParam *ep;
Object *proc;
Object *var;
unsigned char x10;
unsigned char x11;
} EPParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void FillInAppropriateMappingsWithExtParamAction(Object *obj, void *refcon) {
EPParams *params;
ParamMapping *mapping;
IRO_ASSERT(2352, obj != NULL);
IRO_ASSERT(2353, refcon != NULL);
params = refcon;
IRO_ASSERT(2357, params->map != NULL);
IRO_ASSERT(2358, params->ep != NULL);
IRO_ASSERT(2359, params->proc == NULL || params->proc != NULL);
IRO_ASSERT(2360, params->proc != &stUnknown);
IRO_ASSERT(2361, params->var == NULL || params->var != NULL);
IRO_ASSERT(2362, params->var != &stUnknown);
mapping = ParamMappingFunction_FindMappingByFormal(params->map, obj);
if (!mapping) {
if (ObjectIsAnExtendedParamCandidate(obj) || !params->proc || ObjectIsAFunctionArgument(params->proc, obj)) {
mapping = ParamMapping_New();
ParamMapping_Init_PROBABLY(mapping, NULL, obj, params->ep);
Pmf_Add_sub_486610(params->map, mapping);
ParamMapping_Term(mapping);
ParamMapping_Delete(mapping);
params->x11 = 1;
}
} else {
if (ParamMapping_extended(mapping) != params->ep) {
ParamMapping_SetExtended(mapping, params->ep);
params->x11 = 1;
}
}
if (obj == params->var)
params->x10 = 1;
}
static Boolean FillInAppropriateMappingsWithExtParam(ParamMappingFunction *map, Object *var, ExtendedParam *ep, Object *proc) {
EPParams params;
ObjectSet *objSet;
IRO_ASSERT(2398, map != NULL);
IRO_ASSERT(2399, var == NULL || var != NULL);
IRO_ASSERT(2400, var != &stUnknown);
IRO_ASSERT(2401, ep != NULL);
IRO_ASSERT(2402, proc == NULL || proc != NULL);
IRO_ASSERT(2403, proc != &stUnknown);
memset(&params, 0, sizeof(params));
params.map = map;
params.ep = ep;
params.proc = proc;
params.var = var;
params.x10 = 0;
params.x11 = 0;
if ((objSet = ExtendedParam_objectSet(ep)))
ObjectSet_ForEach(objSet, FillInAppropriateMappingsWithExtParamAction, &params);
if (var && !params.x10) {
ExtendedParam_sub_4867B0(ep, var);
FillInAppropriateMappingsWithExtParamAction(var, &params);
}
return params.x11;
}
static void MatchPTFHelper(LocationSet *loc, LocationSetSet *locs, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) {
PointsToFunction *initial;
PAMemoryBlock *block;
PAMemoryBlockKind kind;
Object *obj;
IRO_ASSERT(2448, loc != NULL);
IRO_ASSERT(2449, !LocationSet_IsUnknown(loc));
IRO_ASSERT(2450, locs != NULL);
IRO_ASSERT(2451, proc != NULL);
IRO_ASSERT(2452, map != NULL);
IRO_ASSERT(2453, ptf != NULL);
initial = PartialTransferFunction_initialPointsToFn(ptf);
IRO_ASSERT(2456, initial != NULL);
IRO_ASSERT(2458, !LocationSet_IsUnknown(loc));
block = LocationSet_block(loc);
IRO_ASSERT(2460, block != NULL);
kind = PAMemoryBlock_kind(block);
if (kind == PAMEMORYBLOCKKIND_LOCALVAR) {
PALocalVar *local;
local = PAMemoryBlock_thing(block);
IRO_ASSERT(2466, local != NULL);
obj = GetLocalObject(local, proc, 1);
if (obj && ObjectIsAFunctionArgument(proc, obj)) {
if (LocationSetSet_Count(locs) == 1) {
LocationSet *ls;
ls = LocationSetSet_FindFirst(locs);
if (ls && !LocationSet_IsUnknown(ls)) {
if ((block = LocationSet_block(ls))) {
if (PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
ExtendedParam *ep;
if ((ep = PAMemoryBlock_thing(block))) {
ExtendedParam_sub_4867B0(ep, obj);
if (stExtParamSet)
ExtParamSet_sub_487630(stExtParamSet, ep);
FillInAppropriateMappingsWithExtParam(map, obj, ep, proc);
}
}
}
}
}
}
} else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
void *ep = PAMemoryBlock_thing(block);
IRO_ASSERT(2489, ep != NULL);
obj = NULL;
ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj);
if (obj && obj != &stUnknown)
FillInAppropriateMappingsWithExtParam(map, obj, ep, proc);
} else {
CError_FATAL(2500);
}
if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, loc)) {
PointsToEntry *pte = PointsToEntry_New();
PointsToEntry_Init(pte, loc, locs);
PointsToFunction_AddWithoutChecking(initial, pte);
PointsToEntry_Term(pte);
PointsToEntry_Delete(pte);
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct MatchPTFActionParams {
Object *proc;
PartialTransferFunction *ptfCopy;
ParamMappingFunction *mapCopy;
Stack **stackPtr;
} MatchPTFActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void MatchPTFAction1(PointsToEntry *tgtPTE, void *refcon) {
MatchPTFActionParams *params;
LocationSet *loc;
LocationSetSet *locs;
PAMemoryBlock *block;
PAMemoryBlockKind kind;
IRO_ASSERT(2525, tgtPTE != NULL);
IRO_ASSERT(2526, refcon != NULL);
params = refcon;
IRO_ASSERT(2530, params->proc != NULL);
IRO_ASSERT(2531, params->ptfCopy != NULL);
IRO_ASSERT(2532, params->mapCopy != NULL);
if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) {
if ((block = LocationSet_block(loc))) {
kind = PAMemoryBlock_kind(block);
if (kind == PAMEMORYBLOCKKIND_LOCALVAR) {
MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy);
} else if (kind != PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
CError_FATAL(2547);
}
}
}
}
static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) {
MatchPTFActionParams *params;
LocationSet *loc;
LocationSetSet *locs;
PAMemoryBlock *block;
PAMemoryBlockKind kind;
IRO_ASSERT(2561, tgtPTE != NULL);
IRO_ASSERT(2562, refcon != NULL);
params = refcon;
IRO_ASSERT(2566, params->proc != NULL);
IRO_ASSERT(2567, params->ptfCopy != NULL);
IRO_ASSERT(2568, params->mapCopy != NULL);
if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) {
if ((block = LocationSet_block(loc))) {
kind = PAMemoryBlock_kind(block);
if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy);
}
}
}
}
static Boolean MatchPTF(PartialTransferFunction *tgtPTF, Object *proc, ParamMappingFunction *map, IROLinear *nd, PartialTransferFunction *ptf) {
Boolean result;
PartialTransferFunction *ptfCopy;
ParamMappingFunction *mapCopy;
PointsToFunction *initial;
MatchPTFActionParams params;
IRO_ASSERT(2593, tgtPTF != NULL);
IRO_ASSERT(2594, proc != NULL);
IRO_ASSERT(2595, map != NULL);
IRO_ASSERT(2596, nd != NULL);
IRO_ASSERT(2597, ptf != NULL);
ptfCopy = PartialTransferFunction_New();
PartialTransferFunction_Copy(ptfCopy, ptf);
mapCopy = ParamMappingFunction_New();
ParamMappingFunction_Copy(mapCopy, map);
initial = PartialTransferFunction_initialPointsToFn(tgtPTF);
PointsToFunction_SortByExtendedParamNum(initial);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptfCopy = ptfCopy;
params.mapCopy = mapCopy;
params.stackPtr = &stCallingContextStack;
PointsToFunction_ForEach(initial, MatchPTFAction1, &params);
PointsToFunction_ForEach(initial, MatchPTFAction2, &params);
result = PointsToFunctions_Match(initial, PartialTransferFunction_initialPointsToFn(ptfCopy));
if (result) {
PartialTransferFunction_Term(ptf);
PartialTransferFunction_Copy(ptf, ptfCopy);
ParamMappingFunction_Term(map);
ParamMappingFunction_Copy(map, mapCopy);
}
PartialTransferFunction_Term(ptfCopy);
PartialTransferFunction_Delete(ptfCopy);
ParamMappingFunction_Term(mapCopy);
ParamMappingFunction_Delete(mapCopy);
return result;
}
static void FindCallTargetsAction2(Object *obj, void *refcon) {
ObjectSet *procList;
IRO_ASSERT(2650, obj != NULL);
IRO_ASSERT(2651, refcon != NULL);
procList = refcon;
if (obj == &stUnknown || ObjectIsAFunction(obj))
ObjectSet_sub_4867D0(procList, obj);
}
static void FindCallTargetsAction(LocationSet *ls, void *refcon) {
ObjectSet *procList;
IRO_ASSERT(2669, ls != NULL);
IRO_ASSERT(2670, refcon != NULL);
procList = refcon;
if (!LocationSet_IsUnknown(ls)) {
PAMemoryBlock *mb = LocationSet_block(ls);
if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
ExtendedParam *ep = PAMemoryBlock_thing(mb);
ObjectSet *objSet = ExtendedParam_objectSet(ep);
ObjectSet_ForEach(objSet, FindCallTargetsAction2, procList);
}
} else {
FindCallTargetsAction2(&stUnknown, procList);
}
}
static int FindCallTargets(ObjectSet *procList, Object *proc, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) {
LocationSetSet *set;
int evalResult;
int result;
IRO_ASSERT(2696, procList != NULL);
IRO_ASSERT(2697, proc != NULL);
IRO_ASSERT(2698, nd != NULL);
IRO_ASSERT(2699, nd->type == IROLinearFunccall);
IRO_ASSERT(2700, map != NULL);
IRO_ASSERT(2701, ptf != NULL);
set = LocationSetSet_New();
LocationSetSet_Init(set);
evalResult = EvalExpr(set, proc, nd->u.funccall.linear8, &stCallingContextStack, map, ptf);
result = evalResult | ExpandLocationSetSetToActuals(&stCallingContextStack, map, set);
LocationSetSet_ForEach(set, FindCallTargetsAction, procList);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
return result;
}
static int LookupParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, Boolean unkflag) {
Boolean result;
ExtendedParam *ep;
IRO_ASSERT(2728, set == NULL || set != NULL);
IRO_ASSERT(2729, ls != NULL);
IRO_ASSERT(2730, var != NULL);
IRO_ASSERT(2731, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(2732, proc != NULL);
IRO_ASSERT(2733, map == NULL || map != NULL);
IRO_ASSERT(2734, ptf == NULL || ptf != NULL);
result = 0;
ep = ExtendedParam_FindByObject(var);
if (!ep)
ep = CreateExtendedParam(stackPtr, map, var, &result);
IRO_ASSERT(2741, ep != NULL);
if (ep) {
PAMemoryBlock *block;
LocationSet *newLS;
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep);
newLS = LocationSet_New();
LocationSet_InitKnown(newLS, block, LocationSet_field(ls), LocationSet_stride(ls), LocationSet_rtype(ls));
if (set)
LocationSetSet_Add(set, newLS);
if (unkflag) {
if (map)
result |= FillInAppropriateMappingsWithExtParam(map, var, ep, proc);
if (ptf) {
PointsToFunction *initial;
initial = PartialTransferFunction_initialPointsToFn(ptf);
if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, ls)) {
LocationSet_Term(newLS);
LocationSet_InitKnown(newLS, LocationSet_block(ls), cint64_zero, 0, LocationSet_rtype(ls));
if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, newLS)) {
LocationSet *newLS2;
LocationSetSet *newSet;
PointsToEntry *newPTE;
newLS2 = LocationSet_New();
LocationSet_InitKnown(newLS2, block, cint64_zero, 0, LocationSet_rtype(ls));
newSet = LocationSetSet_New();
LocationSetSet_Init(newSet);
LocationSetSet_Add(newSet, newLS2);
newPTE = PointsToEntry_New();
PointsToEntry_Init(newPTE, newLS, newSet);
result |= PointsToFunction_Add(initial, newPTE);
PointsToEntry_Term(newPTE);
PointsToEntry_Delete(newPTE);
LocationSetSet_Term(newSet);
LocationSetSet_Delete(newSet);
LocationSet_Term(newLS2);
LocationSet_Delete(newLS2);
}
}
}
}
LocationSet_Term(newLS);
LocationSet_Delete(newLS);
}
return result;
}
static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag) {
Boolean result;
PAMemoryBlock *block;
IROLinear *nd;
ExtendedParam *ep;
ParamMapping *mapping;
Type *savedRtype;
CInt64 savedField;
UInt32 savedStride;
LocationSetSet *newSet;
IRO_ASSERT(2821, set == NULL || set != NULL);
IRO_ASSERT(2822, (ls != NULL && var == NULL) || (ls == NULL && var != NULL));
IRO_ASSERT(2823, ls == NULL || !LocationSet_IsUnknown(ls));
IRO_ASSERT(2824, var != &stUnknown);
IRO_ASSERT(2825, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(2826, map == NULL || map != NULL);
result = 0;
block = NULL;
nd = 0;
ep = NULL;
mapping = NULL;
if (ls) {
block = LocationSet_block(ls);
IRO_ASSERT(2838, block != NULL);
IRO_ASSERT(2839, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
ep = PAMemoryBlock_thing(block);
IRO_ASSERT(2842, ep != NULL);
savedField = LocationSet_field(ls);
savedStride = LocationSet_stride(ls);
savedRtype = LocationSet_rtype(ls);
}
IRO_ASSERT(2848, ep == NULL || ep != NULL);
if (stackPtr && *stackPtr) {
StackElement *element = Stack_Top(stackPtr);
if (element && !map)
map = StackElement_map(element);
}
IRO_ASSERT(2859, map == NULL || map != NULL);
if (ep) {
IRO_ASSERT(2863, var == NULL);
ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var);
if (!var)
var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep));
if (!var)
var = &stUnknown;
}
IRO_ASSERT(2870, var != NULL);
if (map && var != &stUnknown) {
if (flag)
result |= FillInAppropriateMappingsWithExtParam(map, var, ep, NULL);
mapping = ParamMappingFunction_FindMappingByFormal(map, var);
}
newSet = LocationSetSet_New();
LocationSetSet_Init(newSet);
IRO_ASSERT(2884, mapping == NULL || mapping != NULL);
if (mapping)
nd = ParamMapping_actual(mapping);
if (!nd) {
if (!ls) {
IRO_ASSERT(2893, var != NULL);
IRO_ASSERT(2894, ep == NULL);
if (var != &stUnknown) {
ep = CreateExtendedParam(stackPtr, NULL, var, &result);
if (flag && mapping && ParamMapping_extended(mapping) != ep) {
ParamMapping_SetExtended(mapping, ep);
result = 1;
}
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep);
savedField = cint64_zero;
savedStride = 0;
savedRtype = CDecl_NewPointerType(var->type);
} else {
block = LocationSet_block(stUnknownLs);
savedRtype = NULL;
}
} else if (var == &stUnknown || !ObjectIsAnExtendedParamCandidate(var)) {
block = LocationSet_block(stUnknownLs);
savedRtype = NULL;
}
IRO_ASSERT(2925, block != NULL);
if (block == LocationSet_block(stUnknownLs)) {
LocationSetSet_AddUnknown(newSet, savedRtype, NULL, NULL);
} else {
LocationSet *tmp = LocationSet_New();
LocationSet_InitKnown(tmp, block, savedField, savedStride, savedRtype);
LocationSetSet_Add(newSet, tmp);
LocationSet_Term(tmp);
LocationSet_Delete(tmp);
}
} else {
Stack *next;
StackElement *element;
if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) {
if (ls) {
if (!savedStride && !CInt64_IsZero(&savedField)) {
IROLinear *ic;
IROLinear *d;
ic = IRO_NewIntConst(savedField, TYPE(&stunsignedlong));
d = IRO_NewLinear(IROLinearOp2Arg);
d->index = ++IRO_NumLinear;
d->rtype = nd->rtype;
d->u.diadic.left = nd;
d->u.diadic.right = ic;
nd = d;
}
if (savedStride) {
IROLinear *call;
IROLinear *d;
call = IRO_NewLinear(IROLinearFunccall);
call->u.funccall.returnedLocs = LocationSetSet_New();
LocationSetSet_Init(call->u.funccall.returnedLocs);
LocationSetSet_AddUnknown(call->u.funccall.returnedLocs, NULL, NULL, NULL);
d = IRO_NewLinear(IROLinearOp2Arg);
d->index = ++IRO_NumLinear;
d->rtype = nd->rtype;
d->u.diadic.left = nd;
d->u.diadic.right = call;
nd = d;
}
}
EvalExpr(newSet, StackElement_proc(element), nd, &next, StackElement_map(element), StackElement_ptf(element));
} else {
LocationSetSet_AddUnknown(newSet, NULL, NULL, NULL);
}
}
if (set)
LocationSetSet_AddSet(set, newSet);
LocationSetSet_Term(newSet);
LocationSetSet_Delete(newSet);
return result;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct ExpandLocationSetSetActionParams {
LocationSetSet *toBeRemoved;
LocationSetSet *toBeAdded;
Stack **stackPtr;
ParamMappingFunction *map;
Boolean x10;
} ExpandLocationSetSetActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void ExpandLocationSetSetToActualsAction(LocationSet *ls, void *refcon) {
ExpandLocationSetSetActionParams *params;
IRO_ASSERT(3021, ls != NULL);
IRO_ASSERT(3022, refcon != NULL);
params = refcon;
IRO_ASSERT(3026, params->toBeRemoved != NULL);
IRO_ASSERT(3027, params->toBeAdded != NULL);
IRO_ASSERT(3028, params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL);
IRO_ASSERT(3029, params->map == NULL || params->map != NULL);
if (!LocationSet_IsUnknown(ls)) {
PAMemoryBlock *block = LocationSet_block(ls);
if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
ExtendedParam *ep = PAMemoryBlock_thing(block);
if (ep) {
ObjectSet *objSet = ExtendedParam_objectSet(ep);
Object *obj = NULL;
ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
if (!obj) {
LocationSetSet_Add(params->toBeRemoved, ls);
params->x10 |= GetActualLocsOfExtendedParam(params->toBeAdded, ls, NULL, params->stackPtr, params->map, 0);
}
}
}
}
}
static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo) {
LocationSetSet *toBeRemoved;
LocationSetSet *toBeAdded;
ExpandLocationSetSetActionParams params;
Boolean result;
IRO_ASSERT(3063, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(3064, map == NULL || map != NULL);
IRO_ASSERT(3065, thingsPointedTo != NULL);
toBeRemoved = LocationSetSet_New();
LocationSetSet_Init(toBeRemoved);
toBeAdded = LocationSetSet_New();
LocationSetSet_Init(toBeAdded);
memset(&params, 0, sizeof(params));
params.toBeRemoved = toBeRemoved;
params.toBeAdded = toBeAdded;
params.stackPtr = stackPtr;
params.map = map;
params.x10 = 0;
LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, &params);
result = params.x10;
LocationSetSet_sub_488700(thingsPointedTo, toBeRemoved);
LocationSetSet_AddSet(thingsPointedTo, toBeAdded);
LocationSetSet_Term(toBeRemoved);
LocationSetSet_Delete(toBeRemoved);
LocationSetSet_Term(toBeAdded);
LocationSetSet_Delete(toBeAdded);
return result;
}
static void EvaluatePartialAbsolute(LocationSetSet *set, LocationSetSet *thingsPointedTo, LocationSet *dst, Type *indRtype) {
LocationSet *absLoc;
Type *absLocRtype;
PAMemoryBlock *block;
IRO_ASSERT(3108, set != NULL);
IRO_ASSERT(3109, thingsPointedTo != NULL);
IRO_ASSERT(3110, dst != NULL);
IRO_ASSERT(3111, indRtype != NULL);
absLoc = LocationSetSet_FindFirst(thingsPointedTo);
IRO_ASSERT(3114, absLoc != NULL);
if (!LocationSet_IsUnknown(absLoc))
absLocRtype = LocationSet_rtype(absLoc);
if (!LocationSet_IsUnknown(absLoc) && indRtype->size == absLocRtype->size) {
LocationSetSet_AddSet(set, thingsPointedTo);
} else if (
!LocationSet_IsUnknown(absLoc) &&
!LocationSet_stride(absLoc) &&
LocationSetSet_Count(thingsPointedTo) == 1 &&
(block = LocationSet_block(absLoc)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT &&
absLocRtype->size <= stsignedlonglong.size &&
indRtype->size < absLocRtype->size
) {
CInt64 val2;
CInt64 val8;
CInt64 val4;
CInt64 val5;
CInt64 val1;
CInt64 val3;
CInt64 val7;
CInt64 val6;
LocationSet *ls;
val1 = LocationSet_field(absLoc);
val2 = *((CInt64 *) PAMemoryBlock_thing(block));
CInt64_SetLong(&val3, 8);
val4 = cint64_zero;
CInt64_SetLong(&val5, stsignedlonglong.size - absLocRtype->size);
val6 = CInt64_Sub(LocationSet_field(dst), val1);
CInt64_SetLong(&val7, absLocRtype->size - indRtype->size);
val5 = CInt64_Add(val5, val6);
val4 = CInt64_Add(val4, val7);
val4 = CInt64_Sub(val4, val6);
val5 = CInt64_MulU(val5, val3);
val4 = CInt64_MulU(val4, val3);
val8 = cint64_negone;
val8 = CInt64_Shl(val8, val5);
val8 = CInt64_ShrU(val8, val5);
val2 = CInt64_And(val2, val8);
val2 = CInt64_ShrU(val2, val4);
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &val2);
ls = LocationSet_New();
LocationSet_InitKnown(ls, block, cint64_zero, 0, indRtype);
LocationSetSet_Add(set, ls);
LocationSet_Term(ls);
LocationSet_Delete(ls);
} else {
LocationSetSet_AddUnknown(set, indRtype, NULL, NULL);
}
}
static Boolean AddToInitialPointsToFunc(Boolean flag, PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *set) {
Boolean result;
LocationSet *ls;
PointsToFunction *initial;
PointsToEntry *pte;
IRO_ASSERT(3192, ptf == NULL || ptf != NULL);
IRO_ASSERT(3193, dst != NULL);
IRO_ASSERT(3194, set != NULL);
result = 0;
if (flag && ptf) {
ls = LocationSetSet_FindUnknown(set);
if (!ls || LocationSet_rtype(ls)) {
initial = PartialTransferFunction_initialPointsToFn(ptf);
if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, dst)) {
IRO_ASSERT(3208, dst != NULL);
pte = PointsToEntry_New();
PointsToEntry_Init(pte, dst, set);
result = PointsToFunction_AddWithoutChecking(initial, pte);
PointsToEntry_Term(pte);
PointsToEntry_Delete(pte);
}
}
}
return result;
}
static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype) {
Boolean result;
LocationSetSet *mySet;
LocationSetSet *set2;
PAMemoryBlock *block;
ExtendedParam *ep;
PALocalVar *local;
ObjectSet *objSet;
Object *obj;
IRO_ASSERT(3245, set == NULL || set != NULL);
IRO_ASSERT(3246, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(3247, proc == NULL || proc != NULL);
IRO_ASSERT(3248, map == NULL || map != NULL);
IRO_ASSERT(3249, ptf == NULL || ptf != NULL);
IRO_ASSERT(3250, dst != NULL);
IRO_ASSERT(3251, pointsToFunc == NULL || pointsToFunc != NULL);
IRO_ASSERT(3252, indRtype == NULL || indRtype != NULL);
result = 0;
set2 = NULL;
mySet = LocationSetSet_New();
LocationSetSet_Init(mySet);
if (proc) {
if (LocationIsVolatile(dst, proc))
LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
}
if (pointsToFunc && !LocationSet_IsUnknown(dst)) {
PointsToEntry *pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst);
if (pte) {
set2 = PointsToEntry_locs(pte);
} else if (indRtype) {
pte = PointsToFunction_FindContainingLocationSet(pointsToFunc, dst, indRtype);
if (pte)
set2 = PointsToEntry_locs(pte);
}
}
if (set2) {
if (indRtype)
EvaluatePartialAbsolute(mySet, set2, dst, indRtype);
else
LocationSetSet_AddSet(mySet, set2);
} else if (!set2) {
block = NULL;
if (!LocationSet_IsUnknown(dst))
block = LocationSet_block(dst);
if (!LocationSet_IsUnknown(dst) && LocationSet_stride(dst)) {
LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
} else if (
block &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
(ep = PAMemoryBlock_thing(block)) &&
(objSet = ExtendedParam_objectSet(ep))
) {
obj = NULL;
ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
if (!obj) {
LocationSetSet *lss3;
LocationSet *tmp;
// Boolean result1;
EvalExprAction3Params params;
lss3 = LocationSetSet_New();
LocationSetSet_Init(lss3);
result = GetActualLocsOfExtendedParam(lss3, dst, NULL, stackPtr, map, unk);
memset(&params, 0, sizeof(params));
params.set = mySet;
params.stackPtr = stackPtr;
params.proc = proc;
params.map = map;
params.ptf = ptf;
params.pointsToFunc = pointsToFunc;
params.indRtype = indRtype;
params.x1C = 0;
LocationSetSet_ForEach(lss3, EvalExprAction3, &params);
result |= params.x1C;
LocationSetSet_Term(lss3);
LocationSetSet_Delete(lss3);
if ((tmp = LocationSetSet_FindUnknown(mySet))) {
if (!LocationSet_restriction(tmp) && ObjectSet_Count(objSet) == 1) {
if ((obj = ObjectSet_FindFirst(objSet))) {
if (ObjectIsRestrictQualified(obj)) {
LocationSet_Term(tmp);
LocationSet_InitUnknown(tmp, indRtype, block, NULL);
}
}
}
}
result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet);
} else {
// Boolean result1;
Stack *next;
StackElement *element;
result = GetActualLocsOfExtendedParam(NULL, dst, NULL, stackPtr, map, unk);
if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) {
result |= Lookup(mySet, &next, StackElement_proc(element), StackElement_map(element),
StackElement_ptf(element), dst, StackElement_funcCall(element)->pointsToFunction, unk, indRtype);
} else {
LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
}
result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet);
}
} else if (
block &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
(local = PAMemoryBlock_thing(block)) &&
proc &&
(obj = GetLocalObject(local, proc, 1)) &&
ObjectIsAFunctionArgument(proc, obj)
) {
result = LookupParam(mySet, dst, obj, stackPtr, proc, map, ptf, unk);
} else {
LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL);
}
}
if (set)
LocationSetSet_AddSet(set, mySet);
LocationSetSet_Term(mySet);
LocationSetSet_Delete(mySet);
return result;
}
static Boolean InputsHaveNewPointerValues(PartialTransferFunction *tgtPTF, PartialTransferFunction *ptf) {
IRO_ASSERT(3393, tgtPTF != NULL);
IRO_ASSERT(3394, ptf != NULL);
return 0;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct CreateEPActionParams {
ParamMapping *last;
ParamMapping *lowest;
} CreateEPActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void CreateExtendedParamAction(ParamMapping *mapping, void *refcon) {
CreateEPActionParams *params;
ExtendedParam *ep;
uint32 value;
ExtendedParam *lowestEP;
uint32 lowestValue;
ExtendedParam *lastEP;
uint32 lastValue;
IRO_ASSERT(3417, mapping != NULL);
IRO_ASSERT(3418, refcon != NULL);
params = refcon;
IRO_ASSERT(3422, params->last == NULL || params->last != NULL);
IRO_ASSERT(3423, params->lowest == NULL || params->lowest != NULL);
if ((ep = ParamMapping_extended(mapping))) {
value = ExtendedParam_sub_489110(ep);
if (params->lowest) {
lowestEP = ParamMapping_extended(params->lowest);
lowestValue = ExtendedParam_sub_489110(lowestEP);
if (params->last) {
lastEP = ParamMapping_extended(params->last);
lastValue = ExtendedParam_sub_489110(lastEP);
if (value > lastValue && value < lowestValue)
params->lowest = mapping;
} else if (value < lowestValue) {
params->lowest = mapping;
}
} else if (params->last) {
lastEP = ParamMapping_extended(params->last);
lastValue = ExtendedParam_sub_489110(lastEP);
if (value > lastValue)
params->lowest = mapping;
} else {
params->lowest = mapping;
}
}
}
static ExtendedParam *FindMatchingExtendedParam(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *lss, ParamMapping *lowest, Boolean *result) {
ExtendedParam *ep;
ExtendedParam *lowestEP;
IRO_ASSERT(3473, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(3474, map == NULL || map != NULL);
IRO_ASSERT(3475, lss != NULL);
IRO_ASSERT(3476, lowest != NULL);
ep = NULL;
if ((lowestEP = ParamMapping_extended(lowest))) {
PAMemoryBlock *block;
LocationSet *lowestLS;
LocationSetSet *lowestLSS;
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, lowestEP);
lowestLS = LocationSet_New();
LocationSet_InitKnown(lowestLS, block, cint64_zero, 0, TYPE(&void_ptr));
lowestLSS = LocationSetSet_New();
LocationSetSet_Init(lowestLSS);
*result |= GetActualLocsOfExtendedParam(lowestLSS, lowestLS, NULL, stackPtr, map, 0);
if (LocationSetSets_Equal(lowestLSS, lss))
ep = lowestEP;
LocationSetSet_Term(lowestLSS);
LocationSetSet_Delete(lowestLSS);
LocationSet_Term(lowestLS);
LocationSet_Delete(lowestLS);
}
return ep;
}
static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result) {
ExtendedParam *ep;
ParamMapping *mapping;
LocationSetSet *lss;
CreateEPActionParams params;
IRO_ASSERT(3518, map == NULL || map != NULL);
IRO_ASSERT(3519, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL);
IRO_ASSERT(3520, var != NULL);
mapping = NULL;
if (map)
mapping = ParamMappingFunction_FindMappingByFormal(map, var);
ep = ExtendedParam_FindByObject(var);
if (ep) {
if (mapping)
IRO_ASSERT(3535, ep == ParamMapping_extended(mapping) || ParamMapping_extended(mapping) == NULL);
} else if (map && !ObjectIsRestrictQualified(var)) {
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
*result |= GetActualLocsOfExtendedParam(lss, NULL, var, stackPtr, map, 0);
memset(&params, 0, sizeof(params));
params.last = NULL;
do {
params.lowest = NULL;
pmf_sub_487C70(map, CreateExtendedParamAction, &params);
if (params.lowest && params.lowest != mapping)
ep = FindMatchingExtendedParam(stackPtr, map, lss, params.lowest, result);
params.last = params.lowest;
} while (params.lowest && !ep);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
}
if (!ep)
ep = ExtendedParam_FindByObject(var);
if (!ep) {
ep = ExtendedParam_New();
ExtendedParam_Init(ep, var);
} else {
ExtendedParam_sub_4867B0(ep, var);
}
if (stExtParamSet)
ExtParamSet_sub_487630(stExtParamSet, ep);
IRO_ASSERT(3583, ep != NULL);
return ep;
}
#ifdef IRO_DEBUG
void __assertion_failed(char *expr, char *filename, int line) {
CError_ASSERT(3605, filename);
CError_Internal(filename, line);
}
#endif
static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) {
IRO_ASSERT(3628, nd != NULL);
IRO_ASSERT(3629, nd->type == IROLinearFunccall);
IRO_ASSERT(3630, proc != NULL);
IRO_ASSERT(3631, map != NULL);
if (proc != &stUnknown) {
int i;
ObjectList *args;
Object *arg;
args = FunctionArguments(proc);
if (args)
arg = args->object;
else
arg = &stUnknown;
for (i = 0; i < nd->u.funccall.argCount; i++) {
IRO_ASSERT(3643, arg != NULL);
if (arg != &stUnknown) {
ParamMapping *mapping = ParamMapping_New();
ParamMapping_Init_PROBABLY(mapping, nd->u.funccall.args[i], arg, NULL);
Pmf_Add_sub_486610(map, mapping);
ParamMapping_Term(mapping);
ParamMapping_Delete(mapping);
}
if (args) {
args = args->next;
if (args)
arg = args->object;
else
arg = &stUnknown;
}
}
}
}
static Boolean IsAddressableLocation(LocationSet *loc, Object *proc, IRONode *fnode, IROLinear *nd) {
IRO_ASSERT(3676, loc != NULL);
IRO_ASSERT(3677, fnode != NULL);
IRO_ASSERT(3678, nd != NULL);
if (!LocationSet_IsUnknown(loc)) {
PAMemoryBlock *block;
PALocalVar *local;
Object *obj;
ExtendedParam *ep;
ObjectSet *objSet;
block = LocationSet_block(loc);
if (
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
(local = PAMemoryBlock_thing(block)) &&
(obj = GetLocalObject(local, proc, 0)) &&
fnode->addressed &&
!ObjectSet_sub_485020(fnode->addressed, obj)
) {
return 0;
}
if (
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
(ep = PAMemoryBlock_thing(block)) &&
(objSet = ExtendedParam_objectSet(ep)) &&
ObjectSet_Count(objSet) == 1 &&
(obj = ObjectSet_FindFirst(objSet)) &&
ObjectIsAFunctionArgument(proc, obj) &&
ObjectIsRestrictQualified(obj)
) {
return 0;
}
}
return 1;
}
static Boolean LocationSetsAlias(LocationSet *ls1, LocationSet *ls2) {
IRO_ASSERT(3719, ls1 != NULL);
IRO_ASSERT(3720, ls2 != NULL);
return
(ls1 == ls2) ||
LocationSet_IsUnknown(ls1) ||
LocationSet_IsUnknown(ls2) ||
(
(LocationSet_stride(ls1) ||
LocationSet_stride(ls2) ||
CInt64_Equal(LocationSet_field(ls1), LocationSet_field(ls2))) &&
MemoryBlocks_Equal(LocationSet_block(ls1), LocationSet_block(ls2))
);
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct FindAliasingParams {
LocationSetSet *x0;
LocationSet *x4;
Boolean x8;
} FindAliasingParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void FindAliasingAction2(LocationSet *ls, void *refcon) {
FindAliasingParams *params;
params = refcon;
if (!params->x8) {
if (LocationSetsAlias(params->x4, ls))
params->x8 = 1;
}
}
static void FindAliasingAction(LocationSet *ls, void *refcon) {
FindAliasingParams *params;
IRO_ASSERT(3751, ls != NULL);
IRO_ASSERT(3752, refcon != NULL);
params = refcon;
if (!params->x8) {
params->x4 = ls;
LocationSetSet_ForEach(params->x0, FindAliasingAction2, params);
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct KillLocationParams {
Object *proc;
IRONode *fnode;
IROLinear *nd;
PartialTransferFunction *ptf;
PointsToFunction *toBeKilled;
LocationSet *dst;
Boolean x18;
} KillLocationParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void KillAllAddressableLocationsAction(PointsToEntry *pte, void *refcon) {
KillLocationParams *params;
LocationSet *loc;
IRO_ASSERT(3779, pte != NULL);
IRO_ASSERT(3780, refcon != NULL);
params = refcon;
IRO_ASSERT(3784, params->proc != NULL);
IRO_ASSERT(3785, params->fnode != NULL);
IRO_ASSERT(3786, params->nd != NULL);
IRO_ASSERT(3787, params->ptf != NULL);
IRO_ASSERT(3788, params->toBeKilled != NULL);
IRO_ASSERT(3789, params->dst == NULL);
loc = PointsToEntry_loc(pte);
IRO_ASSERT(3793, loc != NULL);
IRO_ASSERT(3794, !LocationSet_IsUnknown(loc));
if (IsAddressableLocation(loc, params->proc, params->fnode, params->nd))
PointsToFunction_Add(params->toBeKilled, pte);
}
static void KillAllAliasingExtParamLocsAction(PointsToEntry *pte, void *refcon) {
KillLocationParams *params;
LocationSet *loc;
IRO_ASSERT(3813, pte != NULL);
IRO_ASSERT(3814, refcon != NULL);
params = refcon;
IRO_ASSERT(3818, params->proc != NULL);
IRO_ASSERT(3819, params->fnode != NULL);
IRO_ASSERT(3820, params->nd != NULL);
IRO_ASSERT(3821, params->ptf != NULL);
IRO_ASSERT(3822, params->toBeKilled != NULL);
IRO_ASSERT(3823, params->dst != NULL);
IRO_ASSERT(3824, LocationSet_block(params->dst) != NULL);
IRO_ASSERT(3825, PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
loc = PointsToEntry_loc(pte);
IRO_ASSERT(3829, loc != NULL);
IRO_ASSERT(3830, !LocationSet_IsUnknown(loc));
if (loc != params->dst) {
if (LocationSetsAlias(loc, params->dst)) {
PointsToFunction_Add(params->toBeKilled, pte);
} else {
ExtendedParam *ep;
ObjectSet *objSet;
Object *obj;
PAMemoryBlock *block;
if (
(ep = PAMemoryBlock_thing(LocationSet_block(params->dst))) &&
(objSet = ExtendedParam_objectSet(ep)) &&
(ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) &&
(block = LocationSet_block(loc)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
(ep = PAMemoryBlock_thing(block)) &&
(objSet = ExtendedParam_objectSet(ep)) &&
(ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj))
) {
LocationSetSet *lss1;
LocationSetSet *lss2;
Boolean changed;
FindAliasingParams aparams;
lss1 = LocationSetSet_New();
LocationSetSet_Init(lss1);
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
changed = GetActualLocsOfExtendedParam(lss1, loc, NULL, &stCallingContextStack, NULL, 0);
changed |= GetActualLocsOfExtendedParam(lss2, params->dst, NULL, &stCallingContextStack, NULL, 0);
memset(&aparams, 0, sizeof(aparams));
aparams.x8 = 0;
aparams.x0 = lss2;
LocationSetSet_ForEach(lss1, FindAliasingAction, &aparams);
if (aparams.x8)
PointsToFunction_Add(params->toBeKilled, pte);
LocationSetSet_Term(lss1);
LocationSetSet_Delete(lss1);
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
}
}
}
}
static void KillLocationsAction(PointsToEntry *pte, void *refcon) {
KillLocationParams *params;
LocationSet *loc;
LocationSetSet *lss;
IRO_ASSERT(3886, pte != NULL);
IRO_ASSERT(3887, refcon != NULL);
params = refcon;
IRO_ASSERT(3891, params->proc != NULL);
IRO_ASSERT(3892, params->fnode != NULL);
IRO_ASSERT(3893, params->nd != NULL);
IRO_ASSERT(3894, params->ptf != NULL);
IRO_ASSERT(3895, params->toBeKilled != NULL);
IRO_ASSERT(3896, params->dst == NULL);
loc = PointsToEntry_loc(pte);
IRO_ASSERT(3900, loc != NULL);
IRO_ASSERT(3901, !LocationSet_IsUnknown(loc));
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
params->x18 |= Assign(params->ptf, loc, lss, params->proc, params->nd, params->fnode);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
}
static Boolean KillAllAddressableLocations(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) {
Boolean result;
PointsToFunction *pointsToFunc;
PointsToFunction *pointsToFuncCopy;
PointsToFunction *toBeKilled;
KillLocationParams params;
IRO_ASSERT(3921, proc != NULL);
IRO_ASSERT(3922, fnode == NULL || fnode != NULL);
IRO_ASSERT(3923, nd == NULL || nd != NULL);
IRO_ASSERT(3924, ptf != NULL);
if (nd && nd->pointsToFunction)
pointsToFunc = nd->pointsToFunction;
else
pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
pointsToFuncCopy = PointsToFunction_New();
PointsToFunction_Copy(pointsToFuncCopy, pointsToFunc);
toBeKilled = PointsToFunction_New();
PointsToFunction_Init(toBeKilled);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.fnode = fnode;
params.nd = nd;
params.ptf = ptf;
params.toBeKilled = toBeKilled;
params.dst = NULL;
params.x18 = 0;
if (pointsToFunc) {
PointsToFunction_ForEach(pointsToFunc, KillAllAddressableLocationsAction, &params);
PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, &params);
}
PointsToFunction_Term(toBeKilled);
PointsToFunction_Delete(toBeKilled);
if (params.x18)
result = !PointsToFunctions_Equal(pointsToFuncCopy, pointsToFunc);
else
result = 0;
PointsToFunction_Term(pointsToFuncCopy);
PointsToFunction_Delete(pointsToFuncCopy);
return result;
}
static void KillAllAliasingExtParamLocs(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, LocationSet *dst) {
PointsToFunction *pointsToFunc;
PointsToFunction *toBeKilled;
KillLocationParams params;
IRO_ASSERT(3974, proc != NULL);
IRO_ASSERT(3975, fnode == NULL || fnode != NULL);
IRO_ASSERT(3976, nd == NULL || nd != NULL);
IRO_ASSERT(3977, ptf != NULL);
IRO_ASSERT(3978, dst != NULL);
if (!LocationSet_IsUnknown(dst) && LocationSet_block(dst)) {
if (PAMemoryBlock_kind(LocationSet_block(dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
if (nd && nd->pointsToFunction)
pointsToFunc = nd->pointsToFunction;
else
pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
toBeKilled = PointsToFunction_New();
PointsToFunction_Init(toBeKilled);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.fnode = fnode;
params.nd = nd;
params.ptf = ptf;
params.toBeKilled = toBeKilled;
params.dst = dst;
params.x18 = 0;
if (pointsToFunc) {
PointsToFunction_ForEach(pointsToFunc, KillAllAliasingExtParamLocsAction, &params);
PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, &params);
}
PointsToFunction_Term(toBeKilled);
PointsToFunction_Delete(toBeKilled);
}
}
}
static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode) {
PointsToFunction *pointsToFunc;
Boolean result;
PointsToEntry *pte;
LocationSet *loc;
LocationSetSet *locs;
LocationSet *bitfieldOf;
LocationSetSet *lss;
IRO_ASSERT(4027, ptf != NULL);
IRO_ASSERT(4028, dst != NULL);
IRO_ASSERT(4029, srcs != NULL);
IRO_ASSERT(4030, proc != NULL);
IRO_ASSERT(4031, nd == NULL || nd != NULL);
IRO_ASSERT(4032, fnode == NULL || fnode != NULL);
if (nd) {
if (!nd->pointsToFunction) {
nd->pointsToFunction = PointsToFunction_New();
PointsToFunction_Init(nd->pointsToFunction);
}
pointsToFunc = nd->pointsToFunction;
} else {
pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf);
}
pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst);
if (pte) {
loc = PointsToEntry_loc(pte);
locs = PointsToEntry_locs(pte);
IRO_ASSERT(4056, !LocationSet_IsUnknown(dst));
IRO_ASSERT(4057, LocationSet_stride(dst) == 0 || LocationSet_stride(loc) != 0);
result = !LocationSetSets_Equal(srcs, locs) || LocationSet_stride(dst) != LocationSet_stride(loc);
if (result) {
pte = PointsToEntry_New();
PointsToEntry_Init(pte, dst, srcs);
PointsToFunction_RemoveByLocationSet(pointsToFunc, loc);
PointsToFunction_AddWithoutChecking(pointsToFunc, pte);
PointsToEntry_Term(pte);
PointsToEntry_Delete(pte);
}
} else if (!LocationSet_IsUnknown(dst)) {
KillAllAliasingExtParamLocs(proc, fnode, nd, ptf, dst);
pte = PointsToEntry_New();
PointsToEntry_Init(pte, dst, srcs);
result = PointsToFunction_AddWithoutChecking(pointsToFunc, pte);
PointsToEntry_Term(pte);
PointsToEntry_Delete(pte);
} else if ((bitfieldOf = LocationSet_bitfieldOf(dst))) {
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
LocationSetSet_AddUnknown(lss, NULL, NULL, NULL);
result = Assign(ptf, bitfieldOf, lss, proc, nd, fnode);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
} else if (!LocationSet_restriction(dst)) {
result = KillAllAddressableLocations(proc, fnode, nd, ptf);
}
return result;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EvalMeetActionParams {
Object *proc;
IRONode *fnode;
IRONode *pred;
IROLinear *nd;
PartialTransferFunction *ptf;
Boolean x14;
Boolean x15;
} EvalMeetActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalMeetAction(PointsToEntry *pte, void *refcon) {
EvalMeetActionParams *params;
LocationSet *loc;
LocationSetSet *set;
UInt16 i;
IRO_ASSERT(4123, pte != NULL);
IRO_ASSERT(4124, refcon != NULL);
params = refcon;
IRO_ASSERT(4128, params->proc != NULL);
IRO_ASSERT(4129, params->fnode != NULL);
IRO_ASSERT(4130, params->pred != NULL);
IRO_ASSERT(4131, params->nd != NULL);
IRO_ASSERT(4132, params->ptf != NULL);
loc = PointsToEntry_loc(pte);
set = LocationSetSet_New();
LocationSetSet_Init(set);
LocationSetSet_AddSet(set, PointsToEntry_locs(pte));
for (i = 0; i < params->fnode->numpred; i++) {
IRONode *pred = FunctionNodeTable(params->proc)[params->fnode->pred[i]];
if (pred->x3C && pred != params->pred) {
params->x14 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, loc, pred->last->pointsToFunction, 0, NULL);
}
}
params->x15 |= Assign(params->ptf, loc, set, params->proc, params->nd, params->fnode);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
static Boolean EvalMeet(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) {
PointsToFunction *pointsToFunc;
EvalMeetActionParams params;
int i;
IRO_ASSERT(4163, proc != NULL);
IRO_ASSERT(4164, fnode != NULL);
IRO_ASSERT(4165, nd != NULL);
IRO_ASSERT(4166, ptf != NULL);
pointsToFunc = PointsToFunction_New();
if (nd->pointsToFunction)
PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
else
PointsToFunction_Init(pointsToFunc);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.fnode = fnode;
params.nd = nd;
params.ptf = ptf;
params.x14 = 0;
params.x15 = 0;
for (i = 0; i < fnode->numpred; i++) {
IRONode *pred = FunctionNodeTable(proc)[fnode->pred[i]];
params.pred = pred;
if (pred->x3C && pred->last->pointsToFunction) {
PointsToFunction_ForEach(pred->last->pointsToFunction, EvalMeetAction, &params);
}
}
if (!params.x14 && params.x15) {
if (nd->pointsToFunction)
params.x14 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
else
params.x14 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
}
PointsToFunction_Term(pointsToFunc);
PointsToFunction_Delete(pointsToFunc);
return params.x14;
}
static PartialTransferFunction *AllocatePTF(Object *proc, IROLinear *nd, PartialTransferFunction *ptf) {
PartialTransferFunction *newPTF;
IRO_ASSERT(4210, proc != NULL);
IRO_ASSERT(4211, proc->u.func.ptfList != NULL);
IRO_ASSERT(4212, nd == NULL || nd != NULL);
IRO_ASSERT(4213, ptf == NULL || ptf != NULL);
newPTF = PartialTransferFunction_New();
PartialTransferFunction_Init(newPTF, nd, ptf);
PTFList_sub_48A050(proc->u.func.ptfList, newPTF);
return newPTF;
}
static Object *FindMainEntryPoint(Object *function) {
IRO_ASSERT(4229, function != NULL);
return function;
}
static ObjectList *FunctionArguments(Object *proc) {
Object *search;
ObjectList *scan;
ObjectList *list;
ObjectList *prev;
ExtendedParam *ep;
char *name;
VarInfo *vi;
Object *obj;
FuncArg *args;
Boolean notFound;
IRO_ASSERT(4252, proc != NULL);
if (proc == stCurrentProc) {
for (list = arguments; list; list = list->next) {
if ((obj = list->object) && obj->name && (name = obj->name->name) && name[0]) {
prev = NULL;
for (scan = proc->u.func.argList; scan; scan = scan->next) {
prev = scan;
if ((search = scan->object) && search->name && search->name->name) {
if (!strcmp(name, search->name->name))
break;
}
}
if (!scan)
search = NULL;
notFound = !search;
if (!search) {
search = IRO_malloc(sizeof(Object));
ep = NULL;
search->u.var.info = IRO_malloc(sizeof(VarInfo));
memset(search->u.var.info, 0, sizeof(VarInfo));
search->u.var.info->func = proc;
} else {
ep = search->extParam;
}
vi = search->u.var.info;
memcpy(search, obj, sizeof(Object));
search->extParam = ep;
search->u.var.info = vi;
search->u.var.realObj = obj;
if (notFound) {
scan = IRO_malloc(sizeof(ObjectList));
scan->next = NULL;
scan->object = search;
if (!prev)
proc->u.func.argList = scan;
else
prev->next = scan;
}
}
}
} else if (proc->type) {
for (args = TYPE_FUNC(proc->type)->args; args; args = args->next) {
if (args->name && (name = args->name->name) && name[0]) {
prev = NULL;
for (scan = proc->u.func.argList; scan; scan = scan->next) {
prev = scan;
if ((search = scan->object) && search->name && search->name->name) {
if (!strcmp(name, search->name->name))
break;
}
}
if (!scan)
search = NULL;
if (!search) {
search = IRO_malloc(sizeof(Object));
memset(search, 0, sizeof(Object));
search->datatype = DLOCAL;
search->extParam = NULL;
search->name = GetHashNameNodeExport(name);
search->type = args->type;
search->qual = args->qual;
search->u.var.info = IRO_malloc(sizeof(VarInfo));
memset(search->u.var.info, 0, sizeof(VarInfo));
search->u.var.info->func = proc;
scan = IRO_malloc(sizeof(ObjectList));
scan->next = NULL;
scan->object = search;
if (!prev)
proc->u.func.argList = scan;
else
prev->next = scan;
}
}
}
}
return proc->u.func.argList;
}
static IRONode **FunctionNodeTable(Object *proc) {
IRO_ASSERT(4383, proc != NULL);
IRO_ASSERT(4391, proc == stCurrentProc);
return IRO_NodeTable;
}
static IRONode *FunctionFirstNode(Object *proc) {
IRO_ASSERT(4401, proc != NULL);
IRO_ASSERT(4409, proc == stCurrentProc);
return IRO_FirstNode;
}
static void UpdatePTFDomain() {
// no idea what this would've done
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EvalCallActionParams {
Object *proc;
IRONode *fnode;
IROLinear *nd;
PartialTransferFunction *ptf;
ParamMappingFunction *map;
int x14;
Boolean x18;
Boolean x19;
Boolean x1A;
} EvalCallActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalCallAction(Object *proc, void *refcon) {
EvalCallActionParams *params;
ParamMappingFunction *pmf;
PartialTransferFunction *tgtPTF;
Boolean flag;
Boolean flag2;
IRO_ASSERT(4458, proc != NULL);
IRO_ASSERT(4459, refcon != NULL);
params = refcon;
IRO_ASSERT(4463, params->proc != NULL);
IRO_ASSERT(4464, params->fnode != NULL);
IRO_ASSERT(4465, params->nd != NULL);
IRO_ASSERT(4466, params->ptf != NULL);
IRO_ASSERT(4467, params->map == NULL || params->map != NULL);
if (!params->x18) {
pmf = ParamMappingFunction_New();
ParamMappingFunction_Init(pmf);
RecordActuals(params->nd, proc, pmf);
flag = 0;
if (!Stack_sub_48A710(&stCallingContextStack, proc)) {
StackElement *element;
flag2 = 0;
tgtPTF = GetPTF(pmf, proc, params->nd, params->ptf, &flag2);
element = StackElement_New();
StackElement_Init(element, proc, tgtPTF, pmf, params->nd);
Stack_sub_48A660(&stCallingContextStack, element);
StackElement_Term(element);
StackElement_Delete(element);
IRO_ASSERT(4490, tgtPTF != NULL);
flag = 1;
if (stPTFList)
PTFList_sub_48A050(stPTFList, tgtPTF);
PartialTransferFunction_sub_48A610(tgtPTF, 0);
if (flag2 || params->x1A) {
if (params->x1A) {
params->x1A = 0;
EvalProc(proc, pmf, tgtPTF);
} else {
tgtPTF = stUnknownPTF;
}
}
} else {
tgtPTF = stUnknownPTF;
}
if (params->map)
params->x19 |= ApplySummary(tgtPTF, pmf, params->proc, params->fnode, params->nd, params->ptf, params->map, params->x14 == 1);
if (flag) {
StackElement *element = Stack_sub_48A5B0(&stCallingContextStack);
StackElement_Term(element);
StackElement_Delete(element);
}
ParamMappingFunction_Term(pmf);
ParamMappingFunction_Delete(pmf);
}
}
static Boolean EvalCall(Object *proc, IRONode *fnode, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) {
EvalCallActionParams params;
ObjectSet *objSet;
IRO_ASSERT(4548, proc != NULL);
IRO_ASSERT(4549, fnode != NULL);
IRO_ASSERT(4550, nd != NULL);
IRO_ASSERT(4551, map != NULL);
IRO_ASSERT(4552, ptf != NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.fnode = fnode;
params.nd = nd;
params.ptf = ptf;
params.map = map;
params.x18 = 0;
params.x19 = 0;
params.x1A = 0;
objSet = ObjectSet_New();
ObjectSet_Init(objSet);
params.x19 |= FindCallTargets(objSet, proc, nd, map, ptf);
params.x14 = ObjectSet_Count(objSet);
ObjectSet_ForEach(objSet, EvalCallAction, &params);
ObjectSet_Term(objSet);
ObjectSet_Delete(objSet);
return params.x19;
}
static void AdjustTypesForVolatilityAction(LocationSet *ls, void *refcon) {
Type *type;
Type *newtype;
UInt32 qual;
type = LocationSet_rtype(ls);
switch (type->type) {
case TYPEARRAY:
qual = TYPE_POINTER(type)->qual;
break;
case TYPEPOINTER:
qual = TYPE_POINTER(type)->qual;
break;
case TYPEMEMBERPOINTER:
qual = TYPE_MEMBER_POINTER(type)->qual;
break;
default:
CError_FATAL(4604);
}
if (!(qual & Q_VOLATILE)) {
switch (type->type) {
case TYPEARRAY:
newtype = CDecl_NewArrayType(TYPE_POINTER(type)->target, type->size);
TYPE_POINTER(newtype)->qual |= Q_VOLATILE;
break;
case TYPEPOINTER:
newtype = CDecl_NewPointerType(TYPE_POINTER(type)->target);
TYPE_POINTER(newtype)->qual |= Q_VOLATILE;
break;
case TYPEMEMBERPOINTER:
newtype = galloc(sizeof(TypeMemberPointer));
memcpy(newtype, type, sizeof(TypeMemberPointer));
TYPE_MEMBER_POINTER(newtype)->qual |= Q_VOLATILE;
break;
}
LocationSet_SetRtype(ls, newtype);
}
}
static void AdjustTypesForVolatility(LocationSetSet *set, Object *proc, IROLinear *nd) {
if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS))
LocationSetSet_ForEach(set, AdjustTypesForVolatilityAction, NULL);
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EvalAssignAction2Params {
CInt64 x0;
IROLinear *nd;
Boolean xC;
} EvalAssignAction2Params;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalAssignAction2(LocationSet *ls, void *refcon) {
EvalAssignAction2Params *params;
CInt64 value;
IROLinear *nd;
ENodeType oper;
UInt32 stride;
Type *rtype;
PAMemoryBlock *block;
IRO_ASSERT(4657, ls != NULL);
IRO_ASSERT(4658, refcon != NULL);
params = refcon;
if (!params->xC && !LocationSet_IsUnknown(ls)) {
value = params->x0;
nd = params->nd;
IRO_ASSERT(4665, nd != NULL);
oper = nd->nodetype;
stride = LocationSet_stride(ls);
rtype = LocationSet_rtype(ls);
block = LocationSet_block(ls);
if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT) {
LocationSet_Term(ls);
switch (oper) {
case EPOSTINC:
case EPREINC:
case EADDASS:
value = CInt64_Add(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EPOSTDEC:
case EPREDEC:
case ESUBASS:
value = CInt64_Sub(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EMULASS:
if (IRO_IsUnsignedType(nd->rtype))
value = CInt64_MulU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
else
value = CInt64_Mul(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EDIVASS:
if (CInt64_IsZero(&value)) {
if (nd->stmt->sourceoffset) {
TStreamElement *e = CPrep_CurStreamElement();
e->tokenoffset = nd->stmt->sourceoffset;
CError_SetErrorToken(e);
}
CError_Warning(CErrorStr139);
params->xC = 1;
} else {
if (IRO_IsUnsignedType(nd->rtype))
value = CInt64_DivU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
else
value = CInt64_Div(*((CInt64 *) PAMemoryBlock_thing(block)), value);
}
break;
case EMODASS:
if (CInt64_IsZero(&value)) {
if (nd->stmt->sourceoffset) {
TStreamElement *e = CPrep_CurStreamElement();
e->tokenoffset = nd->stmt->sourceoffset;
CError_SetErrorToken(e);
}
CError_Warning(CErrorStr139);
params->xC = 1;
} else {
if (IRO_IsUnsignedType(nd->rtype))
value = CInt64_ModU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
else
value = CInt64_Mod(*((CInt64 *) PAMemoryBlock_thing(block)), value);
}
break;
case ESHLASS:
value = CInt64_Shl(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case ESHRASS:
if (IRO_IsUnsignedType(nd->rtype))
value = CInt64_ShrU(*((CInt64 *) PAMemoryBlock_thing(block)), value);
else
value = CInt64_Shr(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EANDASS:
value = CInt64_And(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EXORASS:
value = CInt64_Xor(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
case EORASS:
value = CInt64_Or(*((CInt64 *) PAMemoryBlock_thing(block)), value);
break;
default:
CError_FATAL(4746);
}
block = PAMemoryBlock_New();
PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &value);
LocationSet_InitKnown(ls, block, cint64_zero, stride, rtype);
} else {
if (oper == EPOSTDEC || oper == EPREDEC || oper == ESUBASS)
value = CInt64_Neg(value);
switch (oper) {
case EPOSTINC:
case EPOSTDEC:
case EPREINC:
case EPREDEC:
case EADDASS:
case ESUBASS:
value = CInt64_Add(LocationSet_field(ls), value);
if (stride) {
CInt64 tmp;
CInt64_SetLong(&tmp, stride);
value = CInt64_Mod(value, tmp);
}
SetsLocationSetField_sub_4851B0(ls, value);
break;
default:
params->xC = 1;
break;
}
}
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EvalAssignActionParams {
Object *proc;
PartialTransferFunction *ptf;
IROLinear *nd;
IRONode *fnode;
LocationSetSet *srcs;
Boolean x14;
Boolean x15;
Boolean x16;
} EvalAssignActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalAssignAction(LocationSet *dst, void *refcon) {
EvalAssignActionParams *params;
LocationSetSet *srcs;
IRO_ASSERT(4797, dst != NULL);
IRO_ASSERT(4798, refcon != NULL);
params = refcon;
IRO_ASSERT(4802, params->proc != NULL);
IRO_ASSERT(4802, params->ptf != NULL);
IRO_ASSERT(4803, params->nd != NULL);
IRO_ASSERT(4804, params->fnode != NULL);
IRO_ASSERT(4805, params->srcs != NULL);
srcs = params->srcs;
if (
!params->x14 ||
!LocationSetRepresentsSingleLocation(dst, params->proc, params->nd->pointsToFunction) ||
LocationIsVolatile(dst, params->proc) ||
LocationSet_sub_48AF30(dst)
) {
LocationSetSet *set = LocationSetSet_New();
LocationSetSet_Init(set);
params->x15 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, params->nd->pointsToFunction, 0, params->nd->rtype);
LocationSetSet_AddSet(srcs, set);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
params->x16 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode);
}
static Boolean EvalAssign(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) {
EvalAssignActionParams params;
EvalAssignAction2Params params2;
LocationSetSet *set;
LocationSet *tmp;
PAMemoryBlock *block;
Type *type;
IRO_ASSERT(4840, proc != NULL);
IRO_ASSERT(4841, nd != NULL);
IRO_ASSERT(4842, fnode != NULL);
IRO_ASSERT(4843, map != NULL);
IRO_ASSERT(4844, ptf != NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptf = ptf;
params.nd = nd;
params.fnode = fnode;
params.x15 = 0;
params.x16 = 0;
set = LocationSetSet_New();
params.srcs = LocationSetSet_New();
LocationSetSet_Init(set);
LocationSetSet_Init(params.srcs);
if (nd->type == IROLinearOp2Arg) {
IRO_ASSERT(4861, nd->u.diadic.left->type == IROLinearOp1Arg && nd->u.diadic.left->nodetype == EINDIRECT);
params.x15 |= EvalExpr(set, proc, nd->u.diadic.left->u.monadic, &stCallingContextStack, map, ptf);
AdjustTypesForVolatility(set, proc, nd->u.diadic.left);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.right, &stCallingContextStack, map, ptf);
if (nd->nodetype != EASS) {
switch (nd->nodetype) {
case EMULASS:
case EDIVASS:
case EMODASS:
case EADDASS:
case ESUBASS:
case ESHLASS:
case ESHRASS:
case EANDASS:
case EXORASS:
case EORASS:
if (
LocationSetSet_Count(params.srcs) == 1 &&
(tmp = LocationSetSet_FindFirst(params.srcs)) &&
!LocationSet_IsUnknown(tmp) &&
!LocationSet_stride(tmp) &&
(block = LocationSet_block(tmp)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT
) {
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
memset(&params2, 0, sizeof(params2));
params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block));
IRO_TruncateValueToType(&params2.x0, nd->u.diadic.right->rtype);
params2.nd = nd;
params2.xC = 0;
if (!CInt64_IsZero(&params2.x0)) {
LocationSetSet_ForEach(params.srcs, EvalAssignAction2, &params2);
if (params2.xC) {
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
if (!LocationSetSet_FindUnknown(params.srcs))
LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
}
}
} else {
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf);
if (!LocationSetSet_FindUnknown(params.srcs))
LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
}
break;
default:
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL);
break;
}
}
} else if (nd->type == IROLinearOp1Arg) {
IRO_ASSERT(4958, nd->u.monadic.left->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EINDIRECT);
params.x15 |= EvalExpr(set, proc, nd->u.monadic->u.monadic, &stCallingContextStack, map, ptf);
AdjustTypesForVolatility(set, proc, nd->u.monadic);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
switch (nd->nodetype) {
case EPOSTINC:
case EPOSTDEC:
case EPREINC:
case EPREDEC:
memset(&params2, 0, sizeof(params2));
params2.x0 = cint64_one;
params2.nd = nd;
params2.xC = 0;
type = NULL;
if (IS_TYPE_POINTER(nd->rtype))
type = TPTR_TARGET(nd->rtype);
else if (IS_TYPE_MEMBERPOINTER(nd->rtype))
type = TYPE_MEMBER_POINTER(nd->rtype)->ty1;
if (type)
CInt64_SetLong(&params2.x0, type->size);
if (!CInt64_IsZero(&params2.x0)) {
LocationSetSet_ForEach(params.srcs, EvalAssignAction2, &params2);
if (params2.xC) {
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
if (!LocationSetSet_FindUnknown(params.srcs))
LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one);
}
}
break;
default:
LocationSetSet_Term(params.srcs);
LocationSetSet_Init(params.srcs);
LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL);
break;
}
} else {
CError_FATAL(5006);
}
if (LocationSetSet_Count(params.srcs) != 0) {
PointsToFunction *pointsToFunc;
pointsToFunc = PointsToFunction_New();
if (nd->pointsToFunction)
PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
else
PointsToFunction_Init(pointsToFunc);
params.x14 = LocationSetSet_Count(set) == 1;
LocationSetSet_ForEach(set, EvalAssignAction, &params);
if (!params.x15 && params.x16) {
if (nd->pointsToFunction)
params.x15 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
else
params.x15 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
}
PointsToFunction_Term(pointsToFunc);
PointsToFunction_Delete(pointsToFunc);
}
LocationSetSet_Term(set);
LocationSetSet_Term(params.srcs);
LocationSetSet_Delete(set);
LocationSetSet_Delete(params.srcs);
return params.x15;
}
static Boolean EvalReturn(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) {
EvalAssignActionParams params;
LocationSet *loc;
IRO_ASSERT(5046, proc != NULL);
IRO_ASSERT(5047, nd != NULL);
IRO_ASSERT(5048, nd->type == IROLinearReturn);
IRO_ASSERT(5049, fnode != NULL);
IRO_ASSERT(5050, map != NULL);
IRO_ASSERT(5051, ptf != NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptf = ptf;
params.nd = nd;
params.fnode = fnode;
params.x15 = 0;
params.x16 = 0;
if (nd->u.monadic) {
params.srcs = LocationSetSet_New();
LocationSetSet_Init(params.srcs);
loc = PartialTransferFunction_returnLocation(ptf);
params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf);
if (LocationSetSet_Count(params.srcs) != 0) {
params.x14 = 1;
EvalAssignAction(loc, &params);
params.x15 |= params.x16;
}
LocationSetSet_Term(params.srcs);
LocationSetSet_Delete(params.srcs);
}
return params.x15;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct ApplySummaryActionParams {
ParamMappingFunction *tgtMap;
Object *proc;
IRONode *fnode;
IROLinear *nd;
PartialTransferFunction *ptf;
ParamMappingFunction *map;
LocationSet *loc;
LocationSetSet *locs;
Boolean x20;
Boolean x21;
Boolean x22;
} ApplySummaryActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void ApplySummaryAction2(ParamMapping *mapping, void *refcon) {
ApplySummaryActionParams *params;
PAMemoryBlock *block;
ExtendedParam *ep;
IROLinear *nd;
LocationSetSet *set;
EvalAssignActionParams assignParams;
IRO_ASSERT(5108, mapping != NULL);
IRO_ASSERT(5109, refcon != NULL);
params = refcon;
IRO_ASSERT(5113, params->tgtMap != NULL);
IRO_ASSERT(5114, params->proc != NULL);
IRO_ASSERT(5115, params->fnode != NULL);
IRO_ASSERT(5116, params->nd != NULL);
IRO_ASSERT(5117, params->nd->type == IROLinearFunccall);
IRO_ASSERT(5118, params->ptf != NULL);
IRO_ASSERT(5119, params->map != NULL);
IRO_ASSERT(5120, params->loc != NULL);
IRO_ASSERT(5121, params->locs != NULL);
block = LocationSet_block(params->loc);
IRO_ASSERT(5124, block != NULL);
IRO_ASSERT(5125, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM);
ep = PAMemoryBlock_thing(block);
IRO_ASSERT(5127, ep != NULL);
if (ParamMapping_extended(mapping) == ep && (nd = ParamMapping_actual(mapping))) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
params->x21 |= EvalExpr(set, params->proc, nd, &stCallingContextStack, params->map, params->ptf);
if (!LocationSetSet_FindUnknown(set)) {
CInt64 stride64;
CInt64 value;
value = LocationSet_field(params->loc);
LocationSetSet_ForEach(set, EvalExprAction, &value);
CInt64_SetULong(&stride64, LocationSet_stride(params->loc));
LocationSetSet_ForEach(set, EvalExprAction2, &stride64);
}
memset(&assignParams, 0, sizeof(assignParams));
assignParams.proc = params->proc;
assignParams.ptf = params->ptf;
assignParams.nd = params->nd;
assignParams.fnode = params->fnode;
assignParams.srcs = params->locs;
assignParams.x14 = params->x20 && (LocationSetSet_Count(set) == 1);
assignParams.x15 = 0;
assignParams.x16 = 0;
LocationSetSet_ForEach(set, EvalAssignAction, &assignParams);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
params->x21 |= assignParams.x15;
params->x22 |= assignParams.x16;
}
}
static void ApplySummaryAction(PointsToEntry *pte, void *refcon) {
ApplySummaryActionParams *params;
LocationSet *loc;
PAMemoryBlock *block;
IRO_ASSERT(5175, pte != NULL);
IRO_ASSERT(5176, refcon != NULL);
params = refcon;
IRO_ASSERT(5180, params->tgtMap != NULL);
IRO_ASSERT(5181, params->proc != NULL);
IRO_ASSERT(5182, params->fnode != NULL);
IRO_ASSERT(5183, params->nd != NULL);
IRO_ASSERT(5184, params->nd->type == IROLinearFunccall);
IRO_ASSERT(5185, params->ptf != NULL);
IRO_ASSERT(5186, params->map != NULL);
loc = PointsToEntry_loc(pte);
IRO_ASSERT(5189, loc != NULL);
IRO_ASSERT(5190, !LocationSet_IsUnknown(loc));
block = LocationSet_block(loc);
if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
params->loc = loc;
params->locs = PointsToEntry_locs(pte);
pmf_sub_487C70(params->tgtMap, ApplySummaryAction2, params);
}
}
static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag) {
Boolean result;
ApplySummaryActionParams params;
PointsToFunction *pointsToFunc;
IRO_ASSERT(5208, tgtPTF != NULL);
IRO_ASSERT(5209, tgtMap != NULL);
IRO_ASSERT(5210, proc != NULL);
IRO_ASSERT(5211, fnode != NULL);
IRO_ASSERT(5212, nd != NULL);
IRO_ASSERT(5213, nd->type == IROLinearFunccall);
IRO_ASSERT(5214, ptf != NULL);
IRO_ASSERT(5215, map != NULL);
StoreReturnedLocations(nd, tgtPTF, tgtMap);
if (tgtPTF == stUnknownPTF) {
result = KillAllAddressableLocations(proc, fnode, nd, ptf);
} else {
pointsToFunc = PointsToFunction_New();
if (nd->pointsToFunction)
PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction);
else
PointsToFunction_Init(pointsToFunc);
memset(&params, 0, sizeof(params));
params.tgtMap = tgtMap;
params.proc = proc;
params.fnode = fnode;
params.nd = nd;
params.ptf = ptf;
params.map = map;
params.loc = NULL;
params.locs = NULL;
params.x20 = flag;
params.x21 = 0;
params.x22 = 0;
PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(tgtPTF), ApplySummaryAction, &params);
result = params.x21;
if (!params.x21 && params.x22) {
if (nd->pointsToFunction)
result = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction);
else
result = PointsToFunction_FindFirst(pointsToFunc) != NULL;
}
}
return result;
}
static void GetPTFAction2(ParamMapping *mapping, void *refcon) {
IRO_ASSERT(5331, mapping != NULL);
if (ParamMapping_extended(mapping))
ParamMapping_SetExtended(mapping, NULL);
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct GetPTFActionParams {
ParamMappingFunction *map;
Object *proc;
IROLinear *nd;
PartialTransferFunction *ptf;
Boolean *needVisit;
PartialTransferFunction *x14;
PartialTransferFunction *x18;
} GetPTFActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void GetPTFAction(PartialTransferFunction *tgtPTF, void *refcon) {
GetPTFActionParams *params;
IRO_ASSERT(5359, tgtPTF != NULL);
IRO_ASSERT(5360, refcon != NULL);
params = refcon;
IRO_ASSERT(5364, params->map != NULL);
IRO_ASSERT(5365, params->proc != NULL);
IRO_ASSERT(5366, params->proc != &stUnknown);
IRO_ASSERT(5367, params->nd != NULL);
IRO_ASSERT(5368, params->ptf != NULL);
IRO_ASSERT(5369, params->needVisit != NULL);
if (!params->x18) {
if (MatchPTF(tgtPTF, params->proc, params->map, params->nd, params->ptf)) {
if (InputsHaveNewPointerValues(tgtPTF, params->ptf))
*params->needVisit = 1;
params->x18 = tgtPTF;
} else {
pmf_sub_487C70(params->map, GetPTFAction2, NULL);
if (PTF_sub_48B980(tgtPTF) == params->nd && PTF_sub_48B970(tgtPTF) == params->ptf)
params->x14 = tgtPTF;
}
}
}
static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit) {
PartialTransferFunction *found;
PartialTransferFunction *result;
GetPTFActionParams params;
IRO_ASSERT(5396, map != NULL);
IRO_ASSERT(5397, proc != NULL);
IRO_ASSERT(5398, nd != NULL);
IRO_ASSERT(5399, ptf != NULL);
IRO_ASSERT(5400, needVisit != NULL);
if (proc == &stUnknown) {
result = stUnknownPTF;
} else {
memset(&params, 0, sizeof(params));
params.map = map;
params.proc = proc;
params.nd = nd;
params.ptf = PartialTransferFunction_New();
PartialTransferFunction_Init(params.ptf, nd, ptf);
params.needVisit = needVisit;
params.x14 = NULL;
params.x18 = NULL;
if (!proc->u.func.ptfList) {
proc->u.func.ptfList = PTFList_New();
PTFList_Init(proc->u.func.ptfList);
}
PTFList_ForEach(proc->u.func.ptfList, GetPTFAction, &params);
found = params.x18;
if (found && !*needVisit) {
PartialTransferFunction_Copy(result = PartialTransferFunction_New(), found);
} else {
result = stUnknownPTF;
}
PartialTransferFunction_Term(params.ptf);
PartialTransferFunction_Delete(params.ptf);
}
return result;
}
static Boolean IsMeetNode(IRONode *fnode, IROLinear *nd) {
return (fnode->numpred > 1) && (fnode->first == nd);
}
static Boolean IsExitNode(Object *proc, IRONode *fnode) {
IRO_ASSERT(5467, proc != NULL);
IRO_ASSERT(5468, fnode != NULL);
return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom);
}
static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) {
UInt16 i;
IRO_ASSERT(5479, proc != NULL);
IRO_ASSERT(5480, fnode != NULL);
for (i = 0; i < fnode->numpred; i++) {
if (FunctionNodeTable(proc)[fnode->pred[i]]->x3C)
return 1;
}
return 0;
}
static Boolean AllPredecessorsHaveBeenVisited(Object *proc, IRONode *fnode) {
UInt16 i;
IRO_ASSERT(0, proc != NULL);
IRO_ASSERT(0, fnode != NULL);
for (i = 0; i < fnode->numpred; i++) {
if (!FunctionNodeTable(proc)[fnode->pred[i]]->x3C)
return 0;
}
return 1;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct EvalProcActionParams {
Object *proc;
IRONode *fnode;
PartialTransferFunction *ptf;
} EvalProcActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalProcAction2(PointsToEntry *pte, void *refcon) {
EvalProcActionParams *params;
LocationSet *dst;
PAMemoryBlock *block;
LocationSetSet *set;
IRONode *node;
IRO_ASSERT(5525, pte != NULL);
IRO_ASSERT(5526, refcon != NULL);
params = refcon;
IRO_ASSERT(5530, params->proc != NULL);
IRO_ASSERT(5531, params->fnode != NULL);
IRO_ASSERT(5532, params->ptf != NULL);
dst = PointsToEntry_loc(pte);
IRO_ASSERT(5535, dst != NULL);
IRO_ASSERT(5536, !LocationSet_IsUnknown(dst));
block = LocationSet_block(dst);
if (block && (LocationSet_sub_48AF30(dst) || PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM)) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
LocationSetSet_AddSet(set, PointsToEntry_locs(pte));
for (node = FunctionFirstNode(params->proc); node; node = node->nextnode) {
if (node->x3C && node != params->fnode && IsExitNode(params->proc, node)) {
if (node->last->pointsToFunction)
Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, node->last->pointsToFunction, 0, NULL);
}
}
Assign(params->ptf, dst, set, params->proc, NULL, NULL);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct AssignEachInPointsToFunctionActionParams {
Object *proc;
IROLinear *nd;
IRONode *fnode;
PartialTransferFunction *ptf;
Boolean x10;
} AssignEachInPointsToFunctionActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void AssignEachInPointsToFunctionAction(PointsToEntry *pte, void *refcon) {
AssignEachInPointsToFunctionActionParams *params;
LocationSet *dst;
LocationSetSet *srcs;
IRO_ASSERT(5577, pte != NULL);
IRO_ASSERT(5578, refcon != NULL);
params = refcon;
IRO_ASSERT(5582, params->proc != NULL);
IRO_ASSERT(5583, params->nd != NULL);
IRO_ASSERT(5584, params->fnode != NULL);
IRO_ASSERT(5585, params->ptf != NULL);
dst = PointsToEntry_loc(pte);
srcs = LocationSetSet_New();
LocationSetSet_Init(srcs);
LocationSetSet_AddSet(srcs, PointsToEntry_locs(pte));
params->x10 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode);
LocationSetSet_Term(srcs);
LocationSetSet_Delete(srcs);
}
static void AssignEachInPointsToFunction(PointsToFunction *pointsTo, void *refcon) {
AssignEachInPointsToFunctionActionParams *params;
PointsToFunction *pointsToFunc;
IRO_ASSERT(5602, pointsTo != NULL);
IRO_ASSERT(5603, refcon != NULL);
params = refcon;
IRO_ASSERT(5607, params->nd != NULL);
pointsToFunc = PointsToFunction_New();
if (params->nd->pointsToFunction)
PointsToFunction_Copy(pointsToFunc, params->nd->pointsToFunction);
else
PointsToFunction_Init(pointsToFunc);
if (PointsToFunction_FindFirst(pointsToFunc)) {
PointsToFunction_ForEach(pointsTo, AssignEachInPointsToFunctionAction, params);
} else {
if (!params->nd->pointsToFunction)
params->nd->pointsToFunction = PointsToFunction_New();
else
PointsToFunction_Term(params->nd->pointsToFunction);
PointsToFunction_Copy(params->nd->pointsToFunction, pointsTo);
params->x10 = 1;
}
if (params->x10) {
if (params->nd->pointsToFunction)
params->x10 = !PointsToFunctions_Equal(pointsToFunc, params->nd->pointsToFunction);
else
params->x10 = PointsToFunction_FindFirst(pointsToFunc) != NULL;
}
PointsToFunction_Term(pointsToFunc);
PointsToFunction_Delete(pointsToFunc);
}
static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj) {
ObjectList *list;
IRO_ASSERT(5643, proc != NULL);
IRO_ASSERT(5644, proc != &stUnknown);
IRO_ASSERT(5645, obj != NULL);
if (obj->datatype == DLOCAL) {
for (list = FunctionArguments(proc); list; list = list->next) {
if (obj == list->object)
return 1;
}
}
return 0;
}
static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj) {
ObjectList *list;
IRO_ASSERT(5661, proc != NULL);
IRO_ASSERT(5662, proc != &stUnknown);
IRO_ASSERT(5663, obj != NULL);
if (obj->datatype == DLOCAL && proc == cscope_currentfunc) {
for (list = arguments; list; list = list->next) {
if (obj == list->object)
return 1;
}
}
return 0;
}
static void AddLocalVarsAddressedByExceptionUses(Object *var) {
IRO_ASSERT(5699, var != NULL);
IRO_ASSERT(5700, stExceptionFNode != NULL);
IRO_ASSERT(5701, stExceptionFNode->addressed != NULL);
if (var->datatype == DLOCAL)
ObjectSet_sub_4867D0(stExceptionFNode->addressed, var);
}
static Boolean LinearNodeIsInFlowgraphNode(IROLinear *nd, IRONode *fnode) {
IROLinear *first;
IROLinear *last;
IROLinear *scan;
if (fnode && (first = fnode->first) && (last = fnode->last)) {
for (scan = first; scan && scan != last->next; scan = scan->next) {
if (scan == nd)
return 1;
}
}
return 0;
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
static struct {
Object *proc;
IRONode *fnode;
ParamMappingFunction *map;
PartialTransferFunction *ptf;
PointsToFunction *pointsToFunc;
Boolean *changed;
Boolean x18;
Boolean x19;
} stEvalProcActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void EvalProcAction(IROLinear *Int, Boolean flag) {
Boolean *changed;
Boolean result;
Object *proc;
PartialTransferFunction *ptf;
Boolean x18;
Boolean x19;
IRONode *fnode;
PointsToFunction *pointsToFunc;
ParamMappingFunction *map;
Object *obj;
AssignEachInPointsToFunctionActionParams params;
static int userBreakCounter;
if (!flag && !Int->x1E) {
IRO_ASSERT(5748, Int != NULL);
IRO_ASSERT(5749, stEvalProcActionParams.changed != NULL);
proc = stEvalProcActionParams.proc;
fnode = stEvalProcActionParams.fnode;
map = stEvalProcActionParams.map;
ptf = stEvalProcActionParams.ptf;
pointsToFunc = stEvalProcActionParams.pointsToFunc;
changed = stEvalProcActionParams.changed;
x18 = stEvalProcActionParams.x18;
x19 = stEvalProcActionParams.x19;
IRO_ASSERT(5760, proc != NULL);
IRO_ASSERT(5761, fnode != NULL);
IRO_ASSERT(5762, map != NULL);
IRO_ASSERT(5763, ptf != NULL);
if (++userBreakCounter > 40) {
IRO_CheckForUserBreak();
userBreakCounter = 0;
}
result = 0;
if (x19 && Int->pointsToFunction) {
PointsToFunction_Term(Int->pointsToFunction);
PointsToFunction_Delete(Int->pointsToFunction);
Int->pointsToFunction = NULL;
}
memset(&params, 0, sizeof(params));
params.proc = proc;
params.nd = Int;
params.fnode = fnode;
params.ptf = ptf;
params.x10 = 0;
if (x18) {
PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf);
if (fnode == FunctionFirstNode(proc) && initial) {
AssignEachInPointsToFunction(initial, &params);
result |= params.x10;
}
result |= EvalMeet(proc, fnode, Int, ptf);
pointsToFunc = Int->pointsToFunction;
x18 = 0;
} else if (!Int->pointsToFunction) {
if (pointsToFunc)
AssignEachInPointsToFunction(pointsToFunc, &params);
result |= params.x10;
pointsToFunc = Int->pointsToFunction;
}
if (IRO_IsAssignment(Int)) {
if (Int->flags & IROLF_4000)
longjmp(stAbortPointerAnalysis, 1);
result |= EvalAssign(proc, Int, fnode, map, ptf);
pointsToFunc = Int->pointsToFunction;
} else if (Int->type == IROLinearReturn) {
result |= EvalReturn(proc, Int, fnode, map, ptf);
pointsToFunc = Int->pointsToFunction;
} else if (Int->type == IROLinearFunccall) {
if (Int->flags & IROLF_4000)
longjmp(stAbortPointerAnalysis, 1);
if (Int->stmt && IRO_FunctionCallMightThrowException(Int)) {
stExceptionFNode = fnode;
IRO_WalkExcActions(Int->stmt->dobjstack, AddLocalVarsAddressedByExceptionUses);
}
result |= EvalCall(proc, fnode, Int, map, ptf);
pointsToFunc = Int->pointsToFunction;
} else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT && (!(Int->flags & IROLF_Assigned) || (Int->flags & IROLF_Used))) {
result |= EvalExpr(NULL, proc, Int, &stCallingContextStack, map, ptf);
} else if (Int->type == IROLinearOperand && !(Int->flags & IROLF_Ind) && Int->u.node->type == EOBJREF && (obj = Int->u.node->data.objref) && obj->datatype == DLOCAL) {
ObjectSet_sub_4867D0(fnode->addressed, obj);
} else if (Int->type == IROLinearAsm) {
IAEffects effects;
int i;
CodeGen_GetAsmEffects(Int->u.asm_stmt, &effects);
for (i = 0; i < effects.numoperands; i++) {
obj = effects.operands[i].object;
if (obj && obj->datatype == DLOCAL && effects.operands[i].type == IAEffect_3) {
ObjectSet_sub_4867D0(fnode->addressed, obj);
}
}
}
if (result && Int != fnode->last && fnode->last->pointsToFunction) {
PointsToFunction_Term(fnode->last->pointsToFunction);
PointsToFunction_Delete(fnode->last->pointsToFunction);
fnode->last->pointsToFunction = NULL;
}
*changed |= result;
x19 |= result;
stEvalProcActionParams.pointsToFunc = pointsToFunc;
stEvalProcActionParams.x18 = x18;
stEvalProcActionParams.x19 = x19;
Int->x1E = 1;
if (Int->type != IROLinearReturn) {
IROLinear *father = IRO_LocateFather(Int);
if (father && father->type == IROLinearReturn) {
if (LinearNodeIsInFlowgraphNode(father, fnode))
EvalProcAction(father, 0);
else
longjmp(stAbortPointerAnalysis, 1);
}
}
}
}
static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) {
IRONode *fnode;
IRONode *pred;
IROLinear *nd;
UInt32 passCount;
Boolean changed;
UInt16 i;
AssignEachInPointsToFunctionActionParams assignParams;
EvalProcActionParams params;
IRO_ASSERT(5964, proc != NULL);
IRO_ASSERT(5965, map != NULL);
IRO_ASSERT(5966, ptf != NULL);
for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode)
fnode->x3C = 0;
passCount = 0;
do {
clock();
changed = 0;
for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
if (fnode->last && ((fnode->numpred == 0) || SomePredecessorHasBeenVisited(proc, fnode))) {
clock();
if (!fnode->addressed) {
fnode->addressed = ObjectSet_New();
ObjectSet_Init(fnode->addressed);
}
for (i = 0; i < fnode->numpred; i++) {
pred = FunctionNodeTable(proc)[fnode->pred[i]];
if (pred->addressed)
ObjectSet_sub_48C590(fnode->addressed, pred->addressed);
}
memset(&stEvalProcActionParams, 0, sizeof(stEvalProcActionParams));
stEvalProcActionParams.proc = proc;
stEvalProcActionParams.fnode = fnode;
stEvalProcActionParams.map = map;
stEvalProcActionParams.ptf = ptf;
stEvalProcActionParams.pointsToFunc = NULL;
stEvalProcActionParams.changed = &changed;
stEvalProcActionParams.x18 = 1;
stEvalProcActionParams.x19 = 0;
for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next)
nd->x1E = 0;
IRO_WalkInts(fnode->first, fnode->last, EvalProcAction);
if (stEvalProcActionParams.x18 || !fnode->last->pointsToFunction) {
memset(&assignParams, 0, sizeof(assignParams));
assignParams.proc = proc;
assignParams.nd = fnode->last;
assignParams.fnode = fnode;
assignParams.ptf = ptf;
assignParams.x10 = 0;
if (stEvalProcActionParams.x18) {
PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf);
if (fnode == FunctionFirstNode(proc) && initial) {
AssignEachInPointsToFunction(initial, &assignParams);
changed |= assignParams.x10;
}
changed |= EvalMeet(proc, fnode, fnode->last, ptf);
stEvalProcActionParams.x18 = 0;
} else {
if (stEvalProcActionParams.pointsToFunc)
AssignEachInPointsToFunction(stEvalProcActionParams.pointsToFunc, &assignParams);
changed |= assignParams.x10;
}
}
fnode->x3C = 1;
clock();
}
}
clock();
if (++passCount > 32)
CError_FATAL(6072);
} while (changed);
if (passCount > stMaxPassCount)
stMaxPassCount = passCount;
PartialTransferFunction_sub_48A610(ptf, 1);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptf = ptf;
for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
if (fnode->x3C && IsExitNode(proc, fnode) && fnode->last->pointsToFunction) {
params.fnode = fnode;
PointsToFunction_ForEach(fnode->last->pointsToFunction, EvalProcAction2, &params);
}
}
}
static void PointerAnalysis_Init(void) {
stCallingContextStack = Stack_New();
Stack_Init(stCallingContextStack);
stUnknownPTF = PartialTransferFunction_New();
PartialTransferFunction_Init(stUnknownPTF, NULL, NULL);
stExtParamSet = AllocsExtParamSet_sub_4876C0();
InitsExtParamSet_sub_4876A0(stExtParamSet);
stPTFList = PTFList_New();
PTFList_Init(stPTFList);
}
static void CleanseLocationSet(LocationSet *loc, void *refcon) {
PAMemoryBlock *block;
PALocalVar *local;
IRO_ASSERT(6161, loc != NULL);
IRO_ASSERT(6162, refcon == NULL);
if (
!LocationSet_IsUnknown(loc) &&
(block = LocationSet_block(loc)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
(local = PAMemoryBlock_thing(block))
) {
PALocalVar_SetSth_sub_4847C0(local, NULL);
}
}
static void CleansePointsToEntry(PointsToEntry *pte, void *refcon) {
IRO_ASSERT(6177, pte != NULL);
IRO_ASSERT(6178, refcon == NULL);
CleanseLocationSet(PointsToEntry_loc(pte), NULL);
LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL);
}
static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) {
IRO_ASSERT(6187, ptf != NULL);
IRO_ASSERT(6188, refcon == NULL);
if (ptf != stUnknownPTF) {
PointsToFunction_ForEach(PartialTransferFunction_initialPointsToFn(ptf), CleansePointsToEntry, NULL);
PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(ptf), CleansePointsToEntry, NULL);
}
}
static void PointerAnalysis_TermAction3(ExtendedParam *ep) {
ExtendedParam_Term(ep);
ExtendedParam_Delete(ep);
}
static void PointerAnalysis_TermAction2(Object *obj, void *refcon) {
ObjectSet *objSet;
Object *proc;
ObjectList *list;
objSet = refcon;
if (!ObjectIsAnExtendedParamCandidate(obj)) {
if (
obj->datatype == DLOCAL &&
obj->u.var.info &&
(proc = obj->u.var.info->func) &&
ObjectIsAFunction(proc) &&
proc->u.func.argList
) {
for (list = proc->u.func.argList; list; list = list->next) {
if (obj == list->object)
break;
}
if (!list)
ObjectSet_sub_4867D0(objSet, obj);
} else {
ObjectSet_sub_4867D0(objSet, obj);
}
}
}
static void PointerAnalysis_TermAction1(ExtendedParam *ep, void *refcon) {
ObjectSet *objSet;
ObjectSet *epObjSet;
Object *obj;
objSet = ObjectSet_New();
ObjectSet_Init(objSet);
epObjSet = ExtendedParam_objectSet(ep);
obj = NULL;
ObjectSet_ForEach(epObjSet, FindGlobalObjectAction, &obj);
if (obj) {
ObjectSet_ForEach(epObjSet, PointerAnalysis_TermAction2, objSet);
if (ObjectSet_FindFirst(objSet))
EP_sub_48C850(ep, objSet);
}
ObjectSet_Term(objSet);
ObjectSet_Delete(objSet);
}
static void PointerAnalysis_Term(void) {
if (stExtParamSet) {
MaybeWalkExtParamSet_sub_48CBE0(stExtParamSet, PointerAnalysis_TermAction1, NULL);
TermsExtParamSet_sub_48CB00(stExtParamSet);
FreesExtParamSet_sub_48CAE0(stExtParamSet);
stExtParamSet = NULL;
}
if (stPTFList) {
PTFList_ForEach(stPTFList, PointerAnalysis_TermAction4, NULL);
PTFList_Term(stPTFList);
PTFList_Delete(stPTFList);
stPTFList = NULL;
}
PartialTransferFunction_Term(stUnknownPTF);
PartialTransferFunction_Delete(stUnknownPTF);
stUnknownPTF = NULL;
Stack_Term(&stCallingContextStack);
Stack_Delete(stCallingContextStack);
stCallingContextStack = NULL;
}
static void InvalidatePointsToFunctions(Object *proc) {
IRONode *fnode;
IROLinear *nd;
IRO_ASSERT(6302, proc != NULL);
for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) {
if (fnode->last) {
if (fnode->addressed) {
ObjectSet_Term(fnode->addressed);
ObjectSet_Delete(fnode->addressed);
fnode->addressed = NULL;
}
for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) {
if (nd->pointsToFunction) {
PointsToFunction_Term(nd->pointsToFunction);
PointsToFunction_Delete(nd->pointsToFunction);
nd->pointsToFunction = NULL;
}
}
}
}
}
static void InitialSetup(void) {
}
static void PointerAnalysis_HeapErrorProc(void) {
longjmp(stAbortPointerAnalysis, 2);
}
void PointerAnalysis_Setup(void) {
IRO_InitializeAllocator();
stExtendedParamNum = 0;
stParamObjs = NULL;
stMaxPassCount = 0;
}
void PointerAnalysis_Cleanup(void) {
ObjectList *list;
ObjectList *next;
for (list = stParamObjs; list; list = next) {
IRO_free(list->object);
next = list->next;
IRO_free(list);
}
stParamObjs = NULL;
IRO_TerminateAllocator();
}
void IRO_AnalyzePointers(Object *function) {
EvalCallActionParams params;
IROLinear nd;
IRONode fnode;
int code;
volatile heaperror_t saveheaperror;
IRO_ASSERT(6393, function != NULL);
PointerAnalysis_Init();
memset(&params, 0, sizeof(params));
memset(&nd, 0, sizeof(nd));
nd.type = IROLinearFunccall;
memset(&fnode, 0, sizeof(fnode));
params.proc = &stUnknown;
params.fnode = &fnode;
params.nd = &nd;
params.ptf = stUnknownPTF;
params.map = NULL;
params.x18 = 0;
params.x19 = 0;
params.x1A = 1;
stCurrentProc = FindMainEntryPoint(function);
if ((code = setjmp(stAbortPointerAnalysis)) == 0) {
saveheaperror = getheaperror();
setheaperror(PointerAnalysis_HeapErrorProc);
InitialSetup();
EvalCallAction(stCurrentProc, &params);
PointerAnalysis_Term();
stCurrentProc = NULL;
setheaperror(saveheaperror);
} else {
setheaperror(saveheaperror);
InvalidatePointsToFunctions(stCurrentProc);
PointerAnalysis_Term();
stCurrentProc = NULL;
if (code == 2 && saveheaperror)
saveheaperror();
}
}
static void RemoveRestrictedExtendedParamsAction(LocationSet *ls, void *refcon) {
LocationSetSet *locs;
PAMemoryBlock *block;
ExtendedParam *ep;
ObjectSet *objSet;
Object *obj;
locs = refcon;
if (
!LocationSet_IsUnknown(ls) &&
(block = LocationSet_block(ls)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
(ep = PAMemoryBlock_thing(block))
) {
objSet = ExtendedParam_objectSet(ep);
if (
ObjectSet_Count(objSet) == 1 &&
(obj = ObjectSet_FindFirst(objSet)) &&
ObjectIsRestrictQualified(obj)
) {
LocationSetSet_Add(locs, ls);
}
}
}
static void RemoveRestrictedExtendedParams(LocationSetSet *locs) {
LocationSetSet *set;
set = LocationSetSet_New();
LocationSetSet_Init(set);
LocationSetSet_ForEach(locs, RemoveRestrictedExtendedParamsAction, set);
LocationSetSet_sub_488700(locs, set);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2) {
LocationSetSet *lss1;
LocationSetSet *lss2;
PointsToFunction *pointsTo1;
PointsToFunction *pointsTo2;
PointsToFunction *savePointsTo1;
PointsToFunction *savePointsTo2;
FindAliasingParams params;
pointsTo1 = nd1->pointsToFunction;
pointsTo2 = nd2->pointsToFunction;
if (!pointsTo1)
pointsTo1 = pointsTo2;
if (!pointsTo2)
pointsTo2 = pointsTo1;
if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype))
return 0;
if (!pointsTo1 || !pointsTo2)
return 1;
lss1 = LocationSetSet_New();
LocationSetSet_Init(lss1);
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
savePointsTo1 = nd1->pointsToFunction;
nd1->pointsToFunction = pointsTo1;
EvalExpr(lss1, proc, nd1, NULL, NULL, NULL);
nd1->pointsToFunction = savePointsTo1;
savePointsTo2 = nd2->pointsToFunction;
nd2->pointsToFunction = pointsTo2;
EvalExpr(lss2, proc, nd2, NULL, NULL, NULL);
nd2->pointsToFunction = savePointsTo2;
memset(&params, 0, sizeof(params));
params.x8 = 0;
params.x0 = lss2;
LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
if (!params.x8) {
params.x0 = lss1;
LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
if (!params.x8) {
RemoveRestrictedExtendedParams(lss1);
RemoveRestrictedExtendedParams(lss2);
ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1);
ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2);
params.x0 = lss2;
LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
if (!params.x8) {
params.x0 = lss1;
LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
}
}
}
LocationSetSet_Term(lss1);
LocationSetSet_Delete(lss1);
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
return params.x8;
}
Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2) {
LocationSetSet *lss1;
LocationSetSet *lss2;
PointsToFunction *pointsTo1;
PointsToFunction *pointsTo2;
PointsToFunction *savePointsTo1;
PointsToFunction *savePointsTo2;
FindAliasingParams params;
pointsTo1 = nd1->pointsTo;
pointsTo2 = nd2->pointsTo;
if (!pointsTo1)
pointsTo1 = pointsTo2;
if (!pointsTo2)
pointsTo2 = pointsTo1;
if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype))
return 0;
if (!pointsTo1 || !pointsTo2)
return 1;
lss1 = LocationSetSet_New();
LocationSetSet_Init(lss1);
lss2 = LocationSetSet_New();
LocationSetSet_Init(lss2);
savePointsTo1 = nd1->pointsTo;
nd1->pointsTo = pointsTo1;
EvalENodeExpr(lss1, proc, nd1, NULL, NULL, NULL);
nd1->pointsTo = savePointsTo1;
savePointsTo2 = nd2->pointsTo;
nd2->pointsTo = pointsTo2;
EvalENodeExpr(lss2, proc, nd2, NULL, NULL, NULL);
nd2->pointsTo = savePointsTo2;
memset(&params, 0, sizeof(params));
params.x8 = 0;
params.x0 = lss2;
LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
if (!params.x8) {
params.x0 = lss1;
LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
if (!params.x8) {
RemoveRestrictedExtendedParams(lss1);
RemoveRestrictedExtendedParams(lss2);
ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1);
ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2);
params.x0 = lss2;
LocationSetSet_ForEach(lss1, FindAliasingAction, &params);
if (!params.x8) {
params.x0 = lss1;
LocationSetSet_ForEach(lss2, FindAliasingAction, &params);
}
}
}
LocationSetSet_Term(lss1);
LocationSetSet_Delete(lss1);
LocationSetSet_Term(lss2);
LocationSetSet_Delete(lss2);
return params.x8;
}
Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd) {
LocationSetSet *lss;
LocationSet *loc;
Boolean result;
if (!nd->pointsToFunction)
return 0;
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
EvalExpr(lss, proc, nd, NULL, NULL, NULL);
result =
(LocationSetSet_Count(lss) == 1) &&
(loc = LocationSetSet_FindFirst(lss)) &&
LocationSetRepresentsSingleLocation(loc, NULL, NULL);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
return result;
}
Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd) {
LocationSetSet *lss;
LocationSet *loc;
Boolean result;
if (!nd->pointsTo)
return 0;
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
EvalENodeExpr(lss, proc, nd, NULL, NULL, NULL);
result =
(LocationSetSet_Count(lss) == 1) &&
(loc = LocationSetSet_FindFirst(lss)) &&
LocationSetRepresentsSingleLocation(loc, NULL, NULL);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
return result;
}
Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo) {
LocationSetSet *lss;
LocationSet *loc;
Boolean result;
if (!pointsTo)
return 0;
lss = LocationSetSet_New();
LocationSetSet_Init(lss);
EvalVariable(lss, proc, var, pointsTo, NULL, NULL, NULL);
result =
(LocationSetSet_Count(lss) == 1) &&
(loc = LocationSetSet_FindFirst(lss)) &&
LocationSetRepresentsSingleLocation(loc, NULL, NULL);
LocationSetSet_Term(lss);
LocationSetSet_Delete(lss);
return result;
}
static void FindGlobalObjectAction(Object *object, void *refcon) {
if (ObjectIsAnExtendedParamCandidate(object)) {
Object **ptr = refcon;
*ptr = object;
}
}
static void GetDefiniteObjectOfExtendedParamLoc(LocationSet *loc, Object **resultObj, CInt64 *resultField) {
Object *obj;
CInt64 field;
PAMemoryBlock *block;
ExtendedParam *ep;
ObjectSet *objSet;
LocationSetSet *locs;
LocationSet *tmp;
PALocalVar *local;
IRO_ASSERT(6763, loc != NULL);
IRO_ASSERT(6764, resultObj != NULL);
IRO_ASSERT(6765, resultField != NULL);
obj = NULL;
field = LocationSet_field(loc);
block = LocationSet_block(loc);
if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) {
IRO_ASSERT(6777, obj == NULL);
ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
}
}
if (!obj) {
locs = LocationSetSet_New();
LocationSetSet_Init(locs);
GetActualLocsOfExtendedParam(locs, loc, NULL, &stCallingContextStack, NULL, 0);
if (
LocationSetSet_Count(locs) == 1 &&
(tmp = LocationSetSet_FindFirst(locs)) &&
!LocationSet_IsUnknown(tmp))
{
field = CInt64_Add(field, LocationSet_field(tmp));
if (
(block = LocationSet_block(tmp)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM &&
(ep = PAMemoryBlock_thing(block)) &&
(objSet = ExtendedParam_objectSet(ep))
)
{
IRO_ASSERT(6801, obj == NULL);
ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
} else if (
(block = LocationSet_block(tmp)) &&
PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR &&
(local = PAMemoryBlock_thing(block))
)
{
obj = GetLocalObject(local, &stUnknown, 0);
}
}
LocationSetSet_Term(locs);
LocationSetSet_Delete(locs);
}
*resultObj = obj;
*resultField = field;
}
static void CreateExpressionForLocationSet(LocationSet *loc, IROList *list, Type *rtype, Object *proc) {
CInt64 field;
PAMemoryBlock *block;
PAMemoryBlockKind kind;
void *thing;
IROLinear *nd;
Object *obj;
IRO_ASSERT(6833, loc != NULL);
IRO_ASSERT(6834, !LocationSet_IsUnknown(loc));
IRO_ASSERT(6835, LocationSet_stride(loc) == 0);
IRO_ASSERT(6836, list != NULL);
IRO_ASSERT(6837, rtype != NULL);
IRO_ASSERT(6838, proc != NULL);
field = LocationSet_field(loc);
block = LocationSet_block(loc);
kind = PAMemoryBlock_kind(block);
thing = PAMemoryBlock_thing(block);
nd = NULL;
switch (kind) {
case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field);
if (obj) {
nd = IRO_NewLinear(IROLinearOperand);
nd->u.node = create_objectrefnode(obj);
nd->rtype = rtype;
nd->index = ++IRO_NumLinear;
IRO_AddToList(nd, list);
}
break;
case PAMEMORYBLOCKKIND_LOCALVAR:
obj = GetLocalObject(thing, proc, 0);
if (obj) {
if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj)
obj = obj->u.var.realObj;
nd = IRO_NewLinear(IROLinearOperand);
nd->u.node = create_objectrefnode(obj);
nd->rtype = rtype;
nd->index = ++IRO_NumLinear;
IRO_AddToList(nd, list);
}
break;
case PAMEMORYBLOCKKIND_INT:
if (IS_TYPE_INT(rtype)) {
nd = IRO_NewIntConst(*((CInt64 *) thing), rtype);
IRO_AddToList(nd, list);
}
break;
case PAMEMORYBLOCKKIND_6:
break;
default:
CError_FATAL(6894);
}
if (nd && !CInt64_IsZero(&field)) {
IROLinear *nd2;
IROLinear *nd3;
nd2 = IRO_NewIntConst(field, TYPE(&stunsignedlong));
IRO_AddToList(nd2, list);
nd3 = IRO_NewLinear(IROLinearOp2Arg);
nd3->nodetype = EADD;
nd3->index = ++IRO_NumLinear;
nd3->rtype = rtype;
nd3->u.diadic.left = nd;
nd3->u.diadic.right = nd2;
IRO_AddToList(nd3, list);
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct LookupLinearExprActionParams {
Object *proc;
Type *indirectType;
IROListNode **list;
} LookupLinearExprActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void LookupLinearExprAction(LocationSet *loc, void *refcon) {
LookupLinearExprActionParams *params;
IROListNode *list;
IRO_ASSERT(6926, loc != NULL);
IRO_ASSERT(6927, refcon != NULL);
params = refcon;
IRO_ASSERT(6931, params->proc != NULL);
IRO_ASSERT(6932, params->indirectType != NULL);
IRO_ASSERT(6933, params->list != NULL);
list = *params->list = IRO_malloc(sizeof(IROListNode));
IRO_InitList(&list->list);
list->nextList = NULL;
if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL))
CreateExpressionForLocationSet(loc, &list->list, params->indirectType, params->proc);
params->list = &list->nextList;
}
void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list) {
LocationSetSet *set;
LookupLinearExprActionParams params;
IRO_ASSERT(6957, indirect != NULL);
if (indirect->pointsToFunction) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
EvalExpr(set, proc, indirect, NULL, NULL, NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.indirectType = indirect->rtype;
params.list = list;
LocationSetSet_ForEach(set, LookupLinearExprAction, &params);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
static void CreateENodeForLocationSet(LocationSet *loc, ENode **resultNode, Type *rtype, Object *proc) {
CInt64 field;
PAMemoryBlock *block;
PAMemoryBlockKind kind;
void *thing;
ENode *nd;
Object *obj;
IRO_ASSERT(0, loc != NULL);
IRO_ASSERT(0, !LocationSet_IsUnknown(loc));
IRO_ASSERT(0, LocationSet_stride(loc) == 0);
IRO_ASSERT(0, resultNode != NULL);
IRO_ASSERT(0, rtype != NULL);
IRO_ASSERT(0, proc != NULL);
field = LocationSet_field(loc);
block = LocationSet_block(loc);
kind = PAMemoryBlock_kind(block);
thing = PAMemoryBlock_thing(block);
nd = NULL;
switch (kind) {
case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field);
if (obj) {
nd = create_objectrefnode(obj);
nd->rtype = rtype;
}
break;
case PAMEMORYBLOCKKIND_LOCALVAR:
obj = GetLocalObject(thing, proc, 0);
if (obj) {
if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj)
obj = obj->u.var.realObj;
nd = create_objectrefnode(obj);
nd->rtype = rtype;
}
break;
case PAMEMORYBLOCKKIND_INT:
if (IS_TYPE_INT(rtype)) {
nd = IRO_NewENode(EINTCONST);
nd->data.intval = *((CInt64 *) thing);
nd->rtype = rtype;
}
break;
case PAMEMORYBLOCKKIND_6:
break;
default:
CError_FATAL(7040);
}
if (nd && !CInt64_IsZero(&field)) {
ENode *nd2;
ENode *nd3;
nd2 = IRO_NewENode(EINTCONST);
nd2->data.intval = field;
nd2->rtype = TYPE(&stunsignedlong);
nd3 = IRO_NewENode(EADD);
nd3->data.diadic.left = nd;
nd3->data.diadic.right = nd2;
nd3->rtype = rtype;
*resultNode = nd3;
} else {
*resultNode = nd;
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct LookupENodeExprActionParams {
Object *proc;
Type *indirectType;
ENodeList **list;
} LookupENodeExprActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void LookupENodeExprAction(LocationSet *loc, void *refcon) {
LookupENodeExprActionParams *params;
ENodeList *list;
IRO_ASSERT(0, loc != NULL);
IRO_ASSERT(0, refcon != NULL);
params = refcon;
IRO_ASSERT(0, params->proc != NULL);
IRO_ASSERT(0, params->indirectType != NULL);
IRO_ASSERT(0, params->list != NULL);
list = *params->list = IRO_malloc(sizeof(ENodeList));
list->node = NULL;
list->next = NULL;
if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL))
CreateENodeForLocationSet(loc, &list->node, params->indirectType, params->proc);
params->list = &list->next;
}
void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list) {
LocationSetSet *set;
LookupENodeExprActionParams params;
IRO_ASSERT(0, indirect != NULL);
if (indirect->pointsTo) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
EvalENodeExpr(set, proc, indirect, NULL, NULL, NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.indirectType = indirect->rtype;
params.list = list;
LocationSetSet_ForEach(set, LookupENodeExprAction, &params);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROListNode **list) {
LocationSetSet *set;
LookupLinearExprActionParams params;
if (pointsTo) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.indirectType = var->object->type;
params.list = list;
LocationSetSet_ForEach(set, LookupLinearExprAction, &params);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list) {
LocationSetSet *set;
LookupENodeExprActionParams params;
if (pointsTo) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL);
memset(&params, 0, sizeof(params));
params.proc = proc;
params.indirectType = var->object->type;
params.list = list;
LocationSetSet_ForEach(set, LookupENodeExprAction, &params);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct GetFunctionDepsOrKillsActionParams {
Object *proc;
PartialTransferFunction *ptf;
IROLinear *funccall;
ParamMappingFunction *map;
ObjectList **list;
} GetFunctionDepsOrKillsActionParams;
#ifdef __MWERKS__
#pragma options align=reset
#endif
static void GetFunctionDepsOrKillsAction(LocationSet *ls, void *refcon) {
GetFunctionDepsOrKillsActionParams *params;
ObjectList *list;
PAMemoryBlock *block;
ExtendedParam *ep;
ObjectSet *objSet;
PALocalVar *local;
Object *obj;
IRO_ASSERT(7204, ls != NULL);
IRO_ASSERT(7205, refcon != NULL);
params = refcon;
IRO_ASSERT(7209, params->proc != NULL);
IRO_ASSERT(7210, params->ptf != NULL);
IRO_ASSERT(7211, params->funccall != NULL);
IRO_ASSERT(7212, params->map == NULL || params->map != NULL);
IRO_ASSERT(7213, params->list != NULL);
list = *params->list = IRO_malloc(sizeof(ObjectList));
list->object = NULL;
list->next = NULL;
if (!LocationSet_IsUnknown(ls) && (block = LocationSet_block(ls))) {
obj = NULL;
switch (PAMemoryBlock_kind(block)) {
case PAMEMORYBLOCKKIND_EXTENDEDPARAM:
if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) {
IRO_ASSERT(7232, obj == NULL);
ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj);
}
break;
case PAMEMORYBLOCKKIND_LOCALVAR:
if ((local = PAMemoryBlock_thing(block))) {
obj = GetLocalObject(local, &stUnknown, 0);
if (ObjectIsAFunctionArgument(FunctionName, obj) && obj->u.var.realObj)
obj = obj->u.var.realObj;
}
break;
}
list->object = obj;
}
params->list = &list->next;
}
static void GetFunctionDepsOrKillsAction2(PointsToEntry *pte, void *refcon) {
GetFunctionDepsOrKillsActionParams *params;
LocationSet *loc;
PAMemoryBlock *block;
LocationSetSet *set;
IRO_ASSERT(7264, pte != NULL);
IRO_ASSERT(7265, refcon != NULL);
params = refcon;
IRO_ASSERT(7269, params->proc != NULL);
IRO_ASSERT(7270, params->ptf != NULL);
IRO_ASSERT(7271, params->funccall != NULL);
IRO_ASSERT(7272, params->map != NULL);
IRO_ASSERT(7273, params->list != NULL);
loc = PointsToEntry_loc(pte);
IRO_ASSERT(7277, !LocationSet_IsUnknown(loc));
if ((block = LocationSet_block(loc)) && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) {
set = LocationSetSet_New();
LocationSetSet_Init(set);
GetActualLocsOfExtendedParam(set, loc, NULL, &stCallingContextStack, params->map, 0);
LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, params);
LocationSetSet_Term(set);
LocationSetSet_Delete(set);
}
}
static void CreateFalseContext(Object *proc, IROLinear *funccall, PartialTransferFunction **resultPTF, ParamMappingFunction **resultMap) {
IROLinear myFunccall;
Boolean needVisit;
ParamMappingFunction *map;
PartialTransferFunction *ptf;
StackElement *stackElement;
ParamMappingFunction *map2;
PartialTransferFunction *ptf2;
StackElement *stackElement2;
PointerAnalysis_Init();
memset(&myFunccall, 0, sizeof(myFunccall));
myFunccall.type = IROLinearFunccall;
map = ParamMappingFunction_New();
ParamMappingFunction_Init(map);
RecordActuals(&myFunccall, FunctionName, map);
needVisit = 0;
ptf = GetPTF(map, FunctionName, &myFunccall, stUnknownPTF, &needVisit);
stackElement = StackElement_New();
StackElement_Init(stackElement, FunctionName, ptf, map, &myFunccall);
Stack_sub_48A660(&stCallingContextStack, stackElement);
StackElement_Term(stackElement);
StackElement_Delete(stackElement);
map2 = ParamMappingFunction_New();
ParamMappingFunction_Init(map2);
RecordActuals(funccall, proc, map2);
if (FunctionName != proc) {
needVisit = 0;
ptf2 = GetPTF(map2, proc, funccall, ptf, &needVisit);
stackElement2 = StackElement_New();
StackElement_Init(stackElement2, proc, ptf2, map2, funccall);
Stack_sub_48A660(&stCallingContextStack, stackElement2);
StackElement_Term(stackElement2);
StackElement_Delete(stackElement2);
} else {
ptf2 = stUnknownPTF;
}
*resultPTF = ptf2;
*resultMap = map2;
}
static void DestroyFalseContext(Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map) {
StackElement *element;
if (FunctionName != proc) {
element = Stack_sub_48A5B0(&stCallingContextStack);
StackElement_Term(element);
StackElement_Delete(element);
}
ParamMappingFunction_Term(map);
ParamMappingFunction_Delete(map);
element = Stack_sub_48A5B0(&stCallingContextStack);
map = StackElement_map(element);
ParamMappingFunction_Term(map);
ParamMappingFunction_Delete(map);
StackElement_Term(element);
StackElement_Delete(element);
PointerAnalysis_Term();
}
void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list) {
Boolean fail;
PartialTransferFunction *ptf;
LocationSetSet *set;
GetFunctionDepsOrKillsActionParams params;
IRO_ASSERT(7398, proc != NULL);
IRO_ASSERT(7399, funccall != NULL);
IRO_ASSERT(7400, funccall->type == IROLinearFunccall);
if (!ObjectIsAFunction(proc))
return;
fail = !proc->u.func.ptfList || !(ptf = PTFList_FindFirst(proc->u.func.ptfList));
if (!fail) {
fail = !(set = PTF_sub_48D750(ptf));
if (!fail) {
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptf = ptf;
params.funccall = funccall;
params.map = NULL;
params.list = list;
LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, &params);
}
}
if (fail) {
*list = IRO_malloc(sizeof(ObjectList));
(*list)->object = NULL;
(*list)->next = NULL;
}
}
void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list) {
Boolean fail;
PartialTransferFunction *ptf;
ParamMappingFunction *map;
PointsToFunction *finalPointsTo;
GetFunctionDepsOrKillsActionParams params;
IRO_ASSERT(7446, proc != NULL);
IRO_ASSERT(7447, funccall != NULL);
IRO_ASSERT(7448, funccall->type == IROLinearFunccall);
if (!ObjectIsAFunction(proc))
return;
fail = !proc->u.func.ptfList || !PTFList_FindFirst(proc->u.func.ptfList);
if (!fail) {
CreateFalseContext(proc, funccall, &ptf, &map);
fail = !ptf || !map || !(finalPointsTo = PartialTransferFunction_finalPointsToFn(ptf));
if (!fail) {
memset(&params, 0, sizeof(params));
params.proc = proc;
params.ptf = ptf;
params.funccall = funccall;
params.map = map;
params.list = list;
PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, &params);
}
DestroyFalseContext(proc, ptf, map);
}
if (fail) {
*list = IRO_malloc(sizeof(ObjectList));
(*list)->object = NULL;
(*list)->next = NULL;
}
}
void PointerAnalysis_PragmaMode(void) {
if (cparamblkptr->isPreprocessing) {
skipendofline();
return;
}
if (notendofline()) {
if (plex() == TK_IDENTIFIER) {
if (!strcmp(tkidentifier->name, "addr")) {
copts.opt_pointer_analysis_mode = 0;
return;
}
if (!strcmp(tkidentifier->name, "ansi")) {
copts.opt_pointer_analysis_mode = 1;
return;
}
if (!strcmp(tkidentifier->name, "type")) {
copts.opt_pointer_analysis_mode = 2;
return;
}
}
CPrep_Warning(CErrorStr105);
skipendofline();
return;
}
if (copts.warn_illpragma)
CPrep_Warning(CErrorStr186);
skipendofline();
}
typedef enum CreateNewParamObjects {
CREATE_NEW_PARAM_OBJECTS_FALSE,
CREATE_NEW_PARAM_OBJECTS_TRUE
} CreateNewParamObjects;
static void ParseLocationSet(LocationSet *loc, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean arg5, int arg6, Boolean *arg7, Boolean *resultFailed) {
CInt64 field;
UInt32 stride;
PAMemoryBlock *block;
PAMemoryBlock *restriction;
Boolean failed;
Boolean flag37;
Boolean epFlag;
Boolean anotherFlag;
Boolean isUnknown;
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(%ld)", 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);
}
}