/// <summary> /// Inserts two additional instructions for constant coverage /// </summary> /// <param name="const_inst">The instruction with a constant value</param> /// <param name="const_value">Numerical constant value to be covered</param> private static void ProcessConstant(Instruction const_inst, int const_value) { List <int> two_places = Randomizer.MultipleNumbers(2, 0, const_inst.parent.Instructions.BinarySearch(const_inst), true, true); Instruction nop1 = new Instruction(const_inst.parent); Instruction nop2 = new Instruction(const_inst.parent); // We assume that we need 4 bytes for each constant. Variable t1 = const_inst.parent.parent.NewLocalVariable(Variable.Purpose.ConstRecalculation, Objects.Common.MemoryRegionSize.Integer); Variable t2 = const_inst.parent.parent.NewLocalVariable(Variable.Purpose.ConstRecalculation, Objects.Common.MemoryRegionSize.Integer); int first_number = Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue); Instruction.ArithmeticOperationType op = first_number < const_value ? Instruction.ArithmeticOperationType.Addition : Instruction.ArithmeticOperationType.Subtraction; int second_number = Math.Abs(first_number - const_value); MakeInstruction.Copy(nop1, t2, null, first_number); MakeInstruction.FullAssignment(nop2, t1, t2, null, second_number, op); const_inst.parent.Instructions.Insert(two_places[1], nop2); const_inst.parent.Instructions.Insert(two_places[0], nop1); const_inst.ModifyConstInstruction(t1, const_value); }
/// <summary> /// Function to make an actual fake instruction out of a Nop. /// </summary> /// <param name="ins">The nop we want to work on.</param> private static void _GenerateFakeInstruction(Instruction ins) { /* First we get a left value. */ Variable leftvalue = GetLeftValueForInstruction(ins); /* Then we check how many variables can we use as right value. */ List <Variable> rightvalues = GetRandomRightValues(ins, 2); /* We random generate a statement type which we may not use according to the available right values. */ Objects.Common.StatementType statementType = (Objects.Common.StatementType)Randomizer.OneFromManyWithProbability( new int[3] { 25, 15, 60 }, Objects.Common.StatementType.Copy, Objects.Common.StatementType.UnaryAssignment, Objects.Common.StatementType.FullAssignment); /* * The number of the available right values determines which kind of instructions * can we generate. * * - If we don't have any, then we must make a Copy with a constant. * * - If we have one, and it's the same as the left value, then we have to make * a Unary Assignment. * * - If we have one, but it's different from the left value, then we can make * a Copy (1), a Unary Assignment (2) and a Full Assignment with a constant (3). * * - If we have two, we can make all these and a Full Assignment with two * variables. * * Another important thing is that we cannot fill the variables with a value * without using themselves (like t = t + 1) while inside a loop. */ switch (rightvalues.Count) { case 0: /* If we have no available right values, and we are in a loop, then we can't do anything. */ if (DataAnalysis.isLoopBody[ins.parent]) { return; } /* We don't have any right values, so we have to copy a constant value. */ else { MakeInstruction.Copy(ins, leftvalue, null, Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue)); } break; case 1: /* We choose Full Assignment, or rightvalue is the same as leftvalue, or we are in a loop body. */ if (DataAnalysis.isLoopBody[ins.parent] || leftvalue.Equals(rightvalues[0]) || statementType == Objects.Common.StatementType.FullAssignment || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { /* Here we random generate an operator. */ Instruction.ArithmeticOperationType op = (Instruction.ArithmeticOperationType)Randomizer.OneFromMany(Instruction.ArithmeticOperationType.Addition, Instruction.ArithmeticOperationType.Division, Instruction.ArithmeticOperationType.Multiplication, Instruction.ArithmeticOperationType.Subtraction); int num; if (op == Instruction.ArithmeticOperationType.Addition || op == Instruction.ArithmeticOperationType.Subtraction) { num = Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue); } else { /* * Here we generate an integer number which is the power of 2, and is * within the boundaries of GlobalMinNumber and GlobalMaxNumber. */ int min = Convert.ToInt32(Math.Ceiling(Math.Log(Common.GlobalMinValue, 2))); int max = Convert.ToInt32(Math.Floor(Math.Log(Common.GlobalMaxValue, 2))); int pow = Randomizer.SingleNumber(min, max); num = Convert.ToInt32(Math.Pow(2, pow)); } MakeInstruction.FullAssignment(ins, leftvalue, rightvalues.First(), null, num, op); } /* If we choose Unary Assignment. */ else if (statementType == Objects.Common.StatementType.UnaryAssignment) { MakeInstruction.UnaryAssignment(ins, leftvalue, rightvalues.First(), Instruction.UnaryOperationType.ArithmeticNegation); } /* If we choose Copy. */ else { MakeInstruction.Copy(ins, leftvalue, rightvalues.First(), null); } break; case 2: /* We make sure that the first right value isn't the same as the left value. */ if (leftvalue.Equals(rightvalues.First())) { Variable tmp = rightvalues[0]; rightvalues[0] = rightvalues[1]; rightvalues[1] = tmp; } /* * If we are in a loop body, then we can only make a full assignment like that: * t1 = t2 op t1 */ if (DataAnalysis.isLoopBody[ins.parent] || statementType == Objects.Common.StatementType.FullAssignment || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { /* Here we random generate an operator: + or - */ /* TODO: (efficient) * and / */ Instruction.ArithmeticOperationType op = (Instruction.ArithmeticOperationType)Randomizer.OneFromMany(Instruction.ArithmeticOperationType.Addition, Instruction.ArithmeticOperationType.Subtraction); if (DataAnalysis.isLoopBody[ins.parent] || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { MakeInstruction.FullAssignment(ins, leftvalue, rightvalues[0], leftvalue, null, op); } else { MakeInstruction.FullAssignment(ins, leftvalue, rightvalues[0], rightvalues[1], null, op); } } /* If we choose Copy. */ else if (statementType == Objects.Common.StatementType.Copy) { MakeInstruction.Copy(ins, leftvalue, rightvalues.First(), null); } /* If we choose Unary Assignment. */ else { MakeInstruction.UnaryAssignment(ins, leftvalue, rightvalues.First(), Instruction.UnaryOperationType.ArithmeticNegation); } break; } }