//-----------------------------------------------------------------------------
//
// 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) {
this.underlyingParameter = parameterDefinition;
Bpl.Type ptype = TranslationHelper.CciTypeToBoogie(parameterDefinition.Type);
var parameterToken = parameterDefinition.Token();
var typeToken = parameterDefinition.Type.Token();
var parameterName = parameterDefinition.Name.Value;
if (!parameterDefinition.IsOut) {
this.inParameterCopy = new Bpl.Formal(parameterToken, new Bpl.TypedIdent(typeToken, parameterName + "$in", ptype), true);
}
if (parameterDefinition.IsByReference || parameterDefinition.IsOut) {
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.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.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();
}
public static string CreateUniqueMethodName(IMethodReference method) {
var containingTypeName = TypeHelper.GetTypeName(method.ContainingType, NameFormattingOptions.None);
if (containingTypeName == "Poirot.Poirot")
{
string name = method.Name.Value;
if (name == "BeginAtomic")
return "corral_atomic_begin";
else if (name == "EndAtomic")
return "corral_atomic_end";
else if (name == "CurrentThreadId")
return "corral_getThreadID";
else if (name == "Nondet")
return "poirot_nondet";
}
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('(', '$');
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('\n', '$');
s = s.Replace('/', '$');
s = s.Replace('\\', '$');
s = s.Replace('=', '$');
s = s.Replace('@', '$');
return s;
}
#region Temp Stuff that must be replaced as soon as there is real code to deal with this
public static Bpl.Type CciTypeToBoogie(ITypeReference type) {
if (TypeHelper.TypesAreEquivalent(type, type.PlatformType.SystemBoolean))
return Bpl.Type.Bool;
else if (TypeHelper.IsPrimitiveInteger(type))
return Bpl.Type.Int;
else
return Bpl.Type.Int; // BUG! This is where we need to return "ref" for a reference type
}
public static Bpl.Variable TempThisVar() {
return new Bpl.GlobalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "this", Bpl.Type.Int));
}
public static Bpl.Variable TempArrayContentsVar()
{
return new Bpl.GlobalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "$ArrayContents", Bpl.Type.Int));
}
public static Bpl.Variable TempArrayLengthVar()
{
return new Bpl.GlobalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "$ArrayLength", Bpl.Type.Int));
}
#endregion
}
}