mirror of https://git.wuffs.org/MWCC
1431 lines
46 KiB
C
1431 lines
46 KiB
C
#include "compiler/IroVars.h"
|
|
#include "compiler/IroDump.h"
|
|
#include "compiler/IroFlowgraph.h"
|
|
#include "compiler/IroJump.h"
|
|
#include "compiler/IroLinearForm.h"
|
|
#include "compiler/IroMalloc.h"
|
|
#include "compiler/IroPointerAnalysis.h"
|
|
#include "compiler/IroUtil.h"
|
|
#include "compiler/IROUseDef.h"
|
|
#include "compiler/CClass.h"
|
|
#include "compiler/CError.h"
|
|
#include "compiler/CExpr.h"
|
|
#include "compiler/CFunc.h"
|
|
#include "compiler/CParser.h"
|
|
#include "compiler/CompilerTools.h"
|
|
#include "compiler/Exceptions.h"
|
|
#include "compiler/objects.h"
|
|
#include "compiler/InlineAsm.h"
|
|
#include "compiler/InlineAsmPPC.h"
|
|
#include "compiler/BitVector.h"
|
|
|
|
#ifdef __MWERKS__
|
|
#pragma options align=mac68k
|
|
#endif
|
|
typedef struct IndirectRecordMatch {
|
|
IROLinear *nd;
|
|
struct IndirectRecordMatch *otherMatches;
|
|
} IndirectRecordMatch;
|
|
|
|
typedef struct IndirectRecord {
|
|
IROLinear *linear;
|
|
unsigned char flags;
|
|
VarRecord *var;
|
|
SInt32 addend;
|
|
SInt32 size;
|
|
int startbit;
|
|
int endbit;
|
|
Type *type;
|
|
struct IndirectRecord *next;
|
|
IndirectRecordMatch *matches;
|
|
IROLinear *x26;
|
|
} IndirectRecord;
|
|
#ifdef __MWERKS__
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
static IndirectRecord *IRO_FirstIndirectRecord;
|
|
static IndirectRecord *IRO_LastIndirectRecord;
|
|
static IROLinear *TheBaseTerm;
|
|
VarRecord *IRO_FirstVar;
|
|
VarRecord *IRO_LastVar;
|
|
SInt32 IRO_NumVars;
|
|
Boolean IRO_IsBitField;
|
|
SInt32 IRO_BaseTerms;
|
|
SInt32 IRO_VarTerms;
|
|
Boolean IRO_IsModifyOp[MAXEXPR];
|
|
Boolean IRO_IsAssignOp[MAXEXPR];
|
|
|
|
// forward decls
|
|
static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag);
|
|
static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type);
|
|
static void DisableEntries(IndirectRecord *irec);
|
|
static void DisableAddressedEntries(void);
|
|
static UInt32 ObjectIsArg(Object *obj);
|
|
|
|
void IRO_InitializeIRO_IsModifyOpArray(void) {
|
|
int i;
|
|
|
|
for (i = 0; i < MAXEXPR; i++)
|
|
IRO_IsModifyOp[i] = 0;
|
|
|
|
IRO_IsModifyOp[EPOSTINC] = 1;
|
|
IRO_IsModifyOp[EPOSTDEC] = 1;
|
|
IRO_IsModifyOp[EPREINC] = 1;
|
|
IRO_IsModifyOp[EPREDEC] = 1;
|
|
IRO_IsModifyOp[EINDIRECT] = 0;
|
|
IRO_IsModifyOp[EMONMIN] = 0;
|
|
IRO_IsModifyOp[EBINNOT] = 0;
|
|
IRO_IsModifyOp[ELOGNOT] = 0;
|
|
IRO_IsModifyOp[EFORCELOAD] = 0;
|
|
IRO_IsModifyOp[EMUL] = 0;
|
|
IRO_IsModifyOp[EMULV] = 0;
|
|
IRO_IsModifyOp[EDIV] = 0;
|
|
IRO_IsModifyOp[EMODULO] = 0;
|
|
IRO_IsModifyOp[EADDV] = 0;
|
|
IRO_IsModifyOp[ESUBV] = 0;
|
|
IRO_IsModifyOp[EADD] = 0;
|
|
IRO_IsModifyOp[ESUB] = 0;
|
|
IRO_IsModifyOp[ESHL] = 0;
|
|
IRO_IsModifyOp[ESHR] = 0;
|
|
IRO_IsModifyOp[ELESS] = 0;
|
|
IRO_IsModifyOp[EGREATER] = 0;
|
|
IRO_IsModifyOp[ELESSEQU] = 0;
|
|
IRO_IsModifyOp[EGREATEREQU] = 0;
|
|
IRO_IsModifyOp[EEQU] = 0;
|
|
IRO_IsModifyOp[ENOTEQU] = 0;
|
|
IRO_IsModifyOp[EAND] = 0;
|
|
IRO_IsModifyOp[EXOR] = 0;
|
|
IRO_IsModifyOp[EOR] = 0;
|
|
IRO_IsModifyOp[ELAND] = 0;
|
|
IRO_IsModifyOp[ELOR] = 0;
|
|
IRO_IsModifyOp[EASS] = 0;
|
|
IRO_IsModifyOp[EMULASS] = 1;
|
|
IRO_IsModifyOp[EDIVASS] = 1;
|
|
IRO_IsModifyOp[EMODASS] = 1;
|
|
IRO_IsModifyOp[EADDASS] = 1;
|
|
IRO_IsModifyOp[ESUBASS] = 1;
|
|
IRO_IsModifyOp[ESHLASS] = 1;
|
|
IRO_IsModifyOp[ESHRASS] = 1;
|
|
IRO_IsModifyOp[EANDASS] = 1;
|
|
IRO_IsModifyOp[EXORASS] = 1;
|
|
IRO_IsModifyOp[EORASS] = 1;
|
|
IRO_IsModifyOp[ECOMMA] = 0;
|
|
IRO_IsModifyOp[EPMODULO] = 1;
|
|
IRO_IsModifyOp[EROTL] = 1;
|
|
IRO_IsModifyOp[EROTR] = 1;
|
|
IRO_IsModifyOp[EBCLR] = 1;
|
|
IRO_IsModifyOp[EBTST] = 1;
|
|
IRO_IsModifyOp[EBSET] = 1;
|
|
IRO_IsModifyOp[ETYPCON] = 0;
|
|
IRO_IsModifyOp[EBITFIELD] = 0;
|
|
IRO_IsModifyOp[EINTCONST] = 0;
|
|
IRO_IsModifyOp[EFLOATCONST] = 0;
|
|
IRO_IsModifyOp[ESTRINGCONST] = 0;
|
|
IRO_IsModifyOp[ECOND] = 0;
|
|
IRO_IsModifyOp[EFUNCCALL] = 0;
|
|
IRO_IsModifyOp[EFUNCCALLP] = 0;
|
|
IRO_IsModifyOp[EOBJREF] = 0;
|
|
IRO_IsModifyOp[EMFPOINTER] = 0;
|
|
IRO_IsModifyOp[ENULLCHECK] = 0;
|
|
IRO_IsModifyOp[EPRECOMP] = 0;
|
|
IRO_IsModifyOp[ETEMP] = 0;
|
|
IRO_IsModifyOp[EARGOBJ] = 0;
|
|
IRO_IsModifyOp[ELOCOBJ] = 0;
|
|
IRO_IsModifyOp[ELABEL] = 0;
|
|
IRO_IsModifyOp[ESETCONST] = 0;
|
|
IRO_IsModifyOp[ENEWEXCEPTION] = 0;
|
|
IRO_IsModifyOp[ENEWEXCEPTIONARRAY] = 0;
|
|
IRO_IsModifyOp[EOBJLIST] = 0;
|
|
IRO_IsModifyOp[EMEMBER] = 0;
|
|
IRO_IsModifyOp[ETEMPLDEP] = 0;
|
|
IRO_IsModifyOp[EINSTRUCTION] = 0;
|
|
IRO_IsModifyOp[EDEFINE] = 0;
|
|
IRO_IsModifyOp[EREUSE] = 0;
|
|
IRO_IsModifyOp[EASSBLK] = 0;
|
|
IRO_IsModifyOp[EVECTOR128CONST] = 0;
|
|
IRO_IsModifyOp[ECONDASS] = 1;
|
|
}
|
|
|
|
void IRO_InitializeIRO_IsAssignOpArray(void) {
|
|
int i;
|
|
|
|
for (i = 0; i < MAXEXPR; i++)
|
|
IRO_IsAssignOp[i] = 0;
|
|
|
|
IRO_IsAssignOp[EPOSTINC] = 1;
|
|
IRO_IsAssignOp[EPOSTDEC] = 1;
|
|
IRO_IsAssignOp[EPREINC] = 1;
|
|
IRO_IsAssignOp[EPREDEC] = 1;
|
|
IRO_IsAssignOp[EINDIRECT] = 0;
|
|
IRO_IsAssignOp[EMONMIN] = 0;
|
|
IRO_IsAssignOp[EBINNOT] = 0;
|
|
IRO_IsAssignOp[ELOGNOT] = 0;
|
|
IRO_IsAssignOp[EFORCELOAD] = 0;
|
|
IRO_IsAssignOp[EMUL] = 0;
|
|
IRO_IsAssignOp[EMULV] = 0;
|
|
IRO_IsAssignOp[EDIV] = 0;
|
|
IRO_IsAssignOp[EMODULO] = 0;
|
|
IRO_IsAssignOp[EADDV] = 0;
|
|
IRO_IsAssignOp[ESUBV] = 0;
|
|
IRO_IsAssignOp[EADD] = 0;
|
|
IRO_IsAssignOp[ESUB] = 0;
|
|
IRO_IsAssignOp[ESHL] = 0;
|
|
IRO_IsAssignOp[ESHR] = 0;
|
|
IRO_IsAssignOp[ELESS] = 0;
|
|
IRO_IsAssignOp[EGREATER] = 0;
|
|
IRO_IsAssignOp[ELESSEQU] = 0;
|
|
IRO_IsAssignOp[EGREATEREQU] = 0;
|
|
IRO_IsAssignOp[EEQU] = 0;
|
|
IRO_IsAssignOp[ENOTEQU] = 0;
|
|
IRO_IsAssignOp[EAND] = 0;
|
|
IRO_IsAssignOp[EXOR] = 0;
|
|
IRO_IsAssignOp[EOR] = 0;
|
|
IRO_IsAssignOp[ELAND] = 0;
|
|
IRO_IsAssignOp[ELOR] = 0;
|
|
IRO_IsAssignOp[EASS] = 1;
|
|
IRO_IsAssignOp[EMULASS] = 1;
|
|
IRO_IsAssignOp[EDIVASS] = 1;
|
|
IRO_IsAssignOp[EMODASS] = 1;
|
|
IRO_IsAssignOp[EADDASS] = 1;
|
|
IRO_IsAssignOp[ESUBASS] = 1;
|
|
IRO_IsAssignOp[ESHLASS] = 1;
|
|
IRO_IsAssignOp[ESHRASS] = 1;
|
|
IRO_IsAssignOp[EANDASS] = 1;
|
|
IRO_IsAssignOp[EXORASS] = 1;
|
|
IRO_IsAssignOp[EORASS] = 1;
|
|
IRO_IsAssignOp[ECOMMA] = 0;
|
|
IRO_IsAssignOp[EPMODULO] = 1;
|
|
IRO_IsAssignOp[EROTL] = 1;
|
|
IRO_IsAssignOp[EROTR] = 1;
|
|
IRO_IsAssignOp[EBCLR] = 1;
|
|
IRO_IsAssignOp[EBTST] = 1;
|
|
IRO_IsAssignOp[EBSET] = 1;
|
|
IRO_IsAssignOp[ETYPCON] = 0;
|
|
IRO_IsAssignOp[EBITFIELD] = 0;
|
|
IRO_IsAssignOp[EINTCONST] = 0;
|
|
IRO_IsAssignOp[EFLOATCONST] = 0;
|
|
IRO_IsAssignOp[ESTRINGCONST] = 0;
|
|
IRO_IsAssignOp[ECOND] = 0;
|
|
IRO_IsAssignOp[EFUNCCALL] = 0;
|
|
IRO_IsAssignOp[EFUNCCALLP] = 0;
|
|
IRO_IsAssignOp[EOBJREF] = 0;
|
|
IRO_IsAssignOp[EMFPOINTER] = 0;
|
|
IRO_IsAssignOp[ENULLCHECK] = 0;
|
|
IRO_IsAssignOp[EPRECOMP] = 0;
|
|
IRO_IsAssignOp[ETEMP] = 0;
|
|
IRO_IsAssignOp[EARGOBJ] = 0;
|
|
IRO_IsAssignOp[ELOCOBJ] = 0;
|
|
IRO_IsAssignOp[ELABEL] = 0;
|
|
IRO_IsAssignOp[ESETCONST] = 0;
|
|
IRO_IsAssignOp[ENEWEXCEPTION] = 0;
|
|
IRO_IsAssignOp[ENEWEXCEPTIONARRAY] = 0;
|
|
IRO_IsAssignOp[EOBJLIST] = 0;
|
|
IRO_IsAssignOp[EMEMBER] = 0;
|
|
IRO_IsAssignOp[ETEMPLDEP] = 0;
|
|
IRO_IsAssignOp[EINSTRUCTION] = 0;
|
|
IRO_IsAssignOp[EDEFINE] = 0;
|
|
IRO_IsAssignOp[EREUSE] = 0;
|
|
IRO_IsAssignOp[EASSBLK] = 0;
|
|
IRO_IsAssignOp[EVECTOR128CONST] = 0;
|
|
IRO_IsAssignOp[ECONDASS] = 1;
|
|
}
|
|
|
|
VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2) {
|
|
VarRecord *var;
|
|
VarInfo *vi;
|
|
|
|
var = object->varptr;
|
|
if (!var && flag1) {
|
|
vi = NULL;
|
|
if (object->datatype == DLOCAL)
|
|
vi = object->u.var.info;
|
|
if (vi)
|
|
vi->usage = 0;
|
|
var = oalloc(sizeof(VarRecord));
|
|
var->object = object;
|
|
var->index = ++IRO_NumVars;
|
|
var->x6 = 0;
|
|
var->xA = 0;
|
|
var->next = NULL;
|
|
var->defs = NULL;
|
|
var->uses = NULL;
|
|
var->x1A = NULL;
|
|
var->x1E = NULL;
|
|
var->xB = 0;
|
|
if (IRO_FirstVar)
|
|
IRO_LastVar->next = var;
|
|
else
|
|
IRO_FirstVar = var;
|
|
IRO_LastVar = var;
|
|
object->varptr = var;
|
|
}
|
|
|
|
if (var && !flag2) {
|
|
var->xB = 1;
|
|
if (object->datatype == DLOCAL && object->u.var.info && object->u.var.info->noregister == 0)
|
|
object->u.var.info->noregister = 2;
|
|
}
|
|
|
|
return var;
|
|
}
|
|
|
|
static void ResetVars(void) {
|
|
VarRecord *var;
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next) {
|
|
var->xB = 0;
|
|
if (var->object && var->object->datatype == DLOCAL && var->object->u.var.info) {
|
|
if (var->object->u.var.info->noregister == 2)
|
|
var->object->u.var.info->noregister = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void IRO_HandleExceptionActions(IROLinear *linear) {
|
|
ExceptionAction *action;
|
|
|
|
for (action = linear->stmt->dobjstack; action; action = action->prev) {
|
|
switch (action->type) {
|
|
case EAT_DESTROYLOCAL:
|
|
IRO_FindVar(action->data.destroy_local.local, 1, 0);
|
|
break;
|
|
case EAT_DESTROYLOCALCOND:
|
|
IRO_FindVar(action->data.destroy_local_cond.local, 1, 0);
|
|
break;
|
|
case EAT_DESTROYLOCALOFFSET:
|
|
IRO_FindVar(action->data.destroy_local_offset.local, 1, 0);
|
|
break;
|
|
case EAT_DESTROYLOCALARRAY:
|
|
IRO_FindVar(action->data.destroy_local_array.localarray, 1, 0);
|
|
break;
|
|
case EAT_DESTROYMEMBER:
|
|
case EAT_DESTROYBASE:
|
|
IRO_FindVar(action->data.destroy_member.objectptr, 1, 0);
|
|
break;
|
|
case EAT_DESTROYMEMBERCOND:
|
|
IRO_FindVar(action->data.destroy_member_cond.objectptr, 1, 0);
|
|
break;
|
|
case EAT_DESTROYMEMBERARRAY:
|
|
IRO_FindVar(action->data.destroy_member_array.objectptr, 1, 0);
|
|
break;
|
|
case EAT_CATCHBLOCK:
|
|
if (action->data.catch_block.catch_object)
|
|
IRO_FindVar(action->data.catch_block.catch_object, 1, 0);
|
|
IRO_FindVar(action->data.catch_block.catch_info_object, 1, 0);
|
|
break;
|
|
case EAT_ACTIVECATCHBLOCK:
|
|
IRO_FindVar(action->data.active_catch_block.catch_info_object, 1, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void IRO_FindAllVars(void) {
|
|
IROLinear *linear;
|
|
VarRecord *var;
|
|
|
|
linear = IRO_FirstLinear;
|
|
IRO_NumVars = 0;
|
|
IRO_FirstVar = IRO_LastVar = NULL;
|
|
|
|
while (linear) {
|
|
if (IS_LINEAR_ENODE(linear, EOBJREF)) {
|
|
if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL)
|
|
IRO_FindVar(linear->u.node->data.objref, 1, (linear->flags & IROLF_Ind) != 0);
|
|
else
|
|
linear->u.node->data.objref->varptr = NULL;
|
|
} else if (linear->type == IROLinearFunccall) {
|
|
if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
|
|
IRO_HandleExceptionActions(linear);
|
|
} else if (linear->type == IROLinearAsm) {
|
|
IAEffects effects;
|
|
int i;
|
|
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
|
|
for (i = 0; i < effects.numoperands; i++)
|
|
IRO_FindVar(effects.operands[i].object, 1, effects.operands[i].type != IAEffect_3);
|
|
}
|
|
linear = linear->next;
|
|
}
|
|
|
|
var = IRO_FirstVar;
|
|
Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1);
|
|
Bv_SetBit(0, IRO_FuncKills);
|
|
while (var) {
|
|
if (Inline_IsObjectData(var->object) || var->xB)
|
|
Bv_SetBit(var->index, IRO_FuncKills);
|
|
var = var->next;
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
void IRO_ZapVarPtrs(void) {
|
|
VarRecord *var;
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next)
|
|
var->object->varptr = NULL;
|
|
}
|
|
|
|
void IRO_UpdateVars(void) {
|
|
IROLinear *linear;
|
|
VarRecord *var;
|
|
|
|
ResetVars();
|
|
|
|
for (linear = IRO_FirstLinear; linear; linear = linear->next) {
|
|
if (IS_LINEAR_ENODE(linear, EOBJREF)) {
|
|
if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL)
|
|
IRO_FindVar(linear->u.node->data.objref, 0, (linear->flags & IROLF_Ind) || !(linear->flags & IROLF_Reffed));
|
|
} else if (linear->type == IROLinearFunccall) {
|
|
if (linear->stmt && IRO_FunctionCallMightThrowException(linear))
|
|
IRO_HandleExceptionActions(linear);
|
|
} else if (linear->type == IROLinearAsm) {
|
|
IAEffects effects;
|
|
int i;
|
|
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
|
|
for (i = 0; i < effects.numoperands; i++)
|
|
IRO_FindVar(effects.operands[i].object, 0, effects.operands[i].type != IAEffect_3);
|
|
}
|
|
}
|
|
|
|
var = IRO_FirstVar;
|
|
Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1);
|
|
Bv_SetBit(0, IRO_FuncKills);
|
|
while (var) {
|
|
if (Inline_IsObjectData(var->object) || var->xB)
|
|
Bv_SetBit(var->index, IRO_FuncKills);
|
|
var = var->next;
|
|
}
|
|
}
|
|
|
|
void IRO_AddElmToList(IROLinear *linear, IROElmList **list) {
|
|
IROElmList *l = oalloc(sizeof(IROElmList));
|
|
l->element = linear;
|
|
l->next = NULL;
|
|
if (!*list) {
|
|
*list = l;
|
|
} else {
|
|
l->next = *list;
|
|
*list = l;
|
|
}
|
|
}
|
|
|
|
void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec) {
|
|
if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) {
|
|
IRO_DecomposeAddressExpression(linear->u.diadic.left, rec);
|
|
} else if (IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) {
|
|
rec->numInts++;
|
|
IRO_AddElmToList(linear->u.diadic.left, &rec->ints);
|
|
} else if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) {
|
|
rec->numObjRefs++;
|
|
IRO_AddElmToList(linear->u.diadic.left, &rec->objRefs);
|
|
} else {
|
|
rec->numMisc++;
|
|
IRO_AddElmToList(linear->u.diadic.left, &rec->misc);
|
|
}
|
|
|
|
if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) {
|
|
IRO_DecomposeAddressExpression(linear->u.diadic.right, rec);
|
|
} else if (IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
|
|
rec->numInts++;
|
|
IRO_AddElmToList(linear->u.diadic.right, &rec->ints);
|
|
} else if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) {
|
|
rec->numObjRefs++;
|
|
IRO_AddElmToList(linear->u.diadic.right, &rec->objRefs);
|
|
} else {
|
|
rec->numMisc++;
|
|
IRO_AddElmToList(linear->u.diadic.right, &rec->misc);
|
|
}
|
|
}
|
|
|
|
void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear) {
|
|
if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) {
|
|
IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.left);
|
|
} else if (!IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) {
|
|
if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) {
|
|
IRO_BaseTerms++;
|
|
TheBaseTerm = linear->u.diadic.left;
|
|
} else {
|
|
IRO_VarTerms++;
|
|
}
|
|
}
|
|
|
|
if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) {
|
|
IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.right);
|
|
} else if (!IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
|
|
if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) {
|
|
IRO_BaseTerms++;
|
|
TheBaseTerm = linear->u.diadic.right;
|
|
} else {
|
|
IRO_VarTerms++;
|
|
}
|
|
}
|
|
}
|
|
|
|
VarRecord *IRO_FindAssigned(IROLinear *linear) {
|
|
VarRecord *rec;
|
|
|
|
IRO_IsBitField = 0;
|
|
if (linear->type == IROLinearOp2Arg)
|
|
linear = linear->u.diadic.left;
|
|
else if (linear->type == IROLinearOp1Arg)
|
|
linear = linear->u.monadic;
|
|
else
|
|
CError_FATAL(818);
|
|
|
|
if (IS_LINEAR_MONADIC(linear, EINDIRECT))
|
|
linear = linear->u.monadic;
|
|
|
|
if (IS_LINEAR_MONADIC(linear, EBITFIELD)) {
|
|
IRO_IsBitField = 1;
|
|
linear = linear->u.monadic;
|
|
}
|
|
|
|
if (IS_LINEAR_DIADIC(linear, EADD)) {
|
|
if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) {
|
|
linear = linear->u.diadic.left;
|
|
} else {
|
|
IRO_BaseTerms = 0;
|
|
IRO_DecomposeAddressExpression_Cheap(linear);
|
|
if (IRO_BaseTerms == 1)
|
|
linear = TheBaseTerm;
|
|
}
|
|
}
|
|
|
|
if (!IS_LINEAR_ENODE(linear, EOBJREF))
|
|
return NULL;
|
|
|
|
if ((rec = IRO_FindVar(linear->u.node->data.objref, 0, 1)))
|
|
return rec;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
static void GetKillsByIndirectAssignment(IROLinear *linear) {
|
|
IROListNode *resultList;
|
|
IROLinear *nd;
|
|
IROListNode *list;
|
|
IROListNode *scan;
|
|
IROLinear *inner;
|
|
Boolean result;
|
|
Boolean foundLinear;
|
|
|
|
result = 0;
|
|
|
|
if (linear->type == IROLinearOp2Arg)
|
|
linear = linear->u.diadic.left;
|
|
else
|
|
linear = linear->u.monadic;
|
|
|
|
if (
|
|
linear &&
|
|
linear->type == IROLinearOp1Arg &&
|
|
linear->nodetype == EINDIRECT &&
|
|
(inner = linear->u.monadic) &&
|
|
copts.opt_pointer_analysis &&
|
|
inner->pointsToFunction &&
|
|
FunctionName
|
|
)
|
|
{
|
|
resultList = NULL;
|
|
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
|
|
if ((list = resultList)) {
|
|
for (scan = list; scan; scan = scan->nextList) {
|
|
if (!scan->list.head || !scan->list.tail) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
|
|
foundLinear = 0;
|
|
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
foundLinear = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!foundLinear) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
while (list) {
|
|
for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
Object *obj;
|
|
VarRecord *var;
|
|
int index;
|
|
|
|
obj = nd->u.node->data.objref;
|
|
CError_ASSERT(952, obj != NULL);
|
|
|
|
var = IRO_FindVar(obj, 1, 1);
|
|
CError_ASSERT(954, var != NULL);
|
|
|
|
index = var->index;
|
|
CError_ASSERT(956, index != 0);
|
|
|
|
Bv_SetBit(index, IRO_VarKills);
|
|
}
|
|
}
|
|
|
|
list = list->nextList;
|
|
}
|
|
}
|
|
|
|
while (resultList) {
|
|
IROListNode *next = resultList->nextList;
|
|
IRO_free(resultList);
|
|
resultList = next;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
|
|
if (result)
|
|
Bv_Or(IRO_FuncKills, IRO_VarKills);
|
|
}
|
|
|
|
static void GetKillsByFunctionCall(IROLinear *linear) {
|
|
IROListNode *resultList;
|
|
IROLinear *nd;
|
|
IROListNode *list;
|
|
IROListNode *scan;
|
|
IROLinear *inner;
|
|
Boolean result;
|
|
Boolean foundLinear;
|
|
Object *obj;
|
|
ObjectList *killList;
|
|
ObjectList *olist;
|
|
|
|
result = 0;
|
|
|
|
if (
|
|
(inner = linear->u.funccall.linear8) &&
|
|
copts.opt_pointer_analysis &&
|
|
inner->pointsToFunction &&
|
|
FunctionName
|
|
)
|
|
{
|
|
resultList = NULL;
|
|
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
|
|
if (resultList) {
|
|
for (scan = resultList; scan; scan = scan->nextList) {
|
|
if (!scan->list.head || !scan->list.tail) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
|
|
foundLinear = 0;
|
|
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
foundLinear = 1;
|
|
obj = nd->u.node->data.objref;
|
|
CError_ASSERT(1028, obj != NULL);
|
|
|
|
killList = NULL;
|
|
PointerAnalysis_GetFunctionKills(obj, linear, &killList);
|
|
|
|
for (olist = killList; olist; olist = olist->next) {
|
|
if (!olist->object) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (killList) {
|
|
ObjectList *next = killList->next;
|
|
IRO_free(killList);
|
|
killList = next;
|
|
}
|
|
|
|
if (result)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!foundLinear)
|
|
result = 1;
|
|
if (result)
|
|
break;
|
|
}
|
|
|
|
if (!result) {
|
|
for (scan = resultList; scan; scan = scan->nextList) {
|
|
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
obj = nd->u.node->data.objref;
|
|
killList = NULL;
|
|
PointerAnalysis_GetFunctionKills(obj, linear, &killList);
|
|
|
|
for (olist = killList; olist; olist = olist->next) {
|
|
VarRecord *var;
|
|
int index;
|
|
|
|
var = IRO_FindVar(olist->object, 1, 1);
|
|
CError_ASSERT(1079, var != NULL);
|
|
|
|
index = var->index;
|
|
CError_ASSERT(1081, index != 0);
|
|
|
|
Bv_SetBit(index, IRO_VarKills);
|
|
}
|
|
|
|
while (killList) {
|
|
ObjectList *next = killList->next;
|
|
IRO_free(killList);
|
|
killList = next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
while (resultList) {
|
|
IROListNode *next = resultList->nextList;
|
|
IRO_free(resultList);
|
|
resultList = next;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
|
|
if (result)
|
|
Bv_Or(IRO_FuncKills, IRO_VarKills);
|
|
}
|
|
|
|
void IRO_GetKills(IROLinear *linear) {
|
|
VarRecord *var;
|
|
|
|
switch (linear->type) {
|
|
case IROLinearOp1Arg:
|
|
case IROLinearOp2Arg:
|
|
if (IRO_IsAssignOp[linear->nodetype]) {
|
|
IROLinear *assigned;
|
|
int index;
|
|
|
|
var = IRO_FindAssigned(linear);
|
|
index = 0;
|
|
if (var) index = var->index;
|
|
Bv_SetBit(index, IRO_VarKills);
|
|
|
|
if (!index)
|
|
GetKillsByIndirectAssignment(linear);
|
|
}
|
|
break;
|
|
case IROLinearFunccall:
|
|
GetKillsByFunctionCall(linear);
|
|
break;
|
|
case IROLinearAsm: {
|
|
IAEffects effects;
|
|
int i;
|
|
|
|
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
|
|
for (i = 0; i < effects.numoperands; i++) {
|
|
switch (effects.operands[i].type) {
|
|
case IAEffect_1:
|
|
case IAEffect_2:
|
|
case IAEffect_4:
|
|
if ((var = IRO_FindVar(effects.operands[i].object, 0, 1)))
|
|
Bv_SetBit(var->index, IRO_VarKills);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (effects.x1 || effects.x4)
|
|
Bv_Or(IRO_FuncKills, IRO_VarKills);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void IRO_CheckInit(void) {
|
|
IRONode *fnode;
|
|
IROLinear *nd;
|
|
VarRecord *var;
|
|
ObjectList *olist;
|
|
int flag;
|
|
int i;
|
|
BitVector *bv;
|
|
|
|
IRO_MakeReachable(IRO_FirstNode);
|
|
fnode = IRO_FirstNode;
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
|
|
while (fnode) {
|
|
Bv_AllocVector(&fnode->x16, IRO_NumVars + 1);
|
|
Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1);
|
|
|
|
for (nd = fnode->first; nd; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
if (nd->flags & IROLF_Ind) {
|
|
if (!(nd->flags & IROLF_Assigned) || (nd->flags & IROLF_Used)) {
|
|
if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) {
|
|
if (!Bv_IsBitSet(var->index, fnode->x1E))
|
|
Bv_SetBit(var->index, fnode->x16);
|
|
}
|
|
}
|
|
} else {
|
|
if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 0))) {
|
|
Bv_SetBit(var->index, fnode->x1E);
|
|
}
|
|
}
|
|
} else if (nd->type == IROLinearOp2Arg && nd->nodetype == EASS) {
|
|
if ((var = IRO_FindAssigned(nd)))
|
|
Bv_SetBit(var->index, fnode->x1E);
|
|
} else if (nd->type == IROLinearAsm) {
|
|
IAEffects effects;
|
|
|
|
CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects);
|
|
for (i = 0; i < effects.numoperands; i++) {
|
|
var = IRO_FindVar(effects.operands[i].object, 0, 1);
|
|
switch (effects.operands[i].type) {
|
|
case IAEffect_1:
|
|
case IAEffect_2:
|
|
case IAEffect_4:
|
|
Bv_SetBit(var->index, fnode->x1E);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nd == fnode->last)
|
|
break;
|
|
}
|
|
|
|
fnode = fnode->nextnode;
|
|
}
|
|
|
|
Bv_AllocVector(&bv, IRO_NumVars + 1);
|
|
|
|
do {
|
|
flag = 0;
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
Bv_Copy(fnode->x1E, bv);
|
|
for (i = 0; i < fnode->numpred; i++)
|
|
Bv_Or(IRO_NodeTable[fnode->pred[i]]->x1E, bv);
|
|
if (!Bv_Compare(bv, fnode->x1E)) {
|
|
Bv_Copy(bv, fnode->x1E);
|
|
flag = 1;
|
|
}
|
|
}
|
|
} while (flag);
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
if (fnode->x36) {
|
|
Bv_Copy(fnode->x16, bv);
|
|
for (i = 0; i < fnode->numpred; i++)
|
|
Bv_Minus(IRO_NodeTable[fnode->pred[i]]->x1E, bv);
|
|
Bv_Or(bv, IRO_VarKills);
|
|
}
|
|
}
|
|
|
|
for (olist = locals; olist; olist = olist->next) {
|
|
if ((var = IRO_FindVar(olist->object, 0, 1)) && Bv_IsBitSet(var->index, IRO_VarKills)) {
|
|
VarInfo *vi = olist->object->u.var.info;
|
|
if (!IsTempName(olist->object->name) && !is_volatile_object(olist->object)) {
|
|
if (!IS_TYPE_CLASS(olist->object->type) || !CClass_IsEmpty(TYPE_CLASS(olist->object->type))) {
|
|
CError_SetErrorToken(&vi->deftoken);
|
|
CError_Warning(CErrorStr185, olist->object->name->name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
static void RewriteIndDec(void) {
|
|
IROLinear *add;
|
|
IROLinear *indirect;
|
|
IROLinear *Int;
|
|
IROLinear *nd;
|
|
CInt64 value;
|
|
IROList list;
|
|
|
|
for (nd = IRO_FirstLinear; nd; nd = nd->next) {
|
|
if (
|
|
nd->type == IROLinearOp1Arg &&
|
|
(nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) &&
|
|
!(nd->flags & IROLF_Reffed)
|
|
) {
|
|
indirect = nd->u.monadic;
|
|
if (
|
|
indirect->type == IROLinearOp1Arg &&
|
|
indirect->nodetype == EINDIRECT &&
|
|
indirect->u.monadic->type == IROLinearOp1Arg &&
|
|
indirect->u.monadic->nodetype == EBITFIELD
|
|
) {
|
|
value = IRO_GetSelfAssignmentVal(nd);
|
|
IRO_InitList(&list);
|
|
|
|
nd->type = IROLinearOp2Arg;
|
|
nd->nodetype = EASS;
|
|
nd->u.diadic.left = indirect;
|
|
IRO_DuplicateExpr(indirect, &list);
|
|
|
|
Int = IRO_NewIntConst(value, indirect->rtype);
|
|
Int->flags |= IROLF_Used | IROLF_Reffed;
|
|
|
|
add = IRO_NewLinear(IROLinearOp2Arg);
|
|
add->nodetype = EADD;
|
|
add->u.diadic.left = list.tail;
|
|
add->u.diadic.left->flags = 0;
|
|
add->u.diadic.left->flags |= IROLF_Used | IROLF_Reffed;
|
|
add->u.diadic.right = Int;
|
|
add->rtype = indirect->rtype;
|
|
add->flags = 0;
|
|
add->flags |= IROLF_Used | IROLF_Reffed;
|
|
|
|
nd->u.diadic.right = add;
|
|
|
|
IRO_AddToList(Int, &list);
|
|
IRO_AddToList(add, &list);
|
|
IRO_PasteAfter(list.head, list.tail, indirect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void IRO_RewriteBitFieldTemps(void) {
|
|
IROLinear *nd;
|
|
IROLinear *expr2;
|
|
Object *obj;
|
|
VarRecord *var;
|
|
IROList list;
|
|
|
|
for (nd = IRO_FirstLinear; nd; nd = nd->next) {
|
|
if ((obj = IRO_IsVariable(nd)) && (nd->flags & IROLF_BitfieldIndirect)) {
|
|
var = IRO_FindVar(obj, 0, 1);
|
|
CError_ASSERT(1526, var != NULL);
|
|
|
|
expr2 = var->x1E;
|
|
CError_ASSERT(1532, expr2 != NULL);
|
|
|
|
IRO_InitList(&list);
|
|
IRO_DuplicateExpr(expr2, &list);
|
|
IRO_NopOut(nd->u.monadic);
|
|
nd->u.monadic = list.tail;
|
|
IRO_Paste(list.head, list.tail, nd);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) {
|
|
IROLinear *funcnd;
|
|
IROLinear *nd;
|
|
IROListNode *scan;
|
|
IROListNode *resultList;
|
|
ObjectList *olist;
|
|
ObjectList *killList;
|
|
VarRecord *var;
|
|
Boolean result;
|
|
Boolean foundObjRef;
|
|
Object *obj;
|
|
|
|
result = 0;
|
|
|
|
funcnd = funccall->u.funccall.linear8;
|
|
if (funcnd && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) {
|
|
resultList = NULL;
|
|
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList);
|
|
|
|
if (resultList) {
|
|
for (scan = resultList; scan; scan = scan->nextList) {
|
|
if (!scan->list.head || !scan->list.tail) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
|
|
foundObjRef = 0;
|
|
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
foundObjRef = 1;
|
|
obj = nd->u.node->data.objref;
|
|
CError_ASSERT(1592, obj != NULL);
|
|
|
|
killList = NULL;
|
|
PointerAnalysis_GetFunctionKills(obj, funccall, &killList);
|
|
for (olist = killList; olist; olist = olist->next) {
|
|
if (!olist->object) {
|
|
result = 1;
|
|
} else {
|
|
var = IRO_FindVar(olist->object, 1, 1);
|
|
CError_ASSERT(1604, var != NULL);
|
|
if (var->xB)
|
|
result = 1;
|
|
}
|
|
|
|
if (result)
|
|
break;
|
|
}
|
|
|
|
while (killList) {
|
|
ObjectList *next = killList->next;
|
|
IRO_free(killList);
|
|
killList = next;
|
|
}
|
|
|
|
if (!result) {
|
|
killList = NULL;
|
|
PointerAnalysis_GetFunctionDependencies(obj, funccall, &killList);
|
|
for (olist = killList; olist; olist = olist->next) {
|
|
if (!olist->object) {
|
|
result = 1;
|
|
} else {
|
|
var = IRO_FindVar(olist->object, 1, 1);
|
|
CError_ASSERT(1632, var != NULL);
|
|
if (var->xB)
|
|
result = 1;
|
|
}
|
|
|
|
if (result)
|
|
break;
|
|
}
|
|
|
|
while (killList) {
|
|
ObjectList *next = killList->next;
|
|
IRO_free(killList);
|
|
killList = next;
|
|
}
|
|
}
|
|
|
|
if (result)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!foundObjRef)
|
|
result = 1;
|
|
if (result)
|
|
break;
|
|
}
|
|
|
|
while (resultList) {
|
|
IROListNode *next = resultList->nextList;
|
|
IRO_free(resultList);
|
|
resultList = next;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) {
|
|
Boolean result;
|
|
IROLinear *inner;
|
|
IROLinear *nd;
|
|
IROListNode *scan;
|
|
IROListNode *resultList;
|
|
Boolean foundObjRef;
|
|
Object *obj;
|
|
VarRecord *var;
|
|
|
|
result = 0;
|
|
|
|
if (
|
|
indirect &&
|
|
indirect->type == IROLinearOp1Arg &&
|
|
indirect->nodetype == EINDIRECT &&
|
|
(inner = indirect->u.monadic) &&
|
|
copts.opt_pointer_analysis &&
|
|
inner->pointsToFunction &&
|
|
FunctionName
|
|
) {
|
|
resultList = NULL;
|
|
PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList);
|
|
if (resultList) {
|
|
for (scan = resultList; scan; scan = scan->nextList) {
|
|
if (!scan->list.head || !scan->list.tail) {
|
|
result = 1;
|
|
break;
|
|
}
|
|
|
|
foundObjRef = 0;
|
|
for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) {
|
|
if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) {
|
|
foundObjRef = 1;
|
|
obj = nd->u.node->data.objref;
|
|
CError_ASSERT(1723, obj != NULL);
|
|
var = IRO_FindVar(obj, 1, 1);
|
|
CError_ASSERT(1725, var != NULL);
|
|
|
|
if (var->xB)
|
|
result = 1;
|
|
}
|
|
}
|
|
|
|
if (!foundObjRef)
|
|
result = 1;
|
|
if (result)
|
|
break;
|
|
}
|
|
|
|
while (resultList) {
|
|
IROListNode *next = resultList->nextList;
|
|
IRO_free(resultList);
|
|
resultList = next;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
} else {
|
|
result = 1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void IRO_ScalarizeClassDataMembers(void) {
|
|
IROLinear *nd;
|
|
VarRecord *var;
|
|
Boolean flag;
|
|
Object *obj;
|
|
IndirectRecord *irec;
|
|
IndirectRecordMatch *match;
|
|
IROLinear *tmp;
|
|
|
|
nd = IRO_FirstLinear;
|
|
IRO_FirstIndirectRecord = NULL;
|
|
IRO_LastIndirectRecord = NULL;
|
|
RewriteIndDec();
|
|
IRO_DumpAfterPhase("RewriteIndDec", 0);
|
|
flag = 0;
|
|
|
|
while (nd) {
|
|
if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) {
|
|
CheckAddress(nd, &flag);
|
|
}
|
|
if (nd->type == IROLinearAsm) {
|
|
IAEffects effects;
|
|
SInt32 i;
|
|
CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects);
|
|
for (i = 0; i < effects.numoperands; i++) {
|
|
if ((var = IRO_FindVar(effects.operands[i].object, 0, 1)))
|
|
CheckAddressConsistency(nd, var, -1, &stvoid);
|
|
else
|
|
CError_FATAL(1823);
|
|
}
|
|
}
|
|
if (nd->type == IROLinearFunccall && !flag)
|
|
flag = FunctionCallMightUseOrKillAnyAddressedVar(nd);
|
|
|
|
nd = nd->next;
|
|
}
|
|
|
|
if (flag)
|
|
DisableAddressedEntries();
|
|
|
|
for (irec = IRO_FirstIndirectRecord; irec; irec = irec->next) {
|
|
if (!(irec->flags & 1)) {
|
|
IROList list1;
|
|
IROList list2;
|
|
|
|
obj = create_temp_object(irec->type);
|
|
var = IRO_FindVar(obj, 1, 1);
|
|
for (match = irec->matches; match; match = match->otherMatches) {
|
|
IRO_InitList(&list1);
|
|
IRO_InitList(&list2);
|
|
IRO_DuplicateExpr(match->nd, &list1);
|
|
IRO_DuplicateExpr(match->nd, &list2);
|
|
if (match->nd->type == IROLinearOperand && match->nd->u.node->type == EOBJREF) {
|
|
tmp = IRO_LocateFather(match->nd);
|
|
if (irec->flags & 2) {
|
|
tmp->flags |= IROLF_BitfieldIndirect;
|
|
var->x1A = match->nd->rtype;
|
|
var->x1E = list2.tail;
|
|
}
|
|
match->nd->u.node = create_objectrefnode(obj);
|
|
irec->x26 = list2.tail;
|
|
} else {
|
|
tmp = IRO_LocateFather(match->nd);
|
|
if (irec->flags & 2) {
|
|
tmp->flags |= IROLF_BitfieldIndirect;
|
|
var->x1A = match->nd->rtype;
|
|
var->x1E = list2.tail;
|
|
}
|
|
irec->x26 = list2.tail;
|
|
|
|
IRO_NopOut(tmp->u.monadic);
|
|
tmp->u.monadic = IRO_NewLinear(IROLinearOperand);
|
|
tmp->u.monadic->u.node = create_objectrefnode(obj);
|
|
tmp->u.monadic->rtype = match->nd->rtype;
|
|
tmp->u.monadic->index = ++IRO_NumLinear;
|
|
tmp->u.monadic->flags |= IROLF_Ind | IROLF_Reffed;
|
|
IRO_NopOut(match->nd);
|
|
IRO_PasteAfter(tmp->u.monadic, tmp->u.monadic, match->nd);
|
|
}
|
|
}
|
|
|
|
if (ObjectIsArg(irec->var->object)) {
|
|
IROLinear *op1;
|
|
IROLinear *op2;
|
|
IROLinear *op3;
|
|
IROLinear *op4;
|
|
IROLinear *op5;
|
|
|
|
op1 = IRO_NewLinear(IROLinearOperand);
|
|
op1->u.node = create_objectrefnode(obj);
|
|
op1->rtype = op1->u.node->data.objref->type;
|
|
op1->index = ++IRO_NumLinear;
|
|
op1->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
op2 = list1.tail;
|
|
|
|
op3 = IRO_NewLinear(IROLinearOp1Arg);
|
|
op3->nodetype = EINDIRECT;
|
|
op3->rtype = irec->type;
|
|
op3->u.monadic = op1;
|
|
op3->index = ++IRO_NumLinear;
|
|
op3->flags |= IROLF_Assigned;
|
|
|
|
op4 = IRO_NewLinear(IROLinearOp1Arg);
|
|
op4->nodetype = EINDIRECT;
|
|
op4->rtype = irec->type;
|
|
op4->u.monadic = op2;
|
|
op4->index = ++IRO_NumLinear;
|
|
op4->flags |= IROLF_Reffed;
|
|
|
|
op5 = IRO_NewLinear(IROLinearOp2Arg);
|
|
op5->nodetype = EASS;
|
|
op5->u.diadic.left = op3;
|
|
op5->u.diadic.right = op4;
|
|
op5->rtype = irec->type;
|
|
op5->index = ++IRO_NumLinear;
|
|
|
|
op2->next = op4;
|
|
op4->next = op1;
|
|
op1->next = op3;
|
|
op3->next = op5;
|
|
|
|
IRO_PasteAfter(list1.head, op5, IRO_FirstLinear);
|
|
}
|
|
}
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) {
|
|
IROLinear *inner;
|
|
VarRecord *var;
|
|
Boolean result;
|
|
|
|
inner = nd->u.monadic;
|
|
if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD)
|
|
inner = inner->u.monadic;
|
|
|
|
result = 0;
|
|
|
|
if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) {
|
|
if (IS_TYPE_CLASS(inner->u.node->data.objref->type) || IS_TYPE_STRUCT(inner->u.node->data.objref->type) ||
|
|
IS_TYPE_ARRAY(inner->u.node->data.objref->type)) {
|
|
if (inner->u.node->data.objref->datatype == DLOCAL) {
|
|
var = IRO_FindVar(inner->u.node->data.objref, 0, 1);
|
|
CError_ASSERT(2240, var != NULL);
|
|
CheckAddressConsistency(nd, var, 0, nd->rtype);
|
|
result = 1;
|
|
}
|
|
}
|
|
} else if (
|
|
inner->type == IROLinearOp2Arg &&
|
|
inner->nodetype == EADD &&
|
|
inner->u.diadic.left->type == IROLinearOperand &&
|
|
inner->u.diadic.left->u.node->type == EOBJREF) {
|
|
if (
|
|
inner->u.diadic.right->type == IROLinearOperand &&
|
|
inner->u.diadic.right->u.node->type == EINTCONST &&
|
|
inner->u.diadic.right->u.node->data.intval.hi == 0) {
|
|
if (
|
|
IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) ||
|
|
IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) ||
|
|
IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type)
|
|
) {
|
|
if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) {
|
|
var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1);
|
|
CError_ASSERT(2267, var != NULL);
|
|
CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype);
|
|
result = 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (
|
|
IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) ||
|
|
IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) ||
|
|
IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type)
|
|
) {
|
|
if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) {
|
|
var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1);
|
|
CheckAddressConsistency(nd, var, -1, nd->rtype);
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!result && !*resultFlag) {
|
|
*resultFlag = IndirectMightUseOrKillAnyAddressedVar(nd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type) {
|
|
IndirectRecord *rp;
|
|
IndirectRecordMatch *match;
|
|
UInt32 flag;
|
|
IROLinear *inner;
|
|
UInt32 start_bit;
|
|
UInt32 end_bit;
|
|
|
|
flag = 0;
|
|
inner = nd->u.monadic;
|
|
if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) {
|
|
start_bit = TYPE_BITFIELD(inner->rtype)->unkA + 8 * addend;
|
|
end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->unkB - 1;
|
|
} else {
|
|
start_bit = 8 * addend;
|
|
end_bit = start_bit + 8 * type->size - 1;
|
|
}
|
|
|
|
if (var->xB && !copts.opt_pointer_analysis)
|
|
return 0;
|
|
|
|
if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS))
|
|
addend = -1;
|
|
if (is_volatile_object(var->object))
|
|
addend = -1;
|
|
|
|
for (rp = IRO_FirstIndirectRecord; rp; rp = rp->next) {
|
|
if (rp->var->index == var->index) {
|
|
if (rp->flags & 1)
|
|
return 0;
|
|
|
|
if (addend == -1) {
|
|
flag = 1;
|
|
break;
|
|
}
|
|
|
|
if (IRO_TypesEqual(rp->type, type) && rp->startbit == start_bit && rp->endbit == end_bit) {
|
|
match = oalloc(sizeof(IndirectRecordMatch));
|
|
match->nd = inner;
|
|
match->otherMatches = NULL;
|
|
if (!rp->matches) {
|
|
rp->matches = match;
|
|
} else {
|
|
match->otherMatches = rp->matches;
|
|
rp->matches = match;
|
|
}
|
|
|
|
IRO_Dump("Exact Match of Type and bits at %d and %d\n", rp->linear->index, nd->index);
|
|
IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
|
|
return 1;
|
|
}
|
|
|
|
if (rp->startbit == start_bit && rp->endbit == end_bit && !IRO_TypesEqual(rp->type, type)) {
|
|
IRO_Dump("match on bits but mismatch on type %d and %d\n", rp->linear->index, nd->index);
|
|
IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
|
|
flag = 1;
|
|
break;
|
|
}
|
|
|
|
if (rp->startbit >= start_bit && end_bit >= rp->startbit) {
|
|
IRO_Dump("Overlap detected --1 %d and %d\n", rp->linear->index, nd->index);
|
|
IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
|
|
flag = 1;
|
|
break;
|
|
}
|
|
|
|
if (rp->startbit < start_bit && rp->endbit >= start_bit) {
|
|
IRO_Dump("Overlap detected --2 %d and %d\n", rp->linear->index, nd->index);
|
|
IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit);
|
|
flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flag) {
|
|
DisableEntries(rp);
|
|
if (addend >= 0)
|
|
return 0;
|
|
}
|
|
|
|
IRO_Dump("Create Entry at %d\n", nd->index);
|
|
IRO_Dump("start_bit=%d,end_bit=%d\n", start_bit, end_bit);
|
|
|
|
rp = oalloc(sizeof(IndirectRecord));
|
|
rp->linear = nd;
|
|
rp->flags = 0;
|
|
rp->var = var;
|
|
rp->addend = addend;
|
|
rp->size = type->size;
|
|
rp->type = type;
|
|
rp->next = NULL;
|
|
rp->matches = oalloc(sizeof(IndirectRecordMatch));
|
|
rp->matches->nd = inner;
|
|
rp->matches->otherMatches = NULL;
|
|
rp->startbit = start_bit;
|
|
rp->endbit = end_bit;
|
|
|
|
if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT &&
|
|
nd->u.monadic->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EBITFIELD)
|
|
rp->flags |= 2;
|
|
|
|
if (!(IS_TYPE_FLOAT(type) || IS_TYPE_INT(type) || IS_TYPE_POINTER_ONLY(type)) ||
|
|
addend == -1 || ((inner->flags & IROLF_4000) && ObjectIsArg(var->object)))
|
|
rp->flags |= 1;
|
|
|
|
if (IRO_FirstIndirectRecord)
|
|
IRO_LastIndirectRecord->next = rp;
|
|
else
|
|
IRO_FirstIndirectRecord = rp;
|
|
IRO_LastIndirectRecord = rp;
|
|
return 1;
|
|
}
|
|
|
|
static void DisableEntries(IndirectRecord *irec) {
|
|
IndirectRecord *scan;
|
|
|
|
for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) {
|
|
if (irec->var->index == scan->var->index)
|
|
scan->flags |= 1;
|
|
}
|
|
}
|
|
|
|
static void DisableAddressedEntries(void) {
|
|
IndirectRecord *scan;
|
|
|
|
for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) {
|
|
if (scan->var->xB)
|
|
scan->flags |= 1;
|
|
}
|
|
}
|
|
|
|
static UInt32 ObjectIsArg(Object *obj) {
|
|
ObjectList *scan;
|
|
|
|
for (scan = arguments; scan; scan = scan->next) {
|
|
if (scan->object == obj)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|