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