/// <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 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); var exceptionExpr = Bpl.Expr.Ident(this.sink.LocalExcVariable); catchTraverser.AddRecordCall(catchClause.ExceptionContainer.Name.Value, sink.Heap.RefType, exceptionExpr); catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), exceptionExpr)); } 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))); PropagateException(); 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)); PropagateExceptionIfAny(); }