internal ISatExpressionWrapper GetSolverExpressionFor(Instruction expression, List <List <Instruction> > listOfConjunctions = null) { Contract.Requires(expression != null); Contract.Ensures(Contract.Result <ISatExpressionWrapper>() != null); var wrapper = this.expressionMap[expression] as ISatExpressionWrapper; if (wrapper == null) { if (!this.mappings.IsRecursive(expression)) { expression = Simplifier.HoistPhiNodes(expression); } if (listOfConjunctions != null && expression.Type.TypeCode == PrimitiveTypeCode.Boolean && expression.Operation.OperationCode == OperationCode.Nop && expression.Operation.Value is INamedEntity) { wrapper = this.GetSolverExpressionForBooleanPhiNode(expression, listOfConjunctions); } else { var operand1 = expression.Operand1 as Instruction; if (operand1 == null) { wrapper = this.satSolver.MakeExpression(expression.Operation, expression.Type); } else { var operand1wrapper = this.GetSolverExpressionFor(operand1, listOfConjunctions); var operand2 = expression.Operand2 as Instruction; if (operand2 == null) { wrapper = this.satSolver.MakeExpression(expression.Operation, expression.Type, operand1wrapper); } else { var operand2wrapper = this.GetSolverExpressionFor(operand2, listOfConjunctions); wrapper = this.satSolver.MakeExpression(expression.Operation, expression.Type, operand1wrapper, operand2wrapper); } } } if (wrapper == null) { wrapper = this.satSolver.Dummy; } Contract.Assume(wrapper != null); this.expressionMap[expression] = wrapper; } return(wrapper); }
internal Instruction GetCanonicalExpression(Instruction naryInstruction, Instruction operand1, Instruction /*?*/ operand2, Instruction[] /*?*/ operands2andBeyond) { Contract.Requires(naryInstruction != null); Contract.Requires(operand1 != null); var expression = this.dummyInstruction; expression.Operation = naryInstruction.Operation; expression.Operand1 = this.GetCanonicalExpression(Simplifier.Simplify(operand1, this.mappings, this)); if (operand2 != null) { expression.Operand2 = this.GetCanonicalExpression(Simplifier.Simplify(operand2, this.mappings, this)); } else if (operands2andBeyond != null) { var n = operands2andBeyond.Length; var canonOps = new Instruction[n]; for (int i = 0; i < n; i++) { Contract.Assume(operands2andBeyond[i] != null); canonOps[i] = this.GetCanonicalExpression(Simplifier.Simplify(operands2andBeyond[i], this.mappings, this)); } expression.Operand2 = canonOps; } expression.Type = naryInstruction.Type; Instruction result; if (!this.cache.TryGetValue(expression, out result)) { this.cache[expression] = result = expression; this.dummyInstruction = new Instruction(); } Contract.Assume(result != null); return(result); }
/// <summary> /// If the cache contains an expression with an Operation structurally equivalent to unaryInstruction.Operation and Operand1 structurally equivalent to /// operand1, then return that expression. Otherwise construct such an expression, add it to the cache and return it. /// </summary> /// <param name="unaryInstruction">An instruction with a single operand.</param> /// <param name="operand1">The already canonicalized version of unaryInstruction.Operand1, if available, otherwise unaryInstruction.Operand1.</param> internal Instruction GetCanonicalExpression(Instruction unaryInstruction, Instruction operand1) { Contract.Requires(unaryInstruction != null); Contract.Requires(operand1 != null); Contract.Ensures(Contract.Result <Instruction>() != null); var expression = this.dummyInstruction; expression.Operation = unaryInstruction.Operation; expression.Operand1 = operand1; expression.Operand2 = null; expression.Type = unaryInstruction.Type; Instruction result; if (!this.cache.TryGetValue(expression, out result)) { result = this.GetCanonicalExpression(Simplifier.SimplifyUnary(expression, this.mappings, this)); this.cache[expression] = result; this.dummyInstruction = new Instruction(); } Contract.Assume(result != null); return(result); }