예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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
            }));
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }
예제 #13
0
 public static BoogieExpr GetDefaultVal(TypeName type)
 {
     return(GetDefaultVal(TransUtils.GetBoogieTypeFromSolidityTypeName(type)));
 }