//----------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Cci; using Microsoft.Cci.MetadataReader; using Microsoft.Cci.MutableCodeModel; using Microsoft.Cci.Contracts; using Microsoft.Cci.ILToCodeModel; using Bpl = Microsoft.Boogie; namespace BytecodeTranslator { public class MethodParameter { /// /// All parameters of the method get an associated in parameter /// in the Boogie procedure except for out parameters. /// public Bpl.Formal/*?*/ inParameterCopy; /// /// A local variable when the underlyingParameter is an in parameter /// and a formal (out) parameter when the underlyingParameter is /// a ref or out parameter. /// public Bpl.Variable outParameterCopy; public IParameterDefinition underlyingParameter; public MethodParameter(IParameterDefinition parameterDefinition, Bpl.Type ptype) { this.underlyingParameter = parameterDefinition; var parameterToken = parameterDefinition.Token(); var typeToken = parameterDefinition.Type.Token(); var parameterName = TranslationHelper.TurnStringIntoValidIdentifier(parameterDefinition.Name.Value); if (String.IsNullOrWhiteSpace(parameterName)) parameterName = "P" + parameterDefinition.Index.ToString(); this.inParameterCopy = new Bpl.Formal(parameterToken, new Bpl.TypedIdent(typeToken, parameterName + "$in", ptype), true); if (parameterDefinition.IsByReference) { this.outParameterCopy = new Bpl.Formal(parameterToken, new Bpl.TypedIdent(typeToken, parameterName + "$out", ptype), false); } else { this.outParameterCopy = new Bpl.LocalVariable(parameterToken, new Bpl.TypedIdent(typeToken, parameterName, ptype)); } } public override string ToString() { return this.underlyingParameter.Name.Value; } } /// /// Class containing several static helper functions to convert /// from Cci to Boogie /// static class TranslationHelper { public static Bpl.StmtList BuildStmtList(Bpl.Cmd cmd, Bpl.TransferCmd tcmd) { Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); builder.Add(cmd); builder.Add(tcmd); return builder.Collect(Bpl.Token.NoToken); } public static Bpl.StmtList BuildStmtList(Bpl.TransferCmd tcmd) { Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); builder.Add(tcmd); return builder.Collect(Bpl.Token.NoToken); } public static Bpl.StmtList BuildStmtList(params Bpl.Cmd[] cmds) { Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); foreach (Bpl.Cmd cmd in cmds) builder.Add(cmd); return builder.Collect(Bpl.Token.NoToken); } public static Bpl.AssignCmd BuildAssignCmd(Bpl.IdentifierExpr lhs, Bpl.Expr rhs) { List lhss = new List(); lhss.Add(new Bpl.SimpleAssignLhs(lhs.tok, lhs)); List rhss = new List(); rhss.Add(rhs); return new Bpl.AssignCmd(lhs.tok, lhss, rhss); } public static Bpl.AssignCmd BuildAssignCmd(List lexprs, List rexprs) { List lhss = new List(); foreach (Bpl.IdentifierExpr lexpr in lexprs) { lhss.Add(new Bpl.SimpleAssignLhs(lexpr.tok, lexpr)); } List rhss = new List(); return new Bpl.AssignCmd(Bpl.Token.NoToken, lhss, rexprs); } public static Bpl.IToken Token(this IObjectWithLocations objectWithLocations) { //TODO: use objectWithLocations.Locations! Bpl.IToken tok = Bpl.Token.NoToken; return tok; } internal static int tmpVarCounter = 0; public static string GenerateTempVarName() { return "$tmp" + (tmpVarCounter++).ToString(); } internal static int catchClauseCounter = 0; public static string GenerateCatchClauseName() { return "catch" + (catchClauseCounter++).ToString(); } internal static int finallyClauseCounter = 0; public static string GenerateFinallyClauseName() { return "finally" + (finallyClauseCounter++).ToString(); } public static string CreateUniqueMethodName(IMethodReference method) { var containingTypeName = TypeHelper.GetTypeName(method.ContainingType, NameFormattingOptions.None); var s = MemberHelper.GetMethodSignature(method, NameFormattingOptions.DocumentationId); s = s.Substring(2); s = s.TrimEnd(')'); s = TurnStringIntoValidIdentifier(s); return s; } public static string TurnStringIntoValidIdentifier(string s) { s = s.Replace("[0:,0:]", "2DArray"); // TODO: Do this programmatically to handle arbitrary arity s = s.Replace("[0:,0:,0:]", "3DArray"); s = s.Replace("[0:,0:,0:,0:]", "4DArray"); s = s.Replace("[0:,0:,0:,0:,0:]", "5DArray"); s = s.Replace('!', '$'); s = s.Replace('*', '$'); s = s.Replace('+', '$'); s = s.Replace('(', '$'); s = s.Replace(')', '$'); s = s.Replace(',', '$'); s = s.Replace("[]", "array"); s = s.Replace('<', '$'); s = s.Replace('>', '$'); s = s.Replace(':', '$'); s = s.Replace(' ', '$'); s = s.Replace('{', '$'); s = s.Replace('}', '$'); s = s.Replace('-', '$'); s = s.Replace(' ', '$'); s = s.Replace('\t', '$'); s = s.Replace('\r', '$'); s = s.Replace('\n', '$'); s = s.Replace('/', '$'); s = s.Replace('\\', '$'); s = s.Replace('=', '$'); s = s.Replace('@', '$'); s = s.Replace(';', '$'); s = s.Replace('%', '$'); s = s.Replace('&', '$'); s = s.Replace('"', '$'); s = s.Replace('[', '$'); s = s.Replace(']', '$'); s = s.Replace('|', '$'); s = s.Replace('+', '$'); s = s.Replace('’', '$'); s = GetRidOfSurrogateCharacters(s); return s; } /// /// Unicode surrogates cannot be handled by Boogie. /// http://msdn.microsoft.com/en-us/library/dd374069(v=VS.85).aspx /// private static string GetRidOfSurrogateCharacters(string s) { var cs = s.ToCharArray(); var okayChars = new char[cs.Length]; for (int i = 0, j = 0; i < cs.Length; i++) { if (Char.IsSurrogate(cs[i])) continue; okayChars[j++] = cs[i]; } var raw = String.Concat(okayChars); return raw.Trim(new char[] { '\0' }); } public static bool IsStruct(ITypeReference typ) { return typ.IsValueType && !typ.IsEnum && typ.TypeCode == PrimitiveTypeCode.NotPrimitive; } } }