extern instruction *NeedIndex( instruction *ins ) { /******************************************************* Mark conflicts for any name used in instruction as as segment as NEEDS_SEGMENT, or split out the segment if it is marked as NEEDS_SEGMENT_SPLIT (move the segment operand to a temp and use the temp as the segment override). Also, if any index conflicts are marked as NEEDS_INDEX_SPLIT, split them out into a temp as well. */ name *temp; name *index; conflict_node *conf; name *name; if( ins->num_operands > NumOperands( ins ) ) { name = ins->operands[ins->num_operands - 1]; conf = NameConflict( ins, name ); if( conf != NULL && _Isnt( conf, CST_NEEDS_SEGMENT_SPLIT ) ) { _SetTrue( conf, CST_NEEDS_SEGMENT ); MarkSegment( ins, name ); } else if( name->n.class != N_REGISTER ) { if( conf != NULL ) { _SetFalse( conf, CST_NEEDS_SEGMENT ); _SetTrue( conf, CST_WAS_SEGMENT ); } temp = AllocTemp( U2 ); ins->operands[ins->num_operands - 1] = temp; PrefixIns( ins, MakeMove( name, temp, U2 ) ); MarkSegment( ins, temp ); _SetTrue( NameConflict( ins, temp ), CST_SEGMENT_SPLIT ); ins = ins->head.prev; } }
extern bool IndexOkay( instruction *ins, name *index ) { /**********************************************************/ name *name; conflict_node *conf; name = index->i.index; if( name->n.class == N_REGISTER ) { return( IsIndexReg( name->r.reg, name->n.name_class, 0 ) ); } if( name->v.conflict == NULL ) return( FALSE ); if( name->v.usage & USE_MEMORY ) return( FALSE ); if( name->n.class != N_TEMP ) return( FALSE ); conf = NameConflict( ins, name ); if( conf == NULL ) return( FALSE ); if( _Is( conf, NEEDS_INDEX_SPLIT ) ) { _SetFalse( conf, NEEDS_INDEX ); return( FALSE ); } else { _SetTrue( conf, NEEDS_INDEX ); ins->head.state = OPERANDS_NEED_WORK; ins->t.index_needs = MarkIndex( ins, name, 0 ); return( TRUE ); } }
extern void SplitVars( void ) /*******************************/ /* For each variable, find out if it can be split into two separate variables.*/ /* This often happens when programmers re-use variables rather than defining*/ /* a new one.*/ { name *op; conflict_node *conf; for( ;; ) { for( conf = ConfList; conf != NULL; conf = conf->next_conflict ) { op = conf->name; if( (op->v.usage & USE_IN_ANOTHER_BLOCK) == 0 ) continue; if( op->n.class != N_TEMP ) continue; if( _Is( conf, CST_CONF_VISITED ) ) continue; _SetFalse( conf, CST_CONFLICT_ON_HOLD ); if( _GBitEmpty( conf->id.out_of_block ) ) continue; if( op->t.alias == op ) Split1Var( conf ); _GBitInit( conf->id.out_of_block, EMPTY ); _SetTrue( conf, CST_CONFLICT_ON_HOLD | CST_CONF_VISITED ); } if( !MoreConflicts() ) { break; } } CleanUp(); FreeConflicts(); InsDead(); NullConflicts( EMPTY ); FindReferences(); MakeConflicts(); }