Example #1
0
        /// <summary>
        /// Keeps track of the block in which a "phi" node expression is defined. This is useful because the entry contraints of this block might provide
        /// additional information about the expression.
        /// </summary>
        internal void SetDefininingBlockFor(Instruction expression, AiBasicBlock <Instruction> block)
        {
            Contract.Requires(expression != null);
            Contract.Requires(block != null);

            this.definingBlockForExpression[expression] = block;
        }
Example #2
0
        /// <summary>
        /// Uses the SAT solver, if supplied, to check if the given Boolean expression is true in the context of the given block.
        /// Since this problem is not decidable, the solver may not be able to return an answer, in which case the return result is null
        /// rather than false or true. Likewise, if no solver is available, the result is null.
        /// </summary>
        public bool?CheckIfExpressionIsTrue(Instruction expression, AiBasicBlock <Instruction> block)
        {
            Contract.Requires(expression != null);
            Contract.Requires(block != null);

            var satSolverHelper = this.satSolverHelper;

            if (satSolverHelper == null)
            {
                return(null);
            }
            var context = block.SatSolverContext;

            if (context == null)
            {
                block.SatSolverContext = context = satSolverHelper.SatSolver.GetNewContext();
                Contract.Assume(context != null);
                var constraintsAtEntry = satSolverHelper.GetSolverExpressionFor(block.ConstraintsAtEntry);
                if (constraintsAtEntry != null)
                {
                    context.Add(constraintsAtEntry);
                }
            }
            var solverExpression = this.satSolverHelper.GetSolverExpressionFor(expression, block.ConstraintsAtEntry);

            context.MakeCheckPoint();
            if (!this.IsRecursive(expression))
            {
                satSolverHelper.AddPhiNodeConstraints(expression, context);
            }
            //context.MakeCheckPoint();
            context.Add(solverExpression);
            var result = context.Check();

            context.RestoreCheckPoint();
            if (result != null && !result.Value)
            {
                //context.RestoreCheckPoint();
                return(false); //The expression is never satisfied, so it is known to be false.
            }
            context.MakeCheckPoint();
            if (!this.IsRecursive(expression))
            {
                satSolverHelper.AddPhiNodeConstraints(expression, context);
            }
            context.AddInverse(solverExpression);
            result = context.Check();
            context.RestoreCheckPoint();
            //context.RestoreCheckPoint();

            if (result != null && !result.Value)
            {
                return(true);                           //The inverse expression is never satisfied, so the expression is known to be true.
            }
            return(null);
        }
Example #3
0
        /// <summary>
        /// Computes an inclusive numerical interval that contains the runtime value of the given expression. If no such interval can be found, the result is null.
        /// </summary>
        /// <param name="expression">The expression for which a containing interval is desired.</param>
        /// <param name="block">A block providing the context for the interval. The entry contraints of the block are used to narrow the interval if possible.</param>
        public Interval /*?*/ GetIntervalFor(Instruction expression, AiBasicBlock <Instruction> block)
        {
            Contract.Requires(expression != null);
            Contract.Requires(block != null);

            var interval = block.IntervalForExpression[expression];

            if (interval == this.dummyInterval)
            {
                return(null);
            }
            if (interval == null)
            {
                block.IntervalForExpression[expression] = this.dummyInterval;
                interval = Interval.TryToGetAsInterval(expression, block, null, null, this);
                block.IntervalForExpression[expression] = interval ?? this.dummyInterval;
            }
            return(interval);
        }
Example #4
0
        public IMetadataConstant /*?*/ GetCompileTimeConstantValueFor(Instruction expression, AiBasicBlock <Instruction> /*?*/ block = null)
        {
            Contract.Requires(expression != null);

            var result = this.compileTimeConstantValueForExpression[expression] as IMetadataConstant;

            if (result != null)
            {
                return(result);
            }
            var ce = this.GetCanonicalExpressionFor(expression);

            if (ce == null)
            {
                return(null);
            }
            result = this.compileTimeConstantValueForExpression[ce] as IMetadataConstant;
            if (result != null || block == null)
            {
                return(result);
            }
            result = block.ConstantForExpression[expression] as IMetadataConstant;
            if (result != null)
            {
                if (result == Dummy.Constant)
                {
                    return(null);
                }
                return(result);
            }
            var operand1 = ce.Operand1 as Instruction;

            if (operand1 == null)
            {
                return(null);
            }
            var operand2 = ce.Operand2 as Instruction;

            if (operand2 != null)
            {
                result = Evaluator.Evaluate(ce.Operation, operand1, operand2, this, block);
                block.ConstantForExpression[expression] = result ?? Dummy.Constant;
                if (result != null && result != Dummy.Constant)
                {
                    return(result);
                }
            }
            else
            {
                var operands2toN = ce.Operand2 as Instruction[];
                if (operands2toN != null)
                {
                    result = Evaluator.Evaluate(ce.Operation, operand1, operands2toN, this, block);
                    block.ConstantForExpression[expression] = result ?? Dummy.Constant;
                    if (result != null && result != Dummy.Constant)
                    {
                        return(result);
                    }
                }
            }
            return(null);
        }
Example #5
0
        private void PrintInstruction(Instruction instruction, AiBasicBlock <Instruction> block)
        {
            if (this.pdbReader != null)
            {
                foreach (IPrimarySourceLocation psloc in this.pdbReader.GetPrimarySourceLocationsFor(instruction.Operation.Location))
                {
                    PrintSourceLocation(psloc);
                    break;
                }
            }

            sourceEmitterOutput.Write("    ");
            sourceEmitterOutput.Write(instruction.Operation.Offset.ToString("x4"));
            sourceEmitterOutput.Write(", ");
            sourceEmitterOutput.Write(instruction.Operation.OperationCode.ToString());
            if (instruction.Operation.Value is uint)
            {
                sourceEmitterOutput.Write(" " + ((uint)instruction.Operation.Value).ToString("x4"));
            }
            sourceEmitterOutput.Write(", ");
            sourceEmitterOutput.Write(TypeHelper.GetTypeName(instruction.Type));
            if (instruction.Operation.Value != null)
            {
                sourceEmitterOutput.Write(", ");
                sourceEmitterOutput.Write(instruction.Operation.Value.ToString());
            }
            if (instruction.Operand1 != null)
            {
                sourceEmitterOutput.Write(", ");
                this.PrintFlowFrom(instruction.Operand1);
            }
            var i2 = instruction.Operand2 as Instruction;

            if (i2 != null)
            {
                sourceEmitterOutput.Write(", ");
                this.PrintFlowFrom(i2);
            }
            else
            {
                var i2a = instruction.Operand2 as Instruction[];
                if (i2a != null)
                {
                    foreach (var i2e in i2a)
                    {
                        sourceEmitterOutput.Write(", ");
                        this.PrintFlowFrom(i2e);
                    }
                }
            }
            sourceEmitterOutput.WriteLine("");
            if (this.valueMappings != null)
            {
                var constVal = this.valueMappings.GetCompileTimeConstantValueFor(instruction, block);
                if (constVal != null)
                {
                    if (constVal is Dummy)
                    {
                        sourceEmitterOutput.WriteLine("      operation always fails to produce a value");
                    }
                    else
                    {
                        sourceEmitterOutput.Write("      pushes constant: ");
                        sourceEmitterOutput.WriteLine((constVal.Value ?? "null").ToString());
                    }
                }
                else
                {
                    var canonicalExpr = this.valueMappings.GetCanonicalExpressionFor(instruction);
                    if (canonicalExpr != null)
                    {
                        sourceEmitterOutput.Write("      canonical expression: ");
                        this.PrintExpression(canonicalExpr);
                        sourceEmitterOutput.WriteLine();
                        var interval = this.valueMappings.GetIntervalFor(canonicalExpr, block);
                        if (interval != null)
                        {
                            sourceEmitterOutput.Write("      interval: ");
                            this.PrintInterval(interval);
                            sourceEmitterOutput.WriteLine();
                        }
                        if (instruction.Type.TypeCode == PrimitiveTypeCode.Boolean)
                        {
                            var isTrue = this.valueMappings.CheckIfExpressionIsTrue(canonicalExpr, block);
                            if (isTrue.HasValue)
                            {
                                sourceEmitterOutput.WriteLine("      is always " + isTrue.Value);
                            }
                        }
                    }
                }
            }
        }
Example #6
0
        private void PrintBlock(AiBasicBlock <Instruction> block)
        {
            sourceEmitterOutput.WriteLine("start of basic block " + block.Offset.ToString("x4"));
            if (this.cfgQueries != null)
            {
                var immediateDominator = this.cfgQueries.ImmediateDominator(block);
                sourceEmitterOutput.WriteLine("  immediate dominator " + immediateDominator.Offset.ToString("x4"));
                foreach (var predecessor in this.cfgQueries.PredeccessorsFor(block))
                {
                    sourceEmitterOutput.WriteLine("  predecessor block " + predecessor.Offset.ToString("x4"));
                }
            }
            if (block.Joins != null)
            {
                sourceEmitterOutput.WriteLine("  joins:");
                foreach (var join in block.Joins)
                {
                    sourceEmitterOutput.Write("    " + join.NewLocal + " = " + this.GetLocalOrParameterName(join.OriginalLocal) + ", via join(");
                    sourceEmitterOutput.Write(join.Join1.Name.Value);
                    if (join.Join2 != null)
                    {
                        sourceEmitterOutput.Write(", " + join.Join2.Name.Value);
                    }
                    if (join.OtherJoins != null)
                    {
                        foreach (var otherJoin in join.OtherJoins)
                        {
                            sourceEmitterOutput.Write(", " + otherJoin.Name.Value);
                        }
                    }
                    sourceEmitterOutput.WriteLine(")");
                }
            }
            sourceEmitterOutput.WriteLine("  Initial stack:");
            foreach (var instruction in block.OperandStack)
            {
                sourceEmitterOutput.Write("    " + TypeHelper.GetTypeName(instruction.Type));
                sourceEmitterOutput.Write(' ');
                this.PrintPhiNode(instruction);
                sourceEmitterOutput.WriteLine();
            }
            sourceEmitterOutput.WriteLine();

            if (block.ConstraintsAtEntry.Count > 0)
            {
                sourceEmitterOutput.WriteLine("  Initial constraints:");
                bool noConstraints = true;
                foreach (var constraintList in block.ConstraintsAtEntry)
                {
                    if (constraintList == null)
                    {
                        continue;
                    }
                    foreach (var constraint in constraintList)
                    {
                        if (constraint == null)
                        {
                            continue;
                        }
                        noConstraints = false;
                        break;
                    }
                }
                if (noConstraints)
                {
                    sourceEmitterOutput.WriteLine();
                }
                else
                {
                    bool firstList = true;
                    foreach (var constraintList in block.ConstraintsAtEntry)
                    {
                        if (firstList)
                        {
                            firstList = false;
                        }
                        else
                        {
                            sourceEmitterOutput.WriteLine("    or");
                        }
                        var firstConstraint = true;
                        if (constraintList != null)
                        {
                            foreach (var constraint in constraintList)
                            {
                                if (constraint == null)
                                {
                                    continue;
                                }
                                if (firstConstraint)
                                {
                                    firstConstraint = false;
                                }
                                else
                                {
                                    sourceEmitterOutput.WriteLine("      and");
                                }
                                sourceEmitterOutput.Write("        ");
                                this.PrintExpression(constraint);
                                sourceEmitterOutput.WriteLine();
                            }
                        }
                        if (firstConstraint)
                        {
                            sourceEmitterOutput.WriteLine("        none");
                        }
                    }
                }
            }

            sourceEmitterOutput.WriteLine("  Instructions: offset, opcode, type, instructions that flow into this");
            foreach (var instruction in block.Instructions)
            {
                this.PrintInstruction(instruction, block);
            }

            int i = 0;

            foreach (var successor in this.cdfg.SuccessorsFor(block))
            {
                sourceEmitterOutput.Write("  successor block " + successor.Offset.ToString("x4"));
                if (this.profileReader != null)
                {
                    uint count = this.ReadCountFromProfile();
                    sourceEmitterOutput.Write(" traversed " + count + " times");
                }
                sourceEmitterOutput.WriteLine();
                if (block.ConstraintsAtExit.Count > i)
                {
                    sourceEmitterOutput.WriteLine("  constraints at successor edge");
                    sourceEmitterOutput.Write("    ");
                    var  constraintList = block.ConstraintsAtExit[i];
                    bool first          = true;
                    foreach (var constraint in constraintList)
                    {
                        if (constraint == null)
                        {
                            continue;
                        }
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            sourceEmitterOutput.Write(" and ");
                        }
                        this.PrintExpression(constraint);
                    }
                    sourceEmitterOutput.WriteLine();
                }
                i++;
            }
            sourceEmitterOutput.WriteLine("end of basic block");
            sourceEmitterOutput.WriteLine();
        }
Example #7
0
    private void PrintBlock(AiBasicBlock<Instruction> block) {
      sourceEmitterOutput.WriteLine("start of basic block "+block.Offset.ToString("x4"));
      if (this.cfgQueries != null) {
        var immediateDominator = this.cfgQueries.ImmediateDominator(block);
        sourceEmitterOutput.WriteLine("  immediate dominator "+immediateDominator.Offset.ToString("x4"));
        foreach (var predecessor in this.cfgQueries.PredeccessorsFor(block)) {
          sourceEmitterOutput.WriteLine("  predecessor block "+predecessor.Offset.ToString("x4"));
        }
      }
      if (block.Joins != null) {
        sourceEmitterOutput.WriteLine("  joins:");
        foreach (var join in block.Joins) {
          sourceEmitterOutput.Write("    "+join.NewLocal+" = " + this.GetLocalOrParameterName(join.OriginalLocal)+", via join(");
          sourceEmitterOutput.Write(join.Join1.Name.Value);
          if (join.Join2 != null) sourceEmitterOutput.Write(", "+join.Join2.Name.Value);
          if (join.OtherJoins != null)
            foreach (var otherJoin in join.OtherJoins) sourceEmitterOutput.Write(", "+otherJoin.Name.Value);
          sourceEmitterOutput.WriteLine(")");
        }
      }
      sourceEmitterOutput.WriteLine("  Initial stack:");
      foreach (var instruction in block.OperandStack) {
        sourceEmitterOutput.Write("    "+TypeHelper.GetTypeName(instruction.Type));
        sourceEmitterOutput.Write(' ');
        this.PrintPhiNode(instruction);
        sourceEmitterOutput.WriteLine();
      }
      sourceEmitterOutput.WriteLine();

      if (block.ConstraintsAtEntry.Count > 0) {
        sourceEmitterOutput.WriteLine("  Initial constraints:");
        bool noConstraints = true;
        foreach (var constraintList in block.ConstraintsAtEntry) {
          if (constraintList == null) continue;
          foreach (var constraint in constraintList) {
            if (constraint == null) continue;
            noConstraints = false;
            break;
          }
        }
        if (noConstraints) {
          sourceEmitterOutput.WriteLine();
        } else {
          bool firstList = true;
          foreach (var constraintList in block.ConstraintsAtEntry) {
            if (firstList) firstList = false; else sourceEmitterOutput.WriteLine("    or");
            var firstConstraint = true;
            if (constraintList != null) {
              foreach (var constraint in constraintList) {
                if (constraint == null) continue;
                if (firstConstraint) firstConstraint = false; else sourceEmitterOutput.WriteLine("      and");
                sourceEmitterOutput.Write("        ");
                this.PrintExpression(constraint);
                sourceEmitterOutput.WriteLine();
              }
            }
            if (firstConstraint) sourceEmitterOutput.WriteLine("        none");
          }
        }
      }

      sourceEmitterOutput.WriteLine("  Instructions: offset, opcode, type, instructions that flow into this");
      foreach (var instruction in block.Instructions)
        this.PrintInstruction(instruction, block);

      int i = 0;
      foreach (var successor in this.cdfg.SuccessorsFor(block)) {
        sourceEmitterOutput.Write("  successor block "+successor.Offset.ToString("x4"));
        if (this.profileReader != null) {
          uint count = this.ReadCountFromProfile();
          sourceEmitterOutput.Write(" traversed "+count+" times");
        }
        sourceEmitterOutput.WriteLine();
        if (block.ConstraintsAtExit.Count > i) {
          sourceEmitterOutput.WriteLine("  constraints at successor edge");
          sourceEmitterOutput.Write("    ");
          var constraintList = block.ConstraintsAtExit[i];
          bool first = true;
          foreach (var constraint in constraintList) {
            if (constraint == null) continue;
            if (first) first = false; else sourceEmitterOutput.Write(" and ");
            this.PrintExpression(constraint);
          }
          sourceEmitterOutput.WriteLine();
        }
        i++;
      }
      sourceEmitterOutput.WriteLine("end of basic block");
      sourceEmitterOutput.WriteLine();
    }
Example #8
0
    private void PrintInstruction(Instruction instruction, AiBasicBlock<Instruction> block) {
      if (this.pdbReader != null) {
        foreach (IPrimarySourceLocation psloc in this.pdbReader.GetPrimarySourceLocationsFor(instruction.Operation.Location)) {
          PrintSourceLocation(psloc);
          break;
        }
      }

      sourceEmitterOutput.Write("    ");
      sourceEmitterOutput.Write(instruction.Operation.Offset.ToString("x4"));
      sourceEmitterOutput.Write(", ");
      sourceEmitterOutput.Write(instruction.Operation.OperationCode.ToString());
      if (instruction.Operation.Value is uint)
        sourceEmitterOutput.Write(" "+((uint)instruction.Operation.Value).ToString("x4"));
      sourceEmitterOutput.Write(", ");
      sourceEmitterOutput.Write(TypeHelper.GetTypeName(instruction.Type));
      if (instruction.Operation.Value != null) {
        sourceEmitterOutput.Write(", ");
        sourceEmitterOutput.Write(instruction.Operation.Value.ToString());
      }
      if (instruction.Operand1 != null) {
        sourceEmitterOutput.Write(", ");
        this.PrintFlowFrom(instruction.Operand1);
      }
      var i2 = instruction.Operand2 as Instruction;
      if (i2 != null) {
        sourceEmitterOutput.Write(", ");
        this.PrintFlowFrom(i2);
      } else {
        var i2a = instruction.Operand2 as Instruction[];
        if (i2a != null) {
          foreach (var i2e in i2a) {
            sourceEmitterOutput.Write(", ");
            this.PrintFlowFrom(i2e);
          }
        }
      }
      sourceEmitterOutput.WriteLine("");
      if (this.valueMappings != null) {
        var constVal = this.valueMappings.GetCompileTimeConstantValueFor(instruction, block);
        if (constVal != null) {
          if (constVal is Dummy)
            sourceEmitterOutput.WriteLine("      operation always fails to produce a value");
          else {
            sourceEmitterOutput.Write("      pushes constant: ");
            sourceEmitterOutput.WriteLine((constVal.Value??"null").ToString());
          }
        } else {
          var canonicalExpr = this.valueMappings.GetCanonicalExpressionFor(instruction);
          if (canonicalExpr != null) {
            sourceEmitterOutput.Write("      canonical expression: ");
            this.PrintExpression(canonicalExpr);
            sourceEmitterOutput.WriteLine();
            var interval = this.valueMappings.GetIntervalFor(canonicalExpr, block);
            if (interval != null) {
              sourceEmitterOutput.Write("      interval: ");
              this.PrintInterval(interval);
              sourceEmitterOutput.WriteLine();
            }
            if (instruction.Type.TypeCode == PrimitiveTypeCode.Boolean) {
              var isTrue = this.valueMappings.CheckIfExpressionIsTrue(canonicalExpr, block);
              if (isTrue.HasValue) {
                sourceEmitterOutput.WriteLine("      is always "+isTrue.Value);
              }
            }
          }
        }
      }
    }