static Program Process(Program program) { // find null var nil = program.TopLevelDeclarations.OfType <Constant>().Where(g => g.Name == "null").FirstOrDefault(); if (nil == null) { Console.WriteLine("Error: null not found in the input program"); return(null); } // Add Freed: [Ref] bool; Freed = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "FreedRef", new MapType(Token.NoToken, new List <TypeVariable>(), new List <btype> { nil.TypedIdent.Type }, btype.Bool))); program.AddTopLevelDeclaration(Freed); // Find "Alloc" and add "assume !Freed[x];" var allocProc = program.TopLevelDeclarations.OfType <Implementation>() .Where(impl => impl.Name == "Alloc") .FirstOrDefault(); Alloc = program.TopLevelDeclarations.OfType <GlobalVariable>() .Where(impl => impl.Name == "$Alloc") .FirstOrDefault(); if (allocProc == null || Alloc == null) { Console.WriteLine("Error: Alloc procedure not found in the input program"); return(null); } var x = allocProc.OutParams[0]; allocProc.Blocks[0].Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(BoogieAstFactory.MkMapAccessExpr(Freed, Expr.Ident(x))))); // Find System.Heap.Delete, add Freed[x] := true var freeProcs = program.TopLevelDeclarations.OfType <Implementation>() .Where(impl => impl.Name.StartsWith("System.Heap.Delete")).ToList(); if (freeProcs.Count != 1) { Console.WriteLine("Error: Free procedure not found, or multiple found in the input program"); return(null); } x = freeProcs[0].InParams[0]; freeProcs[0].Blocks[0].Cmds.Insert(0, BoogieAstFactory.MkMapAssign(Freed, Expr.Ident(x), Expr.Literal(true))); DesugarIte.Instrument(program); InstrumentMemoryAccesses.Instrument(program, nil); return(program); }
//Change the body of any stub that returns a pointer into calling unknown() //TODO: only do this for procedures with a single return with a pointer type private void MkStubImplementation(List <Implementation> stubImpls, Procedure p) { List <Cmd> cmds = new List <Cmd>(); List <Variable> localVars = new List <Variable>(); stubs.Add(p.Name); foreach (var op in p.OutParams) { if (IsPointerVariable(op)) { cmds.Add(AllocatePointerAsUnknown(op)); } else { // Avoid using Havoc -- we'll let this fall on the floor as an // uninitialized variable. AVN will take care of concretizing it //cmds.Add(BoogieAstFactory.MkHavocVar(op)); } } foreach (var v in p.Modifies.Select(ie => ie.Decl)) { if (IsPointerVariable(v)) { cmds.Add(AllocatePointerAsUnknown(v)); } else { // unsupported Console.WriteLine("Warning: demonic havoc of global {0} in {1}", v.Name, p.Name); } } foreach (var ip in p.InParams) { if (!BoogieUtil.checkAttrExists("ref", ip.Attributes)) { continue; } string mapName = QKeyValue.FindStringAttribute(ip.Attributes, "ref"); if (mapName == null) { Utils.Print(String.Format("Expecting a map <name> with {:ref <name>} annotation on procedure {0}", p.Name), Utils.PRINT_TAG.AV_WARNING); continue; } var mapVars = prog.TopLevelDeclarations.OfType <Variable>().Where(x => x.Name == mapName && x.TypedIdent.Type.IsMap); if (mapVars.Count() != 1) { Utils.Print(String.Format("Mapname {0} provided in {{:ref}} for parameter {1} for procedure {2} has {3} matches, expecting exactly 1 match", mapName, ip.Name, p.Name, mapVars.Count()), Utils.PRINT_TAG.AV_WARNING); continue; } var tmpVar = BoogieAstFactory.MkLocal("__tmp_" + ip.Name, ip.TypedIdent.Type); localVars.Add(tmpVar); cmds.Add(AllocatePointerAsUnknown(tmpVar)); cmds.Add(BoogieAstFactory.MkMapAssign(mapVars.First(), IdentifierExpr.Ident(ip), IdentifierExpr.Ident(tmpVar))); } if (cmds.Count == 0) { return; //don't create a body if no statements } var blk = BoogieAstFactory.MkBlock(cmds, new ReturnCmd(Token.NoToken)); var blks = new List <Block>() { blk }; //don't insert the proc as it already exists var impl = BoogieAstFactory.MkImpl(p.Name, DropAnnotations(p.InParams), DropAnnotations(p.OutParams), new List <Variable>(), blks); ((Implementation)impl[1]).LocVars.AddRange(localVars); stubImpls.Add((Implementation)impl[1]); }