示例#1
0
        private static void _DeadVarsAlgortihm(Function func, Variable.State state)
        {
            /*
             * Before the algorithm starts we ensure that all instructions have a
             * list of dead variables which is filled with all the variables present in
             * the function. During the algorithm we will remove the variables from these
             * lists that are not really dead at the given point.
             */
            SetAllVariablesAsDead(func, state);

            /*
             * If we are going upwards (looking for FREE dead variables), we start from
             * the point called "fake exit block", the one and only ultimate endpoint
             * of all functions ever created. Thank you Kohlmann!
             *
             * If going downwards (looking for NOT_INITIALIZED dead variables),
             * we start from the very first basic block (func.BasicBlocks[0]).
             */
            BasicBlock block = (state == Variable.State.Free) ? func.GetFakeExitBasicBlock() : func.GetEntranceBasicBlock();

            /*
             * We go through all the instructions and deal with all their
             * referenced variables. At the and of this we will have the list of the dead
             * variables for all instructions.
             */
            recursive(block, state);

            /*
             * In the end we clear the done_ids list, so it won't influence the algorithm's
             * future runs (if these will exist).
             */
            DoneIDs.Clear();
        }
示例#2
0
        /// <summary>
        /// Recursive function to get to all the instructions of the Function.
        /// </summary>
        /// <param name="actual">Actual BasicBlock</param>
        private static void recursive(BasicBlock actual, Variable.State state)
        {
            /*
             * We deal with every original(1) instruction in the basic block,
             * and in every instruction we deal with every referenced variable.
             * The referenced variables should be removed from the dead variables list
             * in all the instructions accesible from here.
             *
             * (1): Only the original instructions determine whether a variable is dead
             *      or not, because the fake instructions work with dead variables only.
             *
             * deal_with_var() - it will be described in detail in the forthcoming parts
             */
            foreach (Instruction ins in actual.Instructions)
            {
                if (/*ins.isFake == false*/ true)
                {
                    foreach (Variable var in ins.RefVariables)
                    {
                        DealWithVariable(var, ins, state);
                    }
                }
            }

            /*
             * We have finished the task with this basic block, and we should not
             * come back here anymore, so we save its ID into the done_ids list.
             */
            DoneIDs.Add(actual.ID);

            /*
             * Now that this basic block is finished we should do the same things
             * with its predecessors recursively.
             * We only should deal with the basic blocks not marked as done.
             */
            List <BasicBlock> bblist = (state == Variable.State.Free) ? actual.getPredecessors : actual.getSuccessors;

            foreach (BasicBlock block in bblist)
            {
                if (!DoneIDs.Contains(block.ID))
                {
                    recursive(block, state);
                }
            }
        }
示例#3
0
 /// <summary>
 /// Fills the DeadVariables lists with the variables that aren't already in them.
 /// </summary>
 /// <param name="func">Actual Function</param>
 private static void SetAllVariablesAsDead(Function func, Variable.State state)
 {
     foreach (BasicBlock bb in func.BasicBlocks)
     {
         foreach (Instruction inst in bb.Instructions)
         {
             foreach (Variable var in func.LocalVariables)
             {
                 /* We add it in the list only if it is not already there. */
                 if (!inst.DeadVariables.ContainsKey(var))
                 {
                     /*
                      *  If it's an input parameter we don't use it as NOT_INITIALIZED,
                      *  and if it's a fake input parameter we don't use it at all.
                      */
                     if (var.kind != Variable.Kind.Input || (!var.fake && state != Variable.State.Not_Initialized))
                     {
                         inst.DeadVariables.Add(var, state);
                     }
                 }
             }
         }
     }
 }
示例#4
0
        /// <summary>
        /// Recursive function to set a Variable as alive in the proper places.
        /// </summary>
        /// <param name="var">the Variable we are dealing with</param>
        /// <param name="ins">Actual Instruction</param>
        private static void DealWithVariable(Variable var, Instruction ins, Variable.State state)
        {
            /*
             * This variable is used somewhere after this instruction, so it is alive here.
             *
             * DeadVariables - it contains the dead variables at the point of the given instruction
             */
            ins.DeadVariables.Remove(var);

            /*
             * GetPrecedingInstructions()
             *      - gives a list of the instructions followed by the actual instruction
             *      - if we are in the middle of the basic block, then it consists of only one instruction
             *      - if we are at the beginning of the basic block then it is the list of all
             *        the predecessing basic block's last instruction
             *      - if we are at the beginning of the first basic block (the one with no predecessors)
             *        then it is an empty list, meaning that we have nothing left to do here
             */
            List <Instruction> inslist = (state == Variable.State.Free) ? ins.GetPrecedingInstructions() : ins.GetFollowingInstructions();

            /*
             * Now we have that list of instructions, we should do the same thing we have done
             * to this instruction, assuming that it had not been done already.
             */
            foreach (Instruction i in inslist)
            {
                /*
                 * If the variable is not in the instruction's dead variables list, then it indicates
                 * that we have dealt with this instruction.
                 */
                if (i.DeadVariables.ContainsKey(var) && i.DeadVariables[var] == state)
                {
                    DealWithVariable(var, i, state);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Function to check state collisions for the RefreshNext() method.
        /// </summary>
        /// <param name="actual">The actual instruction.</param>
        /// <param name="var">The actual variable.</param>
        /// <param name="state">The state we want to refresh to.</param>
        /// <returns>The state we should refresh to.</returns>
        public static Variable.State CheckPrecedingStates(Instruction actual, Variable var, Variable.State state)
        {
            /*
             * We only have to do anything, if the instruction is on the beginning of
             * a basic block, because at that point states can collide.
             */
            if (!actual.Equals(actual.parent.Instructions.First()))
            {
                return(state);
            }

            /* So we get all states from the preceding instructions. */
            List <Variable.State> preceding_states = GetPrecedingStates(actual, var);

            /* We only have to do anything if there are more than one of those. */
            if (preceding_states.Count() > 1 && state == Variable.State.Free)
            {
                if (preceding_states.Contains(Variable.State.Not_Initialized))
                {
                    /* FREE meets NOT_INITIALIZED */
                    state = Variable.State.Not_Initialized;
                }
                else if (preceding_states.Contains(Variable.State.Filled))
                {
                    /* FREE meets FILLED */
                    state = Variable.State.Filled;
                }
            }
            return(state);
        }
示例#6
0
        /*
         * This function is called when we encounter a change in a dead variable's state.
         * So we want to push this change through all the instructions, and deal with
         * this variable only.
         *
         * However we can't just overwrite the statement without any check...
         */
        private static void RefreshNext(Instruction ins, Variable var, Variable.State state)
        {
            /*
             * If this instruction uses this variable as well, or this instruction
             * uses a pointer that points to this variable then its state must not
             * be changed, because it's perfect as it is right now.
             */
            if (ins.RefVariables.Contains(var))
            {
                /* This instruction uses this variable. */
                return;
            }

            /*
             * We have to do anything only if the variable is in this instruction is
             * dead, and it's state differs from the new state.
             */
            if (ins.DeadVariables.ContainsKey(var) &&   // This variable is dead.
                ins.DeadVariables[var] != state)        // The state differs.
            {
                foreach (Variable v in ins.RefVariables)
                {
                    if (ins.DeadPointers.ContainsKey(v) && ins.DeadPointers[v].PointsTo.Equals(var))
                    {
                        /* The instruction uses a pointer that points to this variable. */
                        return;
                    }
                }

                /*
                 * Now we are at the point, that maybe we have to change the state.
                 * Although it's not sure, because if the instruction has more than one predecessors,
                 * then the actual state might not change anything.
                 * For example: NOT_INITIALIZED meets FREE, or FREE meets FILLED.
                 *
                 * NOTE: we don't know right now what to do if NOT_INIT meets FILLED...
                 */
                state = DataAnalysis.CheckPrecedingStates(ins, var, state);

                ins.DeadVariables[var] = state;
                foreach (Instruction inst in ins.GetFollowingInstructions())
                {
                    RefreshNext(inst, var, state);
                }
            }

            /*
             * Another case for doing something when we pass a dead pointer with changed state.
             * In this case we do not have to look for variables pointing to that one.
             *
             * WARNING FOR FUTURE: (1)
             */
            if (ins.DeadPointers.ContainsKey(var) &&        // This is a dead pointer.
                ins.DeadPointers[var].State != state)       // The states differ.
            {
                /* Just like in the previous case, we have to check all the preceding states for collisions. */
                state = DataAnalysis.CheckPrecedingStates(ins, var, state);

                ins.DeadPointers[var].State = state;
                foreach (Instruction inst in ins.GetFollowingInstructions())
                {
                    RefreshNext(inst, var, state);
                }
            }
        }
示例#7
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="state">The state of the pointer.</param>
 /// <param name="var">The variable it points to.</param>
 public PointerData(Variable.State state, Variable var)
 {
     State    = state;
     PointsTo = var;
 }