///// <summary> ///// Use this constructor for translating expressions that do *not* occur ///// within the context of the statements in a method body. ///// </summary> //public ExpressionTraverser(Sink sink) // : this(sink, null) //{ } /// <summary> /// Use this constructor for translating expressions that do occur within /// the context of the statements in a method body. /// </summary> public ExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) { this.sink = sink; this.StmtTraverser = statementTraverser; TranslatedExpressions = new Stack<Bpl.Expr>(); this.contractContext = contractContext; this.currentExpressionIsOpAssignStatement = expressionIsStatement; }
/// <summary> /// /// </summary> /// <remarks>(mschaef) Works, but still a stub</remarks> /// <param name="conditionalStatement"></param> public override void TraverseChildren(IConditionalStatement conditionalStatement) { StatementTraverser thenTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext); StatementTraverser elseTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext); ExpressionTraverser condTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext); if (this.sink.Options.instrumentBranches) { var tok = conditionalStatement.Token(); thenTraverser.StmtBuilder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> { Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies) }, null)) ); elseTraverser.StmtBuilder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> { Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies) }, null)) ); } condTraverser.Traverse(conditionalStatement.Condition); thenTraverser.Traverse(conditionalStatement.TrueBranch); elseTraverser.Traverse(conditionalStatement.FalseBranch); Bpl.Expr conditionExpr = condTraverser.TranslatedExpressions.Pop(); Bpl.Type conditionType = this.sink.CciTypeToBoogie(conditionalStatement.Condition.Type); if (conditionType == this.sink.Heap.RefType) { conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Ident(this.sink.Heap.NullRef)); } else if (conditionType == Bpl.Type.Int) { conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Literal(0)); } else { System.Diagnostics.Debug.Assert(conditionType == Bpl.Type.Bool); } Bpl.IfCmd ifcmd = new Bpl.IfCmd(conditionalStatement.Token(), conditionExpr, thenTraverser.StmtBuilder.Collect(conditionalStatement.TrueBranch.Token()), null, elseTraverser.StmtBuilder.Collect(conditionalStatement.FalseBranch.Token()) ); StmtBuilder.Add(ifcmd); }
/// <summary> /// /// </summary> public override void TraverseChildren(IMethodDefinition method) { if (TranslationHelper.HasAttribute(method, "BCTOmitAttribute")) { return; } if (method.IsStaticConstructor) { this.sawCctor = true; } bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_")); if (isEventAddOrRemove) { return; } Sink.ProcedureInfo procInfo; IMethodDefinition stubMethod = null; if (IsStubMethod(method, out stubMethod)) { procInfo = this.sink.FindOrCreateProcedure(stubMethod); } else { procInfo = this.sink.FindOrCreateProcedure(method); } if (method.IsAbstract || method.IsExternal || TranslationHelper.HasAttribute(method, "BCTOmitImplementationAttribute") // CCI is currently hacked to skip decompiling all method bodies in // compiler-generated classes. This is nontrivial to test for here, so // just omit implementation of all methods whose bodies haven't been // decompiled, at risk of silently hiding other problems. || !(method.Body is ISourceMethodBody)) { // we're done, just define the procedure return; } this.sink.BeginMethod(method); var decl = procInfo.Decl; var proc = decl as Bpl.Procedure; var formalMap = procInfo.FormalMap; if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey) { decl.AddAttribute("entrypoint"); } try { StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false); // Manually set the beginning of the method as the source location for // BCT synthetic code until we traverse the first real statement, which // will automatically pick up its source location. Needed for record // calls to show up in the trace. stmtTraverser.EmitSourceContext(method); if (!method.IsStatic) { stmtTraverser.AddRecordCall("this", sink.CciTypeToBoogie(method.ContainingType), new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.ThisVariable)); } #region Add assignments from In-Params to local-Params foreach (MethodParameter mparam in formalMap) { if (mparam.inParameterCopy != null) { Bpl.IToken tok = method.Token(); Bpl.Expr rhs = new Bpl.IdentifierExpr(tok, mparam.inParameterCopy); stmtTraverser.AddRecordCall(mparam.underlyingParameter.Name.Value, mparam.inParameterCopy.TypedIdent.Type, rhs); stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, new Bpl.IdentifierExpr(tok, mparam.outParameterCopy), rhs)); } } #endregion #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values var inits = InitializeFieldsInConstructor(method); if (0 < inits.Count) { foreach (var s in inits) { stmtTraverser.Traverse(s); } } #endregion #region Translate method attributes // Don't need an expression translator because there is a limited set of things // that can appear as arguments to custom attributes // TODO: decode enum values try { foreach (var a in method.Attributes) { var attrName = TypeHelper.GetTypeName(a.Type); if (attrName.EndsWith("Attribute")) { attrName = attrName.Substring(0, attrName.Length - 9); } var args = new List <object>(); foreach (var c in a.Arguments) { var mdc = c as IMetadataConstant; if (mdc != null) { object o; if (mdc.Type.IsEnum) { var lit = Bpl.Expr.Literal((int)mdc.Value); lit.Type = Bpl.Type.Int; o = lit; } else { switch (mdc.Type.TypeCode) { case PrimitiveTypeCode.Boolean: o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False; break; case PrimitiveTypeCode.Int32: var lit = Bpl.Expr.Literal((int)mdc.Value); lit.Type = Bpl.Type.Int; o = lit; break; case PrimitiveTypeCode.String: o = mdc.Value; break; default: throw new InvalidCastException("Invalid metadata constant type"); } } args.Add(o); } } decl.AddAttribute(attrName, args.ToArray()); } } catch (InvalidCastException) { Console.WriteLine("Warning: Cannot translate custom attributes for method\n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine(" >>Skipping attributes, continuing with method translation"); } #endregion #region Translate body var helperTypes = stmtTraverser.TranslateMethod(method); if (helperTypes != null) { this.privateTypes.AddRange(helperTypes); } #endregion #region Create Local Vars For Implementation List <Bpl.Variable> vars = new List <Bpl.Variable>(); foreach (MethodParameter mparam in formalMap) { if (!mparam.underlyingParameter.IsByReference) { vars.Add(mparam.outParameterCopy); } } foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) { vars.Add(v); } // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions if (0 < this.sink.Options.modelExceptions) { vars.Add(procInfo.LocalExcVariable); } vars.Add(procInfo.LabelVariable); List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray()); #endregion var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken); #region Add implementation to Boogie program if (proc != null) { Bpl.Implementation impl = new Bpl.Implementation(method.Token(), decl.Name, new List <Bpl.TypeVariable>(), decl.InParams, decl.OutParams, vseq, translatedBody); impl.Proc = proc; this.sink.TranslatedProgram.AddTopLevelDeclaration(impl); } else // method is translated as a function //var func = decl as Bpl.Function; //Contract.Assume(func != null); //var blocks = new List<Bpl.Block>(); //var counter = 0; //var returnValue = decl.OutParams[0]; //foreach (var bb in translatedBody.BigBlocks) { // var label = bb.LabelName ?? "L" + counter++.ToString(); // var newTransferCmd = (bb.tc is Bpl.ReturnCmd) // ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue)) // : bb.tc; // var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd); // blocks.Add(b); //} //var localVars = new List<Bpl.Variable>(); //localVars.Add(returnValue); //func.Body = new Bpl.CodeExpr(localVars, blocks); { } #endregion } catch (TranslationException te) { Console.WriteLine("Translation error in body of \n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine("\t" + te.Message + "\n" + te.StackTrace); } catch (Exception e) { Console.WriteLine("Error encountered during translation of \n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine("\t>>" + e.Message + "\n" + e.StackTrace); } finally { } }
public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsOpAssignStatement = false) { return new ExpressionTraverser(sink, statementTraverser, contractContext, expressionIsOpAssignStatement); }
public CLRExpressionSemantics(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) : base(sink, statementTraverser, contractContext, expressionIsStatement) { }
public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) { return new CLRExpressionSemantics(sink, statementTraverser, contractContext, expressionIsStatement); }
/// <summary> /// /// </summary> public override void TraverseChildren(IMethodDefinition method) { if (method.IsStaticConstructor) { this.sawCctor = true; } bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_")); if (isEventAddOrRemove) { return; } Sink.ProcedureInfo procInfo; IMethodDefinition stubMethod = null; if (IsStubMethod(method, out stubMethod)) { procInfo = this.sink.FindOrCreateProcedure(stubMethod); } else { procInfo = this.sink.FindOrCreateProcedure(method); } if (method.IsAbstract || method.IsExternal) // we're done, just define the procedure { return; } this.sink.BeginMethod(method); var decl = procInfo.Decl; var proc = decl as Bpl.Procedure; var formalMap = procInfo.FormalMap; if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey) { decl.AddAttribute("entrypoint"); } // FEEDBACK inline handler methods to avoid more false alarms if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) && !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method)) { proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE)); PhoneCodeHelper.instance().trackCallableMethod(proc); } try { StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false); // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null // FEEDBACK for modular analysis we need it to be non-null at the start // FEEDBACK also, callee is obviously non null IMethodDefinition translatedMethod = sink.getMethodBeingTranslated(); if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& translatedMethod != null && PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod)) { // assign null to exception List <Bpl.AssignLhs> assignee = new List <Bpl.AssignLhs>(); Bpl.AssignLhs exceptionAssignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)); assignee.Add(exceptionAssignee); List <Bpl.Expr> value = new List <Bpl.Expr>(); value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef)); Bpl.Cmd exceptionAssign = new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value); stmtTraverser.StmtBuilder.Add(exceptionAssign); } #region Add assignments from In-Params to local-Params foreach (MethodParameter mparam in formalMap) { if (mparam.inParameterCopy != null) { Bpl.IToken tok = method.Token(); stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, new Bpl.IdentifierExpr(tok, mparam.outParameterCopy), new Bpl.IdentifierExpr(tok, mparam.inParameterCopy))); } } #endregion #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values var inits = InitializeFieldsInConstructor(method); if (0 < inits.Count) { foreach (var s in inits) { stmtTraverser.Traverse(s); } } #endregion #region Translate method attributes // Don't need an expression translator because there is a limited set of things // that can appear as arguments to custom attributes // TODO: decode enum values try { foreach (var a in method.Attributes) { var attrName = TypeHelper.GetTypeName(a.Type); if (attrName.EndsWith("Attribute")) { attrName = attrName.Substring(0, attrName.Length - 9); } var args = new List <object>(); foreach (var c in a.Arguments) { var mdc = c as IMetadataConstant; if (mdc != null) { object o; if (mdc.Type.IsEnum) { var lit = Bpl.Expr.Literal((int)mdc.Value); lit.Type = Bpl.Type.Int; o = lit; } else { switch (mdc.Type.TypeCode) { case PrimitiveTypeCode.Boolean: o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False; break; case PrimitiveTypeCode.Int32: var lit = Bpl.Expr.Literal((int)mdc.Value); lit.Type = Bpl.Type.Int; o = lit; break; case PrimitiveTypeCode.String: o = mdc.Value; break; default: throw new InvalidCastException("Invalid metadata constant type"); } } args.Add(o); } } decl.AddAttribute(attrName, args.ToArray()); } } catch (InvalidCastException) { Console.WriteLine("Warning: Cannot translate custom attributes for method\n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine(" >>Skipping attributes, continuing with method translation"); } #endregion #region Translate body var helperTypes = stmtTraverser.TranslateMethod(method); if (helperTypes != null) { this.privateTypes.AddRange(helperTypes); } #endregion #region Create Local Vars For Implementation List <Bpl.Variable> vars = new List <Bpl.Variable>(); foreach (MethodParameter mparam in formalMap) { if (!mparam.underlyingParameter.IsByReference) { vars.Add(mparam.outParameterCopy); } } foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) { vars.Add(v); } // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions if (0 < this.sink.Options.modelExceptions) { vars.Add(procInfo.LocalExcVariable); } vars.Add(procInfo.LabelVariable); List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray()); #endregion var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken); #region Add implementation to Boogie program if (proc != null) { Bpl.Implementation impl = new Bpl.Implementation(method.Token(), decl.Name, new List <Bpl.TypeVariable>(), decl.InParams, decl.OutParams, vseq, translatedBody); impl.Proc = proc; this.sink.TranslatedProgram.AddTopLevelDeclaration(impl); } else // method is translated as a function //var func = decl as Bpl.Function; //Contract.Assume(func != null); //var blocks = new List<Bpl.Block>(); //var counter = 0; //var returnValue = decl.OutParams[0]; //foreach (var bb in translatedBody.BigBlocks) { // var label = bb.LabelName ?? "L" + counter++.ToString(); // var newTransferCmd = (bb.tc is Bpl.ReturnCmd) // ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue)) // : bb.tc; // var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd); // blocks.Add(b); //} //var localVars = new List<Bpl.Variable>(); //localVars.Add(returnValue); //func.Body = new Bpl.CodeExpr(localVars, blocks); { } #endregion } catch (TranslationException te) { Console.WriteLine("Translation error in body of \n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine("\t" + te.Message); } catch (Exception e) { Console.WriteLine("Error encountered during translation of \n '{0}':", MemberHelper.GetMethodSignature(method, NameFormattingOptions.None)); Console.WriteLine("\t>>" + e.Message); } finally { } }
public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsOpAssignStatement = false) { return(new ExpressionTraverser(sink, statementTraverser, contractContext, expressionIsOpAssignStatement)); }
public SourceContextEmitter(StatementTraverser parent) { this.parent = parent; }
public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) { return(new CLRExpressionSemantics(sink, statementTraverser, contractContext, expressionIsStatement)); }
public CLRExpressionSemantics(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) : base(sink, statementTraverser, contractContext, expressionIsStatement) { }
public CLRExpressionSemantics(Sink sink, StatementTraverser/*?*/ statementTraverser) : base(sink, statementTraverser) { }
public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) { return new CLRExpressionSemantics(sink, statementTraverser); }
public WholeProgramExpressionSemantics(WholeProgram parent, Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) : base(sink, statementTraverser, contractContext, expressionIsStatement) { this.parent = parent; this.subTypes = parent.subTypes; }
public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) { return new ExpressionTraverser(sink, statementTraverser); }
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); }
/// <summary> /// Use this constructor for translating expressions that do occur within /// the context of the statements in a method body. /// </summary> public ExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) { this.sink = sink; HeapVariable = sink.HeapVariable; this.StmtTraverser = statementTraverser; TranslatedExpressions = new Stack<Bpl.Expr>(); }