/// <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; }
/// <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); }
/// <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); }
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); }
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); } } } } } }
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(); }
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(); }
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); } } } } } }