コード例 #1
0
        public void Generate()
        {
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            List <BoogieAttribute> attributes = new List <BoogieAttribute>()
            {
                new BoogieAttribute("inline", 1),
            };
            var             procName  = "FallbackDispatch";
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = GenerateBody(inParams);

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);

            // let us havoc all the global variables when fallback_unknowntype is called
            var             modSet        = context.Program.Declarations.Where(x => x is BoogieGlobalVariable).Select(x => (BoogieGlobalVariable)x).ToList();
            BoogieProcedure unknownFbProc = new BoogieProcedure("Fallback_UnknownType", inParams, outParams, attributes, modSet);

            context.Program.AddDeclaration(unknownFbProc);
        }
コード例 #2
0
        private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap)
        {
            string harnessName              = "BoogieEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = TransUtils.CollectLocalVars(new List <ContractDefinition>()
            {
                contract
            }, context);
            BoogieStmtList harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }
            harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
コード例 #3
0
        private void GenerateCorralChoiceProcForContract(ContractDefinition contract)
        {
            string procName = "CorralChoice_" + contract.Name;
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("this", BoogieType.Ref)),
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(procName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = RemoveThisFromVariables(TransUtils.CollectLocalVars(new List <ContractDefinition>()
            {
                contract
            }, context));
            BoogieStmtList procBody = GenerateHavocBlock(contract, localVars);

            procBody.AddStatement(TransUtils.GenerateChoiceBlock(new List <ContractDefinition>()
            {
                contract
            }, context));
            BoogieImplementation procImpl = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(procImpl);
        }
コード例 #4
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName              = "CorralEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            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)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
コード例 #5
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName = "CorralEntry_" + contract.Name;

            if (context.TranslateFlags.CreateMainHarness && contract.Name.Equals(context.EntryPointContract))
            {
                harnessName = "main";
            }

            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            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)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            //harnessBody.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr("this"), ));
            if (context.TranslateFlags.NoCustomTypes)
            {
                harnessBody.AddStatement((new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("null"), new BoogieLiteralExpr(0)))));
            }
            harnessBody.AddStatement(new BoogieCallCmd("FreshRefGenerator", new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
            {
                new BoogieIdentifierExpr("this")
            }));
            harnessBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("now"), new BoogieLiteralExpr(0))));
            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }
            harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
コード例 #6
0
        public void Generate()
        {
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            List <BoogieAttribute> attributes = new List <BoogieAttribute>()
            {
                new BoogieAttribute("inline", 1),
            };
            var             procName  = "FallbackDispatch";
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars  = new List <BoogieVariable>();
            var            fbUnknownProcName = "Fallback_UnknownType";
            BoogieStmtList procBody          = GenerateBodyOfFallbackDispatch(inParams, fbUnknownProcName);

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);

            // let us havoc all the global variables when fallback_unknowntype is called
            var             modSet        = context.Program.Declarations.Where(x => x is BoogieGlobalVariable).Select(x => (BoogieGlobalVariable)x).ToList();
            BoogieProcedure unknownFbProc = new BoogieProcedure(fbUnknownProcName, inParams, outParams, attributes);

            context.Program.AddDeclaration(unknownFbProc);

            // we need to create an implementation as Corral seem to ignore modifies on declarations
            // https://github.com/boogie-org/corral/issues/98
            BoogieStmtList fbBody      = new BoogieStmtList();
            var            fbLocalVars = new List <BoogieVariable>();

            if (context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks())
            {
                fbBody.AppendStmtList(CreateBodyOfUnknownFallback(fbLocalVars, inParams));
            }
            else
            {
                Debug.Assert(context.TranslateFlags.ModelStubsAsHavocs(), "Unknown option for modeling stubs");
                foreach (var global in modSet)
                {
                    fbBody.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(global.Name)));
                }
            }

            BoogieImplementation unknownFbImpl = new BoogieImplementation(fbUnknownProcName, inParams, outParams, fbLocalVars, fbBody);

            context.Program.AddDeclaration(unknownFbImpl);
        }
コード例 #7
0
ファイル: TranslatorContext.cs プロジェクト: fredfeng/verisol
 public void AddModiferToPostProc(string modifier, BoogieProcedure procedure)
 {
     if (ModifierToBoogiePostProc.ContainsKey(modifier))
     {
         throw new SystemException("duplicated modifier");
     }
     else
     {
         ModifierToBoogiePostProc[modifier] = procedure;
     }
 }
コード例 #8
0
        private void GenerateGlobalProcedureAllocMany()
        {
            if (context.TranslateFlags.LazyNestedAlloc)
            {
                return;
            }

            // generate the internal one without base constructors
            string procName = "HavocAllocMany";
            List <BoogieVariable>  inParams   = new List <BoogieVariable>();
            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);

            var oldAlloc = new BoogieLocalVariable(new BoogieTypedIdent("oldAlloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)));
            List <BoogieVariable> localVars = new List <BoogieVariable>()
            {
                oldAlloc
            };
            BoogieStmtList       procBody          = new BoogieStmtList();
            BoogieIdentifierExpr oldAllocIdentExpr = new BoogieIdentifierExpr("oldAlloc");
            BoogieIdentifierExpr allocIdentExpr    = new BoogieIdentifierExpr("Alloc");

            // oldAlloc = Alloc
            procBody.AddStatement(new BoogieAssignCmd(oldAllocIdentExpr, allocIdentExpr));
            // havoc Alloc
            procBody.AddStatement(new BoogieHavocCmd(allocIdentExpr));
            // assume forall i:ref oldAlloc[i] ==> alloc[i]
            var             qVar              = QVarGenerator.NewQVar(0, 0);
            BoogieMapSelect allocMapSelect    = new BoogieMapSelect(allocIdentExpr, qVar);
            BoogieMapSelect oldAllocMapSelect = new BoogieMapSelect(oldAllocIdentExpr, qVar);
            BoogieExpr      allocAssumeExpr   = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.IMP, oldAllocMapSelect, allocMapSelect);

            procBody.AddStatement(new BoogieAssumeCmd(new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>()
            {
                qVar
            }, new List <BoogieType>()
            {
                BoogieType.Ref
            }, allocAssumeExpr)));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);
        }
コード例 #9
0
        private BoogieProcedure duplicateProcedure(BoogieProcedure proc, string newNameSuffix, bool dropPublic = false)
        {
            BoogieProcedure dup = new BoogieProcedure(proc.Name + "__" + newNameSuffix,
                                                      new List <BoogieVariable>(proc.InParams),
                                                      new List <BoogieVariable>(proc.OutParams),
                                                      proc.Attributes != null ? new List <BoogieAttribute>(proc.Attributes) : null);

            if (dropPublic && dup.Attributes != null)
            {
                dup.Attributes.RemoveAll(attribute => attribute.Key.Equals("public"));
            }

            return(dup);
        }
コード例 #10
0
        private bool isPublic(BoogieProcedure proc)
        {
            if (proc.Attributes != null)
            {
                foreach (var attr in proc.Attributes)
                {
                    if (attr.Key.Equals("public"))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #11
0
        private void GenerateBoogieRecord(string typeName, BoogieType btype)
        {
            // generate the internal one without base constructors
            string procName = "boogie_si_record_sol2Bpl_" + typeName;
            var    inVar    = new BoogieFormalParam(new BoogieTypedIdent("x", btype));
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                inVar
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, null);

            context.Program.AddDeclaration(procedure);
        }
コード例 #12
0
        private bool isPayable(BoogieProcedure proc)
        {
            //return true;
            if (proc.Attributes != null)
            {
                foreach (var attr in proc.Attributes)
                {
                    if (attr.Key.Equals("payable"))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #13
0
        //Generate Fresh Procedure Boogie Type and add as new reference to BoogieProgram
        private void BuildGlobalProcedureFresh()
        {
            // generate the internal one without base constructors
            string procName = "FreshRefGenerator";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

            var outVar = new BoogieFormalParam(new BoogieTypedIdent("newRef", BoogieType.Ref));
            List <BoogieVariable> outParams = new List <BoogieVariable>()
            {
                outVar
            };
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (Flags_HelperClass.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.getProgram.AddBoogieDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = new BoogieStmtList();

            var outVarIdentifier = new BoogieIdentifierExpr("newRef");
            BoogieIdentifierExpr allocIdentExpr = new BoogieIdentifierExpr("Alloc");

            // havoc tmp;
            procBody.AddStatement(new BoogieHavocCmd(outVarIdentifier));
            // assume Alloc[tmp] == false;
            BoogieMapSelect allocMapSelect  = new BoogieMapSelect(allocIdentExpr, outVarIdentifier);
            BoogieExpr      allocAssumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, allocMapSelect, new BoogieLiteralExpr(false));

            procBody.AddStatement(new BoogieAssumeCmd(allocAssumeExpr));
            // Alloc[tmp] := true;
            procBody.AddStatement(new BoogieAssignCmd(allocMapSelect, new BoogieLiteralExpr(true)));
            // assume tmp != null
            procBody.AddStatement(new BoogieAssumeCmd(
                                      new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, outVarIdentifier, new BoogieIdentifierExpr("null"))));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.getProgram.AddBoogieDeclaration(implementation);
        }
コード例 #14
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);
        }
コード例 #15
0
        private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap)
        {
            string harnessName              = "BoogieEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars   = CollectLocalVars(contract);
            BoogieStmtList        harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
コード例 #16
0
ファイル: ModifierCollector.cs プロジェクト: shenshan/verisol
        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);
        }
コード例 #17
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);
        }
コード例 #18
0
        public void Generate()
        {
            // Collect Global Variables.
            HashSet <BoogieGlobalVariable> globals = new HashSet <BoogieGlobalVariable>();

            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieGlobalVariable)
                {
                    var g = (BoogieGlobalVariable)decl;

                    if (mustHaveShadow(g.Name))
                    {
                        globals.Add(g);
                    }
                }
            }

            // Generate shadow state.
            foreach (var g in globals)
            {
                var varName = g.TypedIdent.Name;
                BoogieTypedIdent     shadowGlobal     = new BoogieTypedIdent("__tmp__" + varName, g.TypedIdent.Type);
                BoogieGlobalVariable shadowGlobalDecl = new BoogieGlobalVariable(shadowGlobal);

                context.Program.AddDeclaration(shadowGlobalDecl);
                shadowGlobals.Add(varName, shadowGlobalDecl);
            }

            // Duplicate and rename methods.
            Dictionary <string, BoogieImplementation> proceduresWithImpl = new Dictionary <string, BoogieImplementation>();

            procsWiltImplNames = proceduresWithImpl.Keys;
            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieImplementation)
                {
                    var boogieImpl = ((BoogieImplementation)decl);
                    if (proceduresInProgram.ContainsKey(boogieImpl.Name))
                    {
                        proceduresWithImpl.Add(boogieImpl.Name, boogieImpl);
                    }
                }
            }

            Dictionary <string, BoogieProcedure> failProcedures = new Dictionary <string, BoogieProcedure>();

            foreach (var implPair in proceduresWithImpl)
            {
                BoogieProcedure proc = proceduresInProgram[implPair.Key];

                if (isPublic(proc) || isConstructor(proc.Name))
                {
                    // If public maintain original definition as the wrapper.
                    BoogieProcedure successVersion = duplicateProcedure(proc, "success", true);
                    //BoogieImplementation successImpl = duplicateImplementation(implPair.Value, "success");

                    context.Program.AddDeclaration(successVersion);
                    //context.Program.AddDeclaration(successImpl);

                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail", true);

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);
                }
                else if (!isHarnessProcudure(proc.Name))
                {
                    // Otherwise reuse original definition/impl as the "successful" method.
                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail");

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);

                    // Reuse original node
                    proc.Name           = proc.Name + "__success";
                    implPair.Value.Name = implPair.Value.Name + "__success";
                }
            }

            // Create implementations for failing methods.
            foreach (var failProcedurePair in failProcedures)
            {
                string          originalProcName = failProcedurePair.Key;
                BoogieProcedure proc             = failProcedurePair.Value;

                var originalImpl = proceduresWithImpl[originalProcName];
                context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl));
                context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl));

                // Remove original implementation for non-public methods
                if (!isPublic(proceduresInProgram[originalProcName]) && !isConstructor(originalProcName))
                {
                    context.Program.Declarations.Remove(originalImpl);
                }
            }

            foreach (var implPair in proceduresWithImpl)
            {
                // Update non-public methods in harness methods
                if (isHarnessProcudure(implPair.Key))
                {
                    context.Program.AddDeclaration(createSuccessImplementation(implPair.Key, implPair.Value));

                    context.Program.Declarations.Remove(implPair.Value);
                }
            }

            // Create wrappers for public methods.

            foreach (var proc in proceduresInProgram.Values)
            {
                if (proceduresWithImpl.ContainsKey(proc.Name) && (isPublic(proc) || isConstructor(proc.Name)))
                {
                    BoogieImplementation impl = proceduresWithImpl[proc.Name];
                    impl.StructuredStmts = new BoogieStmtList();
                    impl.LocalVars       = new List <BoogieVariable>();

                    var exceptionVarName = "__exception";
                    var revertGlobalName = "revert";
                    impl.LocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent(exceptionVarName, BoogieType.Bool)));

                    var stmtList = impl.StructuredStmts;
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(exceptionVarName)));
                    stmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(revertGlobalName), new BoogieLiteralExpr(false)));

                    // Call Successful version.
                    BoogieStmtList successCallStmtList = new BoogieStmtList();
                    successCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__success",
                                                                       impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                       impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    successCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName))));

                    // Call fail version.
                    BoogieStmtList failCallStmtList = new BoogieStmtList();
                    // Write global variables to temps
                    foreach (var shadowGlobalPair in shadowGlobals)
                    {
                        string origVarName = shadowGlobalPair.Key;
                        string shadowName  = shadowGlobalPair.Value.Name;
                        failCallStmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(origVarName)));
                    }
                    failCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__fail",
                                                                    impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                    impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    failCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieIdentifierExpr(revertGlobalName)));

                    stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList));
                }
            }
        }
コード例 #19
0
ファイル: ModSetAnalysis.cs プロジェクト: woods1060/verisol
        public void PerformModSetAnalysis()
        {
            BoogieProgram prog = context.Program;

            List <BoogieImplementation> impls = new List <BoogieImplementation>();
            Dictionary <string, BoogieGlobalVariable> globals    = new Dictionary <string, BoogieGlobalVariable>();
            Dictionary <string, BoogieProcedure>      procedures = new Dictionary <string, BoogieProcedure>();

            foreach (var decl in prog.Declarations)
            {
                if (decl is BoogieImplementation)
                {
                    impls.Add((BoogieImplementation)decl);
                }
                else if (decl is BoogieProcedure)
                {
                    BoogieProcedure proc = (BoogieProcedure)decl;
                    procedures.Add(proc.Name, proc);
                }
                else if (decl is BoogieGlobalVariable)
                {
                    var globalVar = (BoogieGlobalVariable)decl;
                    globals.Add(globalVar.Name, globalVar);
                }
            }

            calculateFlattenCmdLists(impls);

            foreach (var impl in impls)
            {
                HashSet <BoogieGlobalVariable> modSet = new HashSet <BoogieGlobalVariable>();
                modSets.Add(impl.Name, modSet);

                foreach (var stmt in flattenedCmdLists[impl.Name])
                {
                    switch (stmt)
                    {
                    case BoogieHavocCmd havoc:
                        foreach (var identifier in havoc.Vars)
                        {
                            var idName = identifier.Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                        }
                        break;

                    case BoogieAssignCmd assign:
                        switch (assign.Lhs)
                        {
                        case BoogieIdentifierExpr idExpr:
                        {
                            var idName = idExpr.Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                            break;
                        }

                        case BoogieMapSelect mapSelect:
                        {
                            var idName = findOutermostIdentifierExpr(mapSelect).Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                            break;
                        }

                        default:
                            throw new RuntimeWrappedException("unexpected LHS");
                        }
                        break;
                    }
                }
            }

            bool modSetChange;

            do
            {
                modSetChange = false;

                foreach (var impl in impls)
                {
                    HashSet <BoogieGlobalVariable> currModSet = modSets[impl.Name];
                    int oldSize = currModSet.Count;
                    foreach (var stmt in flattenedCmdLists[impl.Name])
                    {
                        if (stmt is BoogieCallCmd)
                        {
                            BoogieCallCmd callCmd = (BoogieCallCmd)stmt;

                            if (modSets.ContainsKey(callCmd.Callee))
                            {
                                currModSet.UnionWith(modSets[callCmd.Callee]);
                            }
                        }
                    }

                    if (currModSet.Count > oldSize)
                    {
                        modSetChange = true;
                    }
                }
            } while (modSetChange);

            foreach (var impl in impls)
            {
                procedures[impl.Name].ModSet = modSets[impl.Name].ToList();
            }
        }