public Bpl.Expr FromUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct) { if (boogieType == UnionType || boogieType == RefType) { return(expr); } Bpl.Function conversion = null; if (boogieType == Bpl.Type.Bool) { conversion = this.Union2Bool; } else if (boogieType == Bpl.Type.Int) { conversion = this.Union2Int; } else if (boogieType == RealType) { conversion = this.Union2Real; } else { throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); } var callExpr = new Bpl.NAryExpr( tok, new Bpl.FunctionCall(conversion), new List <Bpl.Expr>(new Bpl.Expr[] { expr }) ); callExpr.Type = boogieType; return(callExpr); }
/// <summary> /// Returns the BPL expression that corresponds to the value of the dynamic type /// of the object represented by the expression <paramref name="o"/>. /// </summary> public Bpl.Expr DynamicType(Bpl.Expr o) { // $DymamicType(o) var callDynamicType = new Bpl.NAryExpr( o.tok, new Bpl.FunctionCall(this.DynamicTypeFunction), new List <Bpl.Expr>(new Bpl.Expr[] { o }) ); return(callDynamicType); }
private static Bpl.Expr GetLit(Bpl.Expr expr) { if (expr is Bpl.NAryExpr) { Bpl.NAryExpr app = (Bpl.NAryExpr)expr; switch (app.Fun.FunctionName) { case "LitInt": case "LitReal": case "Lit": return(app.Args[0]); default: break; } } return(null); }
/// <summary> /// Returns the (typed) BPL expression that corresponds to the value of the field /// <paramref name="f"/> belonging to the object <paramref name="o"/> (which must be non-null). /// </summary> /// <param name="o">The expression that represents the object to be dereferenced. /// </param> /// <param name="f">The field that is used to dereference the object <paramref name="o"/>. /// </param> public override Bpl.Expr ReadHeap(Bpl.Expr /*?*/ o, Bpl.Expr f, AccessType accessType, Bpl.Type unboxType) { Debug.Assert(o != null); Bpl.NAryExpr callRead; if (accessType == AccessType.Struct || accessType == AccessType.Heap) { callRead = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Read), new List <Bpl.Expr>(new Bpl.Expr[] { new Bpl.IdentifierExpr(f.tok, this.HeapVariable), o, f })); } else { callRead = Bpl.Expr.Select(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f); } // wrap it in the right conversion function var callExpr = FromUnion(f.tok, unboxType, callRead, false); return(callExpr); }
/// <summary> /// Returns the BPL command that corresponds to assigning the value <paramref name="value"/> /// to the field <paramref name="f"/> of the object <paramref name="o"/> (which should be non-null). /// </summary> public override void WriteHeap(Bpl.IToken tok, Bpl.Expr /*?*/ o, Bpl.Expr f, Bpl.Expr value, AccessType accessType, Bpl.Type boxType, Bpl.StmtListBuilder builder) { Debug.Assert(o != null); Bpl.IdentifierExpr h; Bpl.NAryExpr callWrite; var callConversion = ToUnion(f.tok, boxType, value, false, builder); if (accessType == AccessType.Struct || accessType == AccessType.Heap) { h = Bpl.Expr.Ident(HeapVariable); callWrite = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Write), new List <Bpl.Expr>(new Bpl.Expr[] { h, o, f, callConversion })); } else { h = Bpl.Expr.Ident(ArrayContentsVariable); callWrite = Bpl.Expr.Store(Bpl.Expr.Ident(ArrayContentsVariable), o, Bpl.Expr.Store(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f, callConversion)); } builder.Add(Bpl.Cmd.SimpleAssign(f.tok, h, callWrite)); }
public Bpl.Expr ToUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct, Bpl.StmtListBuilder builder) { if (boogieType == UnionType || boogieType == RefType) { return(expr); } Bpl.Expr callConversion; if (boogieType == Bpl.Type.Bool) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Bool2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Bool), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else if (boogieType == Bpl.Type.Int) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Int2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Int), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else if (boogieType == RealType) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Real2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Real), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else { throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); } return(callConversion); }
private void TraverseBitwiseAndRightOperandAndDoOperation(IExpression expression) { Contract.Assume(expression is IBitwiseAnd); var bitwiseAnd = (IBitwiseAnd)expression; this.Traverse(bitwiseAnd.RightOperand); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); Bpl.Expr e; if (bitwiseAnd.Type.TypeCode == PrimitiveTypeCode.Boolean) { e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.And, lexp, rexp); } else { if (lexp.Type != Bpl.Type.Int || rexp.Type != Bpl.Type.Int) throw new TranslationException("BitwiseAnd called in a non-boolean context, but at least one argument is not an integer!"); e = new Bpl.NAryExpr( bitwiseAnd.Token(), new Bpl.FunctionCall(this.sink.Heap.BitwiseAnd), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); } TranslatedExpressions.Push(e); }
public override void TraverseChildren(IUnaryNegation unaryNegation) { base.TraverseChildren(unaryNegation); Bpl.Expr exp = TranslatedExpressions.Pop(); Bpl.Expr e, zero, realZero; zero = Bpl.Expr.Literal(0); realZero = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {zero})); switch (unaryNegation.Type.TypeCode) { case PrimitiveTypeCode.Float32: case PrimitiveTypeCode.Float64: e = new Bpl.NAryExpr( unaryNegation.Token(), new Bpl.FunctionCall(this.sink.Heap.RealMinus), new List<Bpl.Expr>(new Bpl.Expr[] {realZero, exp}) ); break; default: e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Sub, Bpl.Expr.Literal(0), exp); break; } TranslatedExpressions.Push(e); }
public override void TraverseChildren(IConversion conversion) { var tok = conversion.ValueToConvert.Token(); this.Traverse(conversion.ValueToConvert); var boogieTypeOfValue = this.sink.CciTypeToBoogie(conversion.ValueToConvert.Type); var boogieTypeToBeConvertedTo = this.sink.CciTypeToBoogie(conversion.TypeAfterConversion); if (boogieTypeOfValue == boogieTypeToBeConvertedTo && !TranslationHelper.IsStruct(conversion.ValueToConvert.Type) && !TranslationHelper.IsStruct(conversion.TypeAfterConversion)) { // then this conversion is a nop, just ignore it return; } var nameOfTypeToConvert = TypeHelper.GetTypeName(conversion.ValueToConvert.Type); var nameOfTypeToBeConvertedTo = TypeHelper.GetTypeName(conversion.TypeAfterConversion); var msg = String.Format("Can't convert '{0}' to '{1}'", nameOfTypeToConvert, nameOfTypeToBeConvertedTo); var exp = TranslatedExpressions.Pop(); if (boogieTypeOfValue == this.sink.Heap.UnionType && boogieTypeToBeConvertedTo != this.sink.Heap.RefType) { var e = this.sink.Heap.FromUnion(tok, boogieTypeToBeConvertedTo, exp, false); TranslatedExpressions.Push(e); return; } if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) { Bpl.Expr e; if (boogieTypeOfValue == this.sink.Heap.RefType) e = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Union), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); else e = this.sink.Heap.ToUnion(tok, boogieTypeOfValue, exp, false, StmtTraverser.StmtBuilder); TranslatedExpressions.Push(e); return; } if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType && TranslationHelper.IsStruct(conversion.TypeAfterConversion) && boogieTypeOfValue == this.sink.Heap.RefType) { // REVIEW: This also applies to conversions from one struct type to another! TranslatedExpressions.Push(exp); return; } if (boogieTypeToBeConvertedTo == Bpl.Type.Bool) { Bpl.Expr expr; if (boogieTypeOfValue == Bpl.Type.Int) { expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, exp, Bpl.Expr.Literal(0)); } else if (boogieTypeOfValue == this.sink.Heap.RefType) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Bool), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); } else if (boogieTypeOfValue == this.sink.Heap.RealType) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, expr, Bpl.Expr.Literal(0)); } else if (boogieTypeOfValue == this.sink.Heap.UnionType) { expr = this.sink.Heap.FromUnion(tok, Bpl.Type.Bool, exp, false); } else { throw new NotImplementedException(msg); } TranslatedExpressions.Push(expr); return; } if (boogieTypeToBeConvertedTo == Bpl.Type.Int) { Bpl.Expr expr; if (boogieTypeOfValue == Bpl.Type.Bool) { expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)})); } else if (boogieTypeOfValue == this.sink.Heap.RefType) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); } else if (boogieTypeOfValue == this.sink.Heap.RealType) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); } else if (boogieTypeOfValue == this.sink.Heap.UnionType) { expr = this.sink.Heap.FromUnion(Bpl.Token.NoToken, Bpl.Type.Int, exp, false); } else { throw new NotImplementedException(msg); } TranslatedExpressions.Push(expr); return; } if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType) { // var a = BoxFromXXX(exp); Bpl.Variable a = this.sink.CreateFreshLocal(conversion.TypeAfterConversion); Bpl.Procedure boxOperator; if (boogieTypeOfValue == Bpl.Type.Bool) boxOperator = this.sink.Heap.BoxFromBool; else if (boogieTypeOfValue == Bpl.Type.Int) boxOperator = this.sink.Heap.BoxFromInt; else if (boogieTypeOfValue == this.sink.Heap.RealType) boxOperator = this.sink.Heap.BoxFromReal; else if (TranslationHelper.IsStruct(conversion.ValueToConvert.Type)) { // Boxing a struct implicitly makes a copy of the struct var typeOfValue = conversion.ValueToConvert.Type; var proc = this.sink.FindOrCreateProcedureForStructCopy(typeOfValue); var bplLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(typeOfValue)); var cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { exp, }, new List<Bpl.IdentifierExpr> { bplLocal, }); this.StmtTraverser.StmtBuilder.Add(cmd); TranslatedExpressions.Push(bplLocal); return; } else { if (boogieTypeOfValue != this.sink.Heap.UnionType) throw new NotImplementedException(msg); boxOperator = this.sink.Heap.BoxFromUnion; } var name = boxOperator.Name; this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, name, new List<Bpl.Expr>(new Bpl.Expr[] {exp}), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)}))); TranslatedExpressions.Push(Bpl.Expr.Ident(a)); return; } if (boogieTypeToBeConvertedTo == this.sink.Heap.RealType) { Bpl.Expr expr; if (boogieTypeOfValue == Bpl.Type.Bool) { expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)})); expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {expr})); } else if (boogieTypeOfValue == Bpl.Type.Int) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {exp})); } else if (boogieTypeOfValue == this.sink.Heap.RefType) { expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Real), new List<Bpl.Expr>(new Bpl.Expr[] { exp })); } else if (boogieTypeOfValue == this.sink.Heap.UnionType) { expr = this.sink.Heap.FromUnion(tok, this.sink.Heap.RealType, exp, false); } else { throw new NotImplementedException(msg); } TranslatedExpressions.Push(expr); return; } //if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) { // Bpl.Function func; // if (boogieTypeOfValue == Bpl.Type.Bool) { // func = this.sink.Heap.Bool2Union; // } // else if (boogieTypeOfValue == Bpl.Type.Int) { // func = this.sink.Heap.Int2Union; // } // else if (boogieTypeOfValue == this.sink.Heap.RefType) { // func = this.sink.Heap.Ref2Union; // } // else if (boogieTypeOfValue == this.sink.Heap.RealType) { // func = this.sink.Heap.Real2Union; // } // else { // throw new NotImplementedException(msg); // } // var boxExpr = new Bpl.NAryExpr(conversion.Token(), new Bpl.FunctionCall(func), new List<Bpl.Expr>(exp)); // TranslatedExpressions.Push(boxExpr); // return; //} }
public override void TraverseChildren(ICastIfPossible castIfPossible) { base.Traverse(castIfPossible.ValueToCast); var exp = TranslatedExpressions.Pop(); var e = this.sink.FindOrCreateTypeReferenceInCodeContext(castIfPossible.TargetType); var callAs = new Bpl.NAryExpr( castIfPossible.Token(), new Bpl.FunctionCall(this.sink.Heap.AsFunction), new List<Bpl.Expr>(new Bpl.Expr[] {exp, e}) ); TranslatedExpressions.Push(callAs); return; }
public override void TraverseChildren(ILessThanOrEqual lessEqual) { base.TraverseChildren(lessEqual); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); Bpl.Expr e; switch (lessEqual.LeftOperand.Type.TypeCode) { case PrimitiveTypeCode.Float32: case PrimitiveTypeCode.Float64: e = new Bpl.NAryExpr( lessEqual.Token(), new Bpl.FunctionCall(this.sink.Heap.RealLessThanOrEqual), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); break; default: e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Le, lexp, rexp); break; } TranslatedExpressions.Push(e); }
private void TraverseExclusiveOrRightOperandAndDoOperation(IExpression expression) { Contract.Assume(expression is IExclusiveOr); var exclusiveOr = (IExclusiveOr)expression; this.Traverse(exclusiveOr.RightOperand); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); var e = new Bpl.NAryExpr( exclusiveOr.Token(), new Bpl.FunctionCall(this.sink.Heap.BitwiseExclusiveOr), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); TranslatedExpressions.Push(e); }
/// <summary> /// Returns the (typed) BPL expression that corresponds to the value of the field /// <paramref name="f"/> belonging to the object <paramref name="o"/> (which must be non-null). /// </summary> /// <param name="o">The expression that represents the object to be dereferenced. /// </param> /// <param name="f">The field that is used to dereference the object <paramref name="o"/>. /// </param> public override Bpl.Expr ReadHeap(Bpl.Expr/*?*/ o, Bpl.Expr f, AccessType accessType, Bpl.Type unboxType) { Debug.Assert(o != null); Bpl.NAryExpr callRead; if (accessType == AccessType.Struct || accessType == AccessType.Heap) callRead = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Read), new List<Bpl.Expr>(new Bpl.Expr[] {new Bpl.IdentifierExpr(f.tok, this.HeapVariable), o, f})); else callRead = Bpl.Expr.Select(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f); // wrap it in the right conversion function var callExpr = FromUnion(f.tok, unboxType, callRead, false); return callExpr; }
private void TraverseBitwiseOrRightOperandAndDoOperation(IExpression expression) { Contract.Assume(expression is IBitwiseOr); var bitwiseOr = (IBitwiseOr)expression; this.Traverse(bitwiseOr.RightOperand); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); Bpl.Expr e; if (bitwiseOr.Type.TypeCode == PrimitiveTypeCode.Boolean) { e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Or, lexp, rexp); } else { e = new Bpl.NAryExpr( bitwiseOr.Token(), new Bpl.FunctionCall(this.sink.Heap.BitwiseOr), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); } TranslatedExpressions.Push(e); }
/// <summary> /// Returns the BPL command that corresponds to assigning the value <paramref name="value"/> /// to the field <paramref name="f"/> of the object <paramref name="o"/> (which should be non-null). /// </summary> public override void WriteHeap(Bpl.IToken tok, Bpl.Expr/*?*/ o, Bpl.Expr f, Bpl.Expr value, AccessType accessType, Bpl.Type boxType, Bpl.StmtListBuilder builder) { Debug.Assert(o != null); Bpl.IdentifierExpr h; Bpl.NAryExpr callWrite; var callConversion = ToUnion(f.tok, boxType, value, false, builder); if (accessType == AccessType.Struct || accessType == AccessType.Heap) { h = Bpl.Expr.Ident(HeapVariable); callWrite = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Write), new List<Bpl.Expr>(new Bpl.Expr[] {h, o, f, callConversion})); } else { h = Bpl.Expr.Ident(ArrayContentsVariable); callWrite = Bpl.Expr.Store(Bpl.Expr.Ident(ArrayContentsVariable), o, Bpl.Expr.Store(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f, callConversion)); } builder.Add(Bpl.Cmd.SimpleAssign(f.tok, h, callWrite)); }
public override void TraverseChildren(IArrayIndexer arrayIndexer) { //if (!IsAtomicInstance(arrayIndexer.IndexedObject)) { // // Simplify the BE so that all nested dereferences and method calls are broken up into separate assignments to locals. // var se = ExpressionSimplifier.Simplify(this.sink, arrayIndexer); // this.Traverse(se); // return; //} this.Traverse(arrayIndexer.IndexedObject); Bpl.Expr arrayExpr = TranslatedExpressions.Pop(); var be = arrayIndexer.IndexedObject as IBoundExpression; if (be != null && be.Instance != null) { var l = this.sink.CreateFreshLocal(be.Type); var lhs = Bpl.Expr.Ident(l); var cmd = Bpl.Cmd.SimpleAssign(arrayIndexer.Token(), lhs, arrayExpr); this.StmtTraverser.StmtBuilder.Add(cmd); arrayExpr = lhs; } this.Traverse(arrayIndexer.Indices); int count = arrayIndexer.Indices.Count(); Bpl.Expr[] indexExprs = new Bpl.Expr[count]; for (int i = count; i > 0; i--) { indexExprs[i - 1] = TranslatedExpressions.Pop(); } Bpl.Expr indexExpr; if (indexExprs.Length == 1) { indexExpr = indexExprs[0]; } else { Bpl.Function f = this.sink.FindOrCreateNaryIntFunction(indexExprs.Length); indexExpr = new Bpl.NAryExpr(arrayIndexer.Token(), new Bpl.FunctionCall(f), new List<Bpl.Expr>(indexExprs)); } AssertOrAssumeNonNull(arrayIndexer.Token(), arrayExpr); this.TranslatedExpressions.Push(this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type))); }
public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFinallyStatement) { if (this.sink.Options.modelExceptions == 0) { this.Traverse(tryCatchFinallyStatement.TryBody); if (tryCatchFinallyStatement.FinallyBody != null) { this.Traverse(tryCatchFinallyStatement.FinallyBody); } return; } this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry)); this.Traverse(tryCatchFinallyStatement.TryBody); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1))); StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) }))); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement)); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef))); List <Bpl.StmtList> catchStatements = new List <Bpl.StmtList>(); List <Bpl.Expr> typeReferences = new List <Bpl.Expr>(); this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch)); foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses) { typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true)); StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext); if (catchClause.ExceptionContainer != Dummy.LocalVariable) { Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer); catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable))); } catchTraverser.Traverse(catchClause.Body); catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1))); catchTraverser.StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) }))); catchStatements.Insert(0, catchTraverser.StmtBuilder.Collect(catchClause.Token())); } Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false), TranslationHelper.BuildStmtList(new Bpl.ReturnCmd(Bpl.Token.NoToken)), null, null); Bpl.Expr dynTypeOfOperand = this.sink.Heap.DynamicType(Bpl.Expr.Ident(this.sink.LocalExcVariable)); for (int i = 0; i < catchStatements.Count; i++) { Bpl.Expr expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List <Bpl.Expr>(new Bpl.Expr[] { dynTypeOfOperand, typeReferences[i] })); elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, expr, catchStatements[i], elseIfCmd, null); } this.StmtBuilder.Add(elseIfCmd); this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable))); RaiseException(); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)); if (tryCatchFinallyStatement.FinallyBody != null) { this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally)); Bpl.Variable savedExcVariable = this.sink.CreateFreshLocal(this.sink.Heap.RefType); Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable))); this.Traverse(tryCatchFinallyStatement.FinallyBody); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable))); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); } GenerateDispatchContinuation(tryCatchFinallyStatement); StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement)); Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)); RaiseException(raiseExpr); }
private void TraverseMultiplicationRightOperandAndDoOperation(IExpression expression) { Contract.Assume(expression is IMultiplication); var multiplication = (IMultiplication)expression; this.Traverse(multiplication.RightOperand); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); Bpl.Expr e; switch (multiplication.Type.TypeCode) { case PrimitiveTypeCode.Float32: case PrimitiveTypeCode.Float64: e = new Bpl.NAryExpr( multiplication.Token(), new Bpl.FunctionCall(this.sink.Heap.RealTimes), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); break; default: e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Mul, lexp, rexp); break; } TranslatedExpressions.Push(e); }
public Bpl.Expr ToUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct, Bpl.StmtListBuilder builder) { if (boogieType == UnionType || boogieType == RefType) return expr; Bpl.Expr callConversion; if (boogieType == Bpl.Type.Bool) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Bool2Union), new List<Bpl.Expr>(new Bpl.Expr[] {expr})); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Bool), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else if (boogieType == Bpl.Type.Int) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {callConversion})), expr))); } else if (boogieType == RealType) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Real2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Real), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else { throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); } return callConversion; }
private void TraverseLeftShiftRightOperandAndDoOperation(IExpression expression) { Contract.Assume(expression is ILeftShift); var leftShift = (ILeftShift)expression; this.Traverse(leftShift.RightOperand); Bpl.Expr rexp = TranslatedExpressions.Pop(); Bpl.Expr lexp = TranslatedExpressions.Pop(); Bpl.Expr e = new Bpl.NAryExpr( leftShift.Token(), new Bpl.FunctionCall(this.sink.Heap.LeftShift), new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp}) ); TranslatedExpressions.Push(e); }
public Bpl.Expr FromUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct) { if (boogieType == UnionType || boogieType == RefType) return expr; Bpl.Function conversion = null; if (boogieType == Bpl.Type.Bool) conversion = this.Union2Bool; else if (boogieType == Bpl.Type.Int) conversion = this.Union2Int; else if (boogieType == RealType) conversion = this.Union2Real; else throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); var callExpr = new Bpl.NAryExpr( tok, new Bpl.FunctionCall(conversion), new List<Bpl.Expr>(new Bpl.Expr[] {expr}) ); callExpr.Type = boogieType; return callExpr; }
public override void TraverseChildren(ICheckIfInstance checkIfInstance) { var e = this.sink.FindOrCreateTypeReferenceInCodeContext(checkIfInstance.TypeToCheck); //var callTypeOf = new Bpl.NAryExpr( // checkIfInstance.Token(), // new Bpl.FunctionCall(this.sink.Heap.TypeOfFunction), // new List<Bpl.Expr>(new Bpl.IdentifierExpr(checkIfInstance.Token(), v)) // ); base.Traverse(checkIfInstance.Operand); var exp = TranslatedExpressions.Pop(); var dynTypeOfOperand = this.sink.Heap.DynamicType(exp); //var subtype = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Subtype, dynTypeOfOperand, e); var subtype = new Bpl.NAryExpr( Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List<Bpl.Expr>(new Bpl.Expr[] {dynTypeOfOperand, e}) ); var notnull = Bpl.Expr.Neq(exp, Bpl.Expr.Ident(this.sink.Heap.NullRef)); var and = Bpl.Expr.And(notnull, subtype); TranslatedExpressions.Push(and); return; }
/// <summary> /// Returns the BPL expression that corresponds to the value of the dynamic type /// of the object represented by the expression <paramref name="o"/>. /// </summary> public Bpl.Expr DynamicType(Bpl.Expr o) { // $DymamicType(o) var callDynamicType = new Bpl.NAryExpr( o.tok, new Bpl.FunctionCall(this.DynamicTypeFunction), new List<Bpl.Expr>(new Bpl.Expr[] {o}) ); return callDynamicType; }
public override void TraverseChildren(IOnesComplement onesComplement) { base.TraverseChildren(onesComplement); var exp = TranslatedExpressions.Pop(); var e = new Bpl.NAryExpr( onesComplement.Token(), new Bpl.FunctionCall(this.sink.Heap.BitwiseNegation), new List<Bpl.Expr>(new Bpl.Expr[] {exp}) ); TranslatedExpressions.Push(e); }
private void TranslateDelegateCreation(IMethodReference methodToCall, ITypeReference type, IExpression creationAST) { Bpl.IToken cloc = creationAST.Token(); var a = this.sink.CreateFreshLocal(creationAST.Type); ITypeDefinition unspecializedType = Microsoft.Cci.MutableContracts.ContractHelper.Unspecialized(type.ResolvedType).ResolvedType; IMethodDefinition unspecializedMethod = ResolveUnspecializedMethodOrThrow(methodToCall); sink.AddDelegate(unspecializedType, unspecializedMethod); Bpl.Constant constant = sink.FindOrCreateDelegateMethodConstant(unspecializedMethod); Bpl.Expr methodExpr = Bpl.Expr.Ident(constant); Bpl.Expr instanceExpr = TranslatedExpressions.Pop(); List<Bpl.Expr> typeParameterExprs = new List<Bpl.Expr>(); if (unspecializedMethod.IsStatic) { List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>(); Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType); foreach (ITypeReference typeReference in consolidatedTypeArguments) { typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference; if (methodInstanceReference != null) { foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) { typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } Bpl.Expr typeParameterExpr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.FindOrCreateNaryTypeFunction(typeParameterExprs.Count)), typeParameterExprs); this.StmtTraverser.StmtBuilder.Add( new Bpl.CallCmd(cloc, this.sink.DelegateCreate(unspecializedType), new List<Bpl.Expr>(new Bpl.Expr[] {methodExpr, instanceExpr, typeParameterExpr}), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)}))); TranslatedExpressions.Push(Bpl.Expr.Ident(a)); }
/// <summary> /// /// </summary> /// <param name="methodCall"></param> /// <remarks>Stub, This one really needs comments!</remarks> public override void TraverseChildren(IMethodCall methodCall) { var resolvedMethod = ResolveUnspecializedMethodOrThrow(methodCall.MethodToCall); Bpl.IToken methodCallToken = methodCall.Token(); if (this.sink.Options.getMeHere) { // TODO: Get a method reference so this isn't a string comparison? var methodName = MemberHelper.GetMethodSignature(methodCall.MethodToCall, NameFormattingOptions.None); if (methodName.Equals("GetMeHere.GetMeHere.Assert")) { // for now, just translate it as "assert e" this.Traverse(methodCall.Arguments.First()); Bpl.Expr e = this.TranslatedExpressions.Pop(); this.StmtTraverser.StmtBuilder.Add(new Bpl.AssertCmd(methodCallToken, e)); return; } } // Handle type equality specially when it is testing against a constant, i.e., o.GetType() == typeof(T) if (IsOperator(resolvedMethod) && !IsConversionOperator(resolvedMethod) && TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, this.sink.host.PlatformType.SystemType)) { // REVIEW: Assume the only operators on System.Type are == and != var typeToTest = methodCall.Arguments.ElementAtOrDefault(0) as ITypeOf; IMethodCall callToGetType; if (typeToTest == null) { typeToTest = methodCall.Arguments.ElementAtOrDefault(1) as ITypeOf; callToGetType = methodCall.Arguments.ElementAtOrDefault(0) as IMethodCall; } else { callToGetType = methodCall.Arguments.ElementAtOrDefault(1) as IMethodCall; } if (typeToTest != null && callToGetType != null && TypeHelper.TypesAreEquivalent(callToGetType.MethodToCall.ContainingType, this.sink.host.PlatformType.SystemObject) && MemberHelper.GetMethodSignature(callToGetType.MethodToCall).Equals("System.Object.GetType")) { IExpression objectToTest = callToGetType.ThisArgument; // generate: $TypeConstructor($DynamicType(o)) == TypeConstructorId var typeConstructorId = this.sink.FindOrDefineType(typeToTest.TypeToGet.ResolvedType).ConstructorId; Contract.Assume(typeConstructorId != null); this.Traverse(objectToTest); var e = this.TranslatedExpressions.Pop(); var exprs = new List<Bpl.Expr>(new Bpl.Expr[] {this.sink.Heap.DynamicType(e)}); Bpl.Expr typeTestExpression = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(sink.Heap.TypeConstructorFunction), exprs), Bpl.Expr.Ident(typeConstructorId)); if (MemberHelper.GetMethodSignature(resolvedMethod).Equals("System.Type.op_Inequality")) typeTestExpression = Bpl.Expr.Unary( methodCallToken, Bpl.UnaryOperator.Opcode.Not, typeTestExpression); this.TranslatedExpressions.Push(typeTestExpression); return; } } // Handle calls to Contract.ForAll and Contract.Exists specially (if they are to the overloads that take two ints and a predicate on ints) if (resolvedMethod.ContainingTypeDefinition.InternedKey == this.sink.host.PlatformType.SystemDiagnosticsContractsContract.InternedKey) { var methodName = resolvedMethod.Name.Value; if (methodCall.Arguments.Count() == 3 && (methodName == "ForAll" || methodName == "Exists")) { var noToken = Bpl.Token.NoToken; this.Traverse(methodCall.Arguments.ElementAt(0)); var lb = this.TranslatedExpressions.Pop(); this.Traverse(methodCall.Arguments.ElementAt(1)); var ub = this.TranslatedExpressions.Pop(); var delegateArgument = methodCall.Arguments.ElementAt(2); this.Traverse(delegateArgument); var del = this.TranslatedExpressions.Pop(); var boundVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Int)); var resultVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Bool)); var delegateType = delegateArgument.Type; var invokeMethod = delegateType.ResolvedType.GetMembersNamed(this.sink.host.NameTable.GetNameFor("Invoke"), false).First() as IMethodReference; var unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod; var invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod); var ins = new List<Bpl.Expr>(); ins.Add(del); var localStmtTraverser = this.StmtTraverser.factory.MakeStatementTraverser(this.sink, this.StmtTraverser.PdbReader, this.contractContext); var secondArg = new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] {Bpl.Expr.Ident(boundVar)})); ins.Add(secondArg); var outs = new List<Bpl.IdentifierExpr>(); outs.Add(Bpl.Expr.Ident(resultVar)); var callCmd = new Bpl.CallCmd(noToken, invokeProcedureInfo.Decl.Name, ins, outs); var blockCmds = new List<Bpl.Cmd>(); blockCmds.Add( new Bpl.AssumeCmd(noToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {secondArg})), Bpl.Expr.Ident(boundVar)))); blockCmds.Add(callCmd); Bpl.Block block = new Bpl.Block(noToken, "A", blockCmds, new Bpl.ReturnExprCmd(noToken, Bpl.Expr.Ident(resultVar))); Bpl.Expr body = new Bpl.CodeExpr(new List<Bpl.Variable>(new Bpl.Variable[] {resultVar}), new List<Bpl.Block>{block}); Bpl.Expr antecedent = Bpl.Expr.And(Bpl.Expr.Le(lb, Bpl.Expr.Ident(boundVar)), Bpl.Expr.Lt(Bpl.Expr.Ident(boundVar), ub)); Bpl.Expr quantifier; if (methodName == "ForAll") { body = Bpl.Expr.Imp(antecedent, body); quantifier = new Bpl.ForallExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body); } else { body = Bpl.Expr.And(antecedent, body); quantifier = new Bpl.ExistsExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body); } this.TranslatedExpressions.Push(quantifier); return; } } List<Bpl.Expr> inexpr; List<Bpl.IdentifierExpr> outvars; Bpl.IdentifierExpr thisExpr; Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed; var proc = TranslateArgumentsAndReturnProcedure(methodCallToken, methodCall.MethodToCall, resolvedMethod, methodCall.IsStaticCall ? null : methodCall.ThisArgument, methodCall.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed); string methodname = proc.Name; var translateAsFunctionCall = proc is Bpl.Function; bool isAsync = false; // this code structure is quite chaotic, and some code needs to be evaluated regardless, hence the try-finally try { if (!translateAsFunctionCall) { foreach (var a in resolvedMethod.Attributes) { if (TypeHelper.GetTypeName(a.Type).EndsWith("AsyncAttribute")) { isAsync = true; } } } var deferringCtorCall = resolvedMethod.IsConstructor && methodCall.ThisArgument is IThisReference; // REVIEW!! Ask Herman: is the above test enough? The following test is used in FindCtorCall.IsDeferringCtor, // but it doesn't work when the type is a struct S because then "this" has a type of "&S". //&& TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, methodCall.ThisArgument.Type); if (resolvedMethod.IsConstructor && resolvedMethod.ContainingTypeDefinition.IsStruct && !deferringCtorCall) { handleStructConstructorCall(methodCall, methodCallToken, inexpr, outvars, thisExpr, proc); return; } Bpl.CallCmd call; bool isEventAdd = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("add_"); bool isEventRemove = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("remove_"); if (isEventAdd || isEventRemove) { call = translateAddRemoveCall(methodCall, resolvedMethod, methodCallToken, inexpr, outvars, thisExpr, isEventAdd); } else { if (translateAsFunctionCall) { var func = proc as Bpl.Function; var exprSeq = new List<Bpl.Expr>(); foreach (var e in inexpr) { exprSeq.Add(e); } var callFunction = new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(func), exprSeq); this.TranslatedExpressions.Push(callFunction); return; } else { EmitLineDirective(methodCallToken); call = new Bpl.CallCmd(methodCallToken, methodname, inexpr, outvars); call.IsAsync = isAsync; this.StmtTraverser.StmtBuilder.Add(call); } } foreach (KeyValuePair<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> kv in toBoxed) { var lhs = kv.Key; var tuple = kv.Value; var rhs = tuple.Item1; Bpl.Expr fromUnion = this.sink.Heap.FromUnion(Bpl.Token.NoToken, lhs.Type, rhs, tuple.Item2); this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(lhs, fromUnion)); } if (this.sink.Options.modelExceptions == 2 || (this.sink.Options.modelExceptions == 1 && this.sink.MethodThrowsExceptions(resolvedMethod))) { Bpl.Expr expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)); this.StmtTraverser.RaiseException(expr); } } finally { // TODO move away phone related code from the translation, it would be better to have 2 or more translation phases if (PhoneCodeHelper.instance().PhonePlugin != null) { if (PhoneCodeHelper.instance().PhoneNavigationToggled) { if (PhoneCodeHelper.instance().isNavigationCall(methodCall)) { Bpl.AssignCmd assignCmd = PhoneCodeHelper.instance().createBoogieNavigationUpdateCmd(sink); this.StmtTraverser.StmtBuilder.Add(assignCmd); } } if (PhoneCodeHelper.instance().PhoneFeedbackToggled) { if (PhoneCodeHelper.instance().isMethodKnownUIChanger(methodCall)) { Bpl.AssumeCmd assumeFalse = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.LiteralExpr.False); this.StmtTraverser.StmtBuilder.Add(assumeFalse); } } } } }
public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFinallyStatement) { if (this.sink.Options.modelExceptions == 0) { this.Traverse(tryCatchFinallyStatement.TryBody); if (tryCatchFinallyStatement.FinallyBody != null) this.Traverse(tryCatchFinallyStatement.FinallyBody); return; } this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry)); this.Traverse(tryCatchFinallyStatement.TryBody); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1))); StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] {this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)}))); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement)); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef))); List<Bpl.StmtList> catchStatements = new List<Bpl.StmtList>(); List<Bpl.Expr> typeReferences = new List<Bpl.Expr>(); this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch)); foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses) { typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true)); StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext); if (catchClause.ExceptionContainer != Dummy.LocalVariable) { Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer); catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable))); } catchTraverser.Traverse(catchClause.Body); catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1))); catchTraverser.StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] {this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)}))); catchStatements.Insert(0, catchTraverser.StmtBuilder.Collect(catchClause.Token())); } Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false), TranslationHelper.BuildStmtList(new Bpl.ReturnCmd(Bpl.Token.NoToken)), null, null); Bpl.Expr dynTypeOfOperand = this.sink.Heap.DynamicType(Bpl.Expr.Ident(this.sink.LocalExcVariable)); for (int i = 0; i < catchStatements.Count; i++) { Bpl.Expr expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List<Bpl.Expr>(new Bpl.Expr[] {dynTypeOfOperand, typeReferences[i]})); elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, expr, catchStatements[i], elseIfCmd, null); } this.StmtBuilder.Add(elseIfCmd); this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable))); RaiseException(); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)); if (tryCatchFinallyStatement.FinallyBody != null) { this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally)); Bpl.Variable savedExcVariable = this.sink.CreateFreshLocal(this.sink.Heap.RefType); Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable))); this.Traverse(tryCatchFinallyStatement.FinallyBody); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable))); StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable))); this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1); } GenerateDispatchContinuation(tryCatchFinallyStatement); StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement)); Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)); RaiseException(raiseExpr); }