diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroVars.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IroVars.c | 1430 |
1 files changed, 1430 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroVars.c b/compiler_and_linker/FrontEnd/Optimizer/IroVars.c new file mode 100644 index 0000000..b72ba89 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroVars.c @@ -0,0 +1,1430 @@ +#include "IroVars.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroJump.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroUtil.h" +#include "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 "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)->offset + 8 * addend; + end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->bitlength - 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; +} + |