private void GenerateMemoryVariablesForArray(ArrayTypeName array, HashSet <KeyValuePair <BoogieType, BoogieType> > generatedTypes) { BoogieType boogieKeyType = BoogieType.Int; BoogieType boogieValType = null; if (array.BaseType is ArrayTypeName subarray) { boogieValType = BoogieType.Ref; GenerateMemoryVariablesForArray(subarray, generatedTypes); } else if (array.BaseType is Mapping mapping) { boogieValType = BoogieType.Ref; GenerateMemoryVariablesForMapping(mapping, generatedTypes); } else { boogieValType = TransUtils.GetBoogieTypeFromSolidityTypeName(array.BaseType); } KeyValuePair <BoogieType, BoogieType> pair = new KeyValuePair <BoogieType, BoogieType>(boogieKeyType, boogieValType); if (!generatedTypes.Contains(pair)) { generatedTypes.Add(pair); GenerateSingleMemoryVariable(boogieKeyType, boogieValType); } }
private List <BoogieVariable> GetParamsOfFunction(FunctionDefinition funcDef) { List <BoogieVariable> parameters = new List <BoogieVariable>(); foreach (VariableDeclaration param in funcDef.Parameters.Parameters) { string name = TransUtils.GetCanonicalLocalVariableName(param); BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); parameters.Add(localVar); } var retParamCount = 0; foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters) { //string name = "__ret" + funcDef.Name; string name = $"__ret_{retParamCount++}_" + funcDef.Name; if (!string.IsNullOrEmpty(param.Name)) { name = TransUtils.GetCanonicalLocalVariableName(param); } BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); parameters.Add(localVar); } return(parameters); }
private List <BoogieVariable> CollectLocalVars(ContractDefinition contract) { List <BoogieVariable> localVars = new List <BoogieVariable>() { new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)), new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)), new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)), new BoogieLocalVariable(new BoogieTypedIdent("choice", BoogieType.Int)), }; // use to remove duplicated variables by name HashSet <string> uniqueVarNames = new HashSet <string>() { "this", "msgsender_MSG", "msgvalue_MSG", "choice" }; // Consider all visible functions HashSet <FunctionDefinition> funcDefs = context.GetVisibleFunctionsByContract(contract); foreach (FunctionDefinition funcDef in funcDefs) { if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL) { foreach (VariableDeclaration param in funcDef.Parameters.Parameters) { string name = TransUtils.GetCanonicalLocalVariableName(param); if (!uniqueVarNames.Contains(name)) { BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); localVars.Add(localVar); uniqueVarNames.Add(name); } } var retParamCount = 0; foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters) { //string name = "__ret" + funcDef.Name; string name = $"__ret_{retParamCount++}_" + funcDef.Name; if (!string.IsNullOrEmpty(param.Name)) { name = TransUtils.GetCanonicalLocalVariableName(param); } if (!uniqueVarNames.Contains(name)) { BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); localVars.Add(localVar); uniqueVarNames.Add(name); } } } } return(localVars); }
public List <BoogieDeclaration> GetMultiDimArrayLens(VariableDeclaration decl) { List <BoogieDeclaration> lenVars = new List <BoogieDeclaration>(); TypeName curType = decl.TypeName; List <BoogieType> indTypes = new List <BoogieType>() { BoogieType.Ref }; int lvl = 0; while (curType is Mapping || curType is ArrayTypeName) { if (curType is Mapping map) { curType = map.ValueType; indTypes.Add(TransUtils.GetBoogieTypeFromSolidityTypeName(map.KeyType)); } else if (curType is ArrayTypeName arr) { BoogieType mapType = BoogieType.Int; BoogieType initType = BoogieType.Int; for (int i = indTypes.Count - 1; i >= 0; i--) { initType = mapType; mapType = new BoogieMapType(indTypes[i], mapType); } if (arr.Length != null && initType is BoogieMapType lenMap) { BoogieFunction initFn = GenerateMultiDimInitFunction(lenMap); lenVars.Add(initFn); } BoogieGlobalVariable lenVar = new BoogieGlobalVariable(new BoogieTypedIdent(GetMultiDimLengthName(decl, lvl), mapType)); lenVars.Add(lenVar); curType = arr.BaseType; indTypes.Add(BoogieType.Int); } lvl++; } return(lenVars); }
public static BoogieFunction GenerateMultiDimZeroFunction(VariableDeclaration decl) { TypeName curType = decl.TypeName; List <BoogieType> boogieType = new List <BoogieType>(); while (curType is Mapping || curType is ArrayTypeName) { if (curType is Mapping map) { boogieType.Insert(0, TransUtils.GetBoogieTypeFromSolidityTypeName(map.KeyType)); curType = map.ValueType; } else if (curType is ArrayTypeName arr) { boogieType.Insert(0, BoogieType.Int); curType = arr.BaseType; } } BoogieType valType = TransUtils.GetBoogieTypeFromSolidityTypeName(curType); BoogieExpr boogieInit = TransUtils.GetDefaultVal(valType); string smtType = GetSmtType(valType); string smtInit = boogieInit.ToString().Equals("null") ? "0" : boogieInit.ToString(); BoogieType mapType = valType; string fnName = $"{valType.ToString()}Arr"; foreach (BoogieType type in boogieType) { smtType = $"(Array {GetSmtType(type)} {smtType})"; mapType = new BoogieMapType(type, mapType); smtInit = $"((as const {smtType}) {smtInit})"; fnName = $"{type.ToString()}{fnName}"; } var outVar = new BoogieFormalParam(new BoogieTypedIdent("ret", mapType)); var smtDefinedAttr = new BoogieAttribute("smtdefined", $"\"{smtInit}\""); return(new BoogieFunction($"zero{fnName}", new List <BoogieVariable>(), new List <BoogieVariable>() { outVar }, new List <BoogieAttribute>() { smtDefinedAttr })); }
private void GenerateStructConstructors(ContractDefinition contract, StructDefinition structDefn) { // generate the internal one without base constructors string procName = structDefn.CanonicalName + "_ctor"; List <BoogieVariable> inParams = new List <BoogieVariable>(); inParams.AddRange(TransUtils.GetDefaultInParams()); foreach (var member in structDefn.Members) { Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!"); var formalType = TransUtils.GetBoogieTypeFromSolidityTypeName(member.TypeName); var formalName = member.Name; inParams.Add(new BoogieFormalParam(new BoogieTypedIdent(formalName, formalType))); } List <BoogieVariable> outParams = new List <BoogieVariable>(); List <BoogieAttribute> attributes = new List <BoogieAttribute>(); if (context.TranslateFlags.GenerateInlineAttributes) { attributes.Add(new BoogieAttribute("inline", 1)); } ; BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes); context.Program.AddDeclaration(procedure); List <BoogieVariable> localVars = new List <BoogieVariable>(); BoogieStmtList procBody = new BoogieStmtList(); foreach (var member in structDefn.Members) { //f[this] = f_arg Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!"); var mapName = member.Name + "_" + structDefn.CanonicalName; var formalName = member.Name; var mapSelectExpr = new BoogieMapSelect(new BoogieIdentifierExpr(mapName), new BoogieIdentifierExpr("this")); procBody.AddStatement(new BoogieAssignCmd(mapSelectExpr, new BoogieIdentifierExpr(member.Name))); } BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody); context.Program.AddDeclaration(implementation); }
public static BoogieFuncCallExpr GetCallExprForZeroInit(TypeName curType) { string fnName = "zero"; while (curType is Mapping || curType is ArrayTypeName) { if (curType is Mapping map) { fnName = $"{fnName}{TransUtils.GetBoogieTypeFromSolidityTypeName(map.KeyType).ToString()}"; curType = map.ValueType; } else if (curType is ArrayTypeName arr) { fnName = $"{fnName}{BoogieType.Int.ToString()}"; curType = arr.BaseType; } } fnName = $"{fnName}{TransUtils.GetBoogieTypeFromSolidityTypeName(curType).ToString()}Arr"; return(new BoogieFuncCallExpr(fnName, new List <BoogieExpr>())); }
private void GenerateMemoryVariablesForArray(VariableDeclaration decl, ArrayTypeName array, HashSet <String> generatedMaps, int lvl) { BoogieType boogieKeyType = BoogieType.Int; BoogieType boogieValType = null; if (array.BaseType is ArrayTypeName subarray) { boogieValType = BoogieType.Ref; GenerateMemoryVariablesForArray(decl, subarray, generatedMaps, lvl + 1); // The last level gets initialized all at once if (context.TranslateFlags.LazyAllocNoMod) { BoogieMapType mapType = new BoogieMapType(BoogieType.Ref, new BoogieMapType(boogieKeyType, BoogieType.Bool)); context.Program.AddDeclaration(new BoogieGlobalVariable(new BoogieTypedIdent(mapHelper.GetNestedAllocName(decl, lvl), mapType))); } } else if (array.BaseType is Mapping mapping) { boogieValType = BoogieType.Ref; GenerateMemoryVariablesForMapping(decl, mapping, generatedMaps, lvl + 1); if (context.TranslateFlags.LazyAllocNoMod) { BoogieMapType mapType = new BoogieMapType(BoogieType.Ref, new BoogieMapType(boogieKeyType, BoogieType.Bool)); context.Program.AddDeclaration(new BoogieGlobalVariable(new BoogieTypedIdent(mapHelper.GetNestedAllocName(decl, lvl), mapType))); } } else { boogieValType = TransUtils.GetBoogieTypeFromSolidityTypeName(array.BaseType); } KeyValuePair <BoogieType, BoogieType> pair = new KeyValuePair <BoogieType, BoogieType>(boogieKeyType, boogieValType); GenerateSingleMemoryVariable(decl, boogieKeyType, boogieValType, generatedMaps); }
public static BoogieType GetMultiDimBoogieType(TypeName varType) { if (!(varType is Mapping || varType is ArrayTypeName)) { return(TransUtils.GetBoogieTypeFromSolidityTypeName(varType)); } BoogieType resultType = null; if (varType is Mapping map) { BoogieType valType = GetMultiDimBoogieType(map.ValueType); BoogieType keyType = GetMultiDimBoogieType(map.KeyType); resultType = new BoogieMapType(keyType, valType); } else if (varType is ArrayTypeName arr) { BoogieType baseType = GetMultiDimBoogieType(arr.BaseType); resultType = new BoogieMapType(BoogieType.Int, baseType); } return(resultType); }
public override bool Visit(ModifierDefinition modifier) { //if (modifier.Parameters.Length() > 0) //{ // throw new System.Exception("modifiers with parameters not implemented"); //} var modifierInParams = TransUtils.GetDefaultInParams(); foreach (var parameter in modifier.Parameters.Parameters) { string name = null; name = TransUtils.GetCanonicalLocalVariableName(parameter, context); BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName); modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type))); } Block body = modifier.Body; bool hasPre = false; bool hasPost = false; List <Statement> postlude = new List <Statement>(); // this list does not include locals introduced during translation List <BoogieLocalVariable> localVarsDeclared = new List <BoogieLocalVariable>(); bool translatingPre = true; foreach (Statement statement in body.Statements) { if (statement is VariableDeclarationStatement varDecls) { foreach (VariableDeclaration varDecl in varDecls.Declarations) { string name = TransUtils.GetCanonicalLocalVariableName(varDecl, context); BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(varDecl.TypeName); // Issue a warning for intXX variables in case /useModularArithemtic option is used: if (context.TranslateFlags.UseModularArithmetic && varDecl.TypeDescriptions.IsInt()) { Console.WriteLine($"Warning: signed integer arithmetic is not handled with /useModularArithmetic option"); } var boogieVariable = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); if (translatingPre) { localVarsDeclared.Add(boogieVariable); // don't add locals after placeholder } } // throw new System.Exception("locals within modifiers not supported"); } if (statement is PlaceholderStatement) { translatingPre = false; // only capture those locals declared in the prefix, these are visible to postlude context.AddPreludeLocalsToModifier(modifier.Name, localVarsDeclared); continue; } if (translatingPre) { hasPre = true; } else { hasPost = true; } } var attributes = new List <BoogieAttribute>(); attributes.Add(new BoogieAttribute("inline", 1)); if (hasPre) { List <BoogieVariable> inParams = new List <BoogieVariable>(modifierInParams); List <BoogieVariable> outParams = new List <BoogieVariable>(); outParams.AddRange(localVarsDeclared.Select(x => new BoogieFormalParam(new BoogieTypedIdent("__out_mod_" + x.Name, x.TypedIdent.Type)))); BoogieProcedure preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams, attributes); context.AddModiferToPreProc(modifier.Name, preludeProc); BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre", inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList()); context.AddModiferToPreImpl(modifier.Name, preludeImpl); } if (hasPost) { List <BoogieVariable> inParams = new List <BoogieVariable>(modifierInParams); inParams.AddRange(localVarsDeclared); List <BoogieVariable> outParams = new List <BoogieVariable>(); BoogieProcedure postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams, attributes); context.AddModiferToPostProc(modifier.Name, postludeProc); BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post", inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList()); context.AddModiferToPostImpl(modifier.Name, postludeImpl); } return(false); }
public override bool Visit(ModifierDefinition modifier) { //if (modifier.Parameters.Length() > 0) //{ // throw new System.Exception("modifiers with parameters not implemented"); //} var modifierInParams = TransUtils.GetDefaultInParams(); foreach (var parameter in modifier.Parameters.Parameters) { string name = null; name = TransUtils.GetCanonicalLocalVariableName(parameter); BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName); modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type))); } Block body = modifier.Body; bool hasPre = false; bool hasPost = false; List <Statement> postlude = new List <Statement>(); bool translatingPre = true; foreach (Statement statement in body.Statements) { if (statement is VariableDeclarationStatement) { throw new System.Exception("locals within modifiers not supported"); } if (statement is PlaceholderStatement) { translatingPre = false; continue; } if (translatingPre) { hasPre = true; } else { hasPost = true; } } if (hasPre) { List <BoogieVariable> inParams = modifierInParams; List <BoogieVariable> outParams = new List <BoogieVariable>(); BoogieProcedure preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams); context.AddModiferToPreProc(modifier.Name, preludeProc); BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre", inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList()); context.AddModiferToPreImpl(modifier.Name, preludeImpl); } if (hasPost) { List <BoogieVariable> inParams = modifierInParams; List <BoogieVariable> outParams = new List <BoogieVariable>(); BoogieProcedure postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams); context.AddModiferToPostProc(modifier.Name, postludeProc); BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post", inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList()); context.AddModiferToPostImpl(modifier.Name, postludeImpl); } return(false); }
public static List <BoogieVariable> CollectLocalVars(List <ContractDefinition> contracts, TranslatorContext context) { Debug.Assert(contracts.Count > 0, "Internal exception: expecting at least one contract here"); List <BoogieVariable> localVars = new List <BoogieVariable>() { new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)), new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)), new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)), new BoogieLocalVariable(new BoogieTypedIdent("choice", BoogieType.Int)), }; // use to remove duplicated variables by name HashSet <string> uniqueVarNames = new HashSet <string>() { "this", "msgsender_MSG", "msgvalue_MSG", "choice" }; foreach (var contract in contracts) { if (contract.ContractKind != EnumContractKind.CONTRACT) { continue; } // Consider all visible functions HashSet <FunctionDefinition> funcDefs = context.GetVisibleFunctionsByContract(contract); foreach (FunctionDefinition funcDef in funcDefs) { if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL) { foreach (VariableDeclaration param in funcDef.Parameters.Parameters) { string name = TransUtils.GetCanonicalLocalVariableName(param); if (!uniqueVarNames.Contains(name)) { BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); localVars.Add(localVar); uniqueVarNames.Add(name); } } var retParamCount = 0; foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters) { //string name = "__ret" + funcDef.Name; string name = $"__ret_{retParamCount++}_" + funcDef.Name; if (!string.IsNullOrEmpty(param.Name)) { name = TransUtils.GetCanonicalLocalVariableName(param); } if (!uniqueVarNames.Contains(name)) { BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName); BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type)); localVars.Add(localVar); uniqueVarNames.Add(name); } } } } } return(localVars); }
public static BoogieExpr GetDefaultVal(TypeName type) { return(GetDefaultVal(TransUtils.GetBoogieTypeFromSolidityTypeName(type))); }