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); }
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); }
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); }
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); }
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); }
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); }
public void AddModiferToPostProc(string modifier, BoogieProcedure procedure) { if (ModifierToBoogiePostProc.ContainsKey(modifier)) { throw new SystemException("duplicated modifier"); } else { ModifierToBoogiePostProc[modifier] = procedure; } }
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); }
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); }
private bool isPublic(BoogieProcedure proc) { if (proc.Attributes != null) { foreach (var attr in proc.Attributes) { if (attr.Key.Equals("public")) { return(true); } } } return(false); }
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); }
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); }
//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); }
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); }
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); }
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 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 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)); } } }
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(); } }