public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { int callCmdCount = -1; var newCmdSeq = new List <Cmd>(); foreach (Cmd c in cmdSeq) { newCmdSeq.Add(c); var callCmd = c as CallCmd; if (callCmd != null) { callCmdCount++; } if (callCmd != null && BoogieUtil.checkAttrExists(AvnAnnotations.AngelicUnknownCall, callCmd.Proc.Attributes)) { var retCall = callCmd.Outs[0]; btype retType = callCmd.Proc.OutParams[0].TypedIdent.Type; if (retType == null) { retType = btype.Int; } var mallocTriggerFn = new Function(Token.NoToken, mallocTriggerFuncName + mallocTriggers.Count, new List <Variable>() { BoogieAstFactory.MkFormal("a", retType, false) }, BoogieAstFactory.MkFormal("r", btype.Bool, false)); mallocTriggers[callCmd] = mallocTriggerFn; var callId = QKeyValue.FindIntAttribute(callCmd.Attributes, cba.RestrictToTrace.ConcretizeCallIdAttr, -1); Debug.Assert(callId == -1, "Calls to unknown must not already be tagged with an ID"); callId = instance.id++; callCmd.Attributes = new QKeyValue(Token.NoToken, cba.RestrictToTrace.ConcretizeCallIdAttr, new List <object> { Expr.Literal(callId) }, callCmd.Attributes); instance.mallocTriggersLocation[callId] = mallocTriggerFn.Name; instance.mallocTriggerToAllocationSite[mallocTriggerFn.Name] = callId; instance.prog.AddTopLevelDeclaration(mallocTriggerFn); var fnApp = new NAryExpr(Token.NoToken, new FunctionCall(mallocTriggerFn), new List <Expr> () { retCall }); newCmdSeq.Add(BoogieAstFactory.MkAssume(fnApp)); } } return(base.VisitCmdSeq(newCmdSeq)); }
void Desugar(Variable lhs, Expr cond, Expr then, Expr els, ref List <Cmd> currCmds, ref Block currBlock, List <Block> newBlocks) { // create three new blocks var lab1 = GetNewLabel(); var lab2 = GetNewLabel(); var lab3 = GetNewLabel(); var tmp = CreateTmp(btype.Bool); currCmds.Add(BoogieAstFactory.MkVarEqExpr(tmp, cond)); // end current block currBlock.Cmds = currCmds; currBlock.TransferCmd = new GotoCmd(Token.NoToken, new List <string> { lab1, lab2 }); newBlocks.Add(currBlock); var blk1 = new Block(Token.NoToken, lab1, new List <Cmd>(), BoogieAstFactory.MkGotoCmd(lab3)); var blk2 = new Block(Token.NoToken, lab2, new List <Cmd>(), BoogieAstFactory.MkGotoCmd(lab3)); blk1.Cmds.AddRange( new List <Cmd> { BoogieAstFactory.MkAssume(Expr.Ident(tmp)), BoogieAstFactory.MkVarEqExpr(lhs, then) }); blk2.Cmds.AddRange( new List <Cmd> { BoogieAstFactory.MkAssume(Expr.Not(Expr.Ident(tmp))), BoogieAstFactory.MkVarEqExpr(lhs, els) }); newBlocks.Add(blk1); newBlocks.Add(blk2); currBlock = new Block(Token.NoToken, lab3, new List <Cmd>(), null); currCmds = new List <Cmd>(); }
public void SuppressToken(AssertToken token) { var location = tokenLocation[token]; if (Options.DeepAsserts) { location = Tuple.Create((output as PersistentProgram).mainProcName, location.Item2); } var p = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations, location.Item1); var block = p.Blocks.Where(blk => blk.Label == location.Item2).FirstOrDefault(); // disable assignment to assertsPassed var ncmds = new List <Cmd>(); foreach (var cmd in block.Cmds) { if (!Options.DeepAsserts && (cmd is AssignCmd) && (cmd as AssignCmd).Lhss[0].DeepAssignedVariable.Name == assertsPassedName) { var acmd = BoogieAstFactory.MkAssume((cmd as AssignCmd).Rhss[0]) as AssumeCmd; acmd.Attributes = new QKeyValue(Token.NoToken, "suppressAssert", new List <object> { Expr.Literal(token.id) }, null); ncmds.Add(acmd); } else if (Options.DeepAsserts && (cmd is AssertCmd) && QKeyValue.FindIntAttribute((cmd as AssertCmd).Attributes, "avn", -1) == token.id) { var acmd = new AssumeCmd(Token.NoToken, (cmd as AssertCmd).Expr, (cmd as AssertCmd).Attributes); ncmds.Add(acmd); } else { ncmds.Add(cmd); } } block.Cmds = ncmds; }
// This is to avoid a corner-case with ModifyTrans where some statements // that are deleted by the transformation are picked up at the end of the // trace while mapping back. // We avoid this by adding "assume true" right after procedure calls private cba.InsertionTrans AddBlanks(Program program) { var tinfo = new cba.InsertionTrans(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { var currCmds = new List <Cmd>(); tinfo.addTrans(impl.Name, blk.Label, blk.Label); var incnt = -1; foreach (Cmd cmd in blk.Cmds) { incnt++; // procedure call if (cmd is CallCmd) { currCmds.Add(cmd); tinfo.addTrans(impl.Name, blk.Label, incnt, cmd, blk.Label, currCmds.Count - 1, new List <Cmd> { currCmds.Last() }); currCmds.Add(BoogieAstFactory.MkAssume(Expr.True)); continue; } currCmds.Add(cmd); tinfo.addTrans(impl.Name, blk.Label, incnt, cmd, blk.Label, currCmds.Count - 1, new List <Cmd> { currCmds.Last() }); } blk.Cmds = currCmds; } } return(tinfo); }
private void CreateMainProcedure(Function reach) { //blocks List <Block> mainBlocks = new List <Block>(); List <Variable> locals = new List <Variable>(); HashSet <Constant> blockCallConsts = new HashSet <Constant>(); foreach (Implementation impl in prog.TopLevelDeclarations.Where(x => x is Implementation)) { // skip this impl if it is not marked as an entrypoint if (useProvidedEntryPoints && !QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "entrypoint")) { continue; } impl.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Attributes); impl.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Proc.Attributes); // skip initialization procedure if (QKeyValue.FindBoolAttribute(impl.Attributes, AvnAnnotations.InitialializationProcAttr) || QKeyValue.FindBoolAttribute(impl.Proc.Attributes, AvnAnnotations.InitialializationProcAttr)) { continue; } entrypoints.Add(impl.Name); //allocate params var args = new List <Variable>(); var rets = new List <Variable>(); impl.OutParams.ForEach(v => rets.Add(BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type))); if (Options.allocateParameters) { // use impl.Proc here to pickup scalar/pointer attributes impl.Proc.InParams.ForEach(v => { var l = BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type); // We are delibrately dropping the attributes so that // all parameters are initialized by allocation //l.Attributes = v.Attributes; args.Add(l); }); locals.AddRange(args); } else { impl.Proc.InParams.ForEach(v => { var g = BoogieAstFactory.MkGlobal(v.Name + "_" + impl.Name, v.TypedIdent.Type); //g.Attributes = v.Attributes; args.Add(g); }); globalParams.AddRange(args); } locals.AddRange(rets); //call var blockCallConst = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "__block_call_" + impl.Name, btype.Bool), false); blockCallConsts.Add(blockCallConst); blockEntryPointConstants[blockCallConst.Name] = impl.Name; impl2BlockingConstant[impl.Name] = blockCallConst; var blockCallAssumeCmd = new AssumeCmd(Token.NoToken, IdentifierExpr.Ident(blockCallConst)); var cmds = new List <Cmd>(); cmds.Add(blockCallAssumeCmd); if (Options.allocateParameters) // allocate parameters if option is enabled { var argMallocCmds = AllocatePointersAsUnknowns(args); cmds.AddRange(argMallocCmds); } // The beginning of an entry point must be reachable: assume reach(true); cmds.Add(new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken, new FunctionCall(reach), new List <Expr> { Expr.True }))); var callCmd = new CallCmd(Token.NoToken, impl.Name, args.ConvertAll(x => (Expr)IdentifierExpr.Ident(x)), rets.ConvertAll(x => IdentifierExpr.Ident(x))); callCmd.Attributes = new QKeyValue(Token.NoToken, AvUtil.AvnAnnotations.AvhEntryPointAttr, new List <object>(), callCmd.Attributes); cmds.Add(callCmd); //succ var txCmd = new ReturnCmd(Token.NoToken); var blk = BoogieAstFactory.MkBlock(cmds, txCmd); mainBlocks.Add(blk); } foreach (Procedure proc in prog.TopLevelDeclarations.OfType <Procedure>()) { proc.Attributes = BoogieUtil.removeAttr("entrypoint", proc.Attributes); } // add global variables to prog // globals.Iter(x => prog.AddTopLevelDeclaration(x)); //add the constants to the prog blockCallConsts.Iter(x => prog.AddTopLevelDeclaration(x)); //TODO: get globals of type refs/pointers and maps var initCmd = (AssumeCmd)BoogieAstFactory.MkAssume(Expr.True); var globalCmds = new List <Cmd>() { initCmd }; //add call to corralExtraInit var init = Instrumentations.GetEnvironmentAssumptionsProc(prog); if (init != null && !Options.DelayInitialization) { globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>())); } // Dont initialize Boogie instrumentation variables prog.GlobalVariables .Where(g => g.Name == "alloc" || BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes)) .Where(g => !BoogieUtil.checkAttrExists("scalar", g.Attributes)) .Iter(g => g.AddAttribute("scalar")); // initialize globals prog.GlobalVariables .Where(g => g.Name != "alloc" && !BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes)) .Iter(g => g.Attributes = BoogieUtil.removeAttrs(new HashSet <string> { "scalar", "pointer" }, g.Attributes)); globalCmds.AddRange(AllocatePointersAsUnknowns(prog.GlobalVariables.Select(x => (Variable)x).ToList())); if (init != null && Options.DelayInitialization) { globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>())); } // globals for parameters prog.AddTopLevelDeclarations(globalParams); //first block var transferCmd = mainBlocks.Count > 0 ? (TransferCmd)(new GotoCmd(Token.NoToken, mainBlocks)) : (TransferCmd)(new ReturnCmd(Token.NoToken)); Block blkStart = new Block(Token.NoToken, "CorralMainStart", globalCmds, transferCmd); var blocks = new List <Block>(); blocks.Add(blkStart); blocks.AddRange(mainBlocks); var mainProcImpl = BoogieAstFactory.MkImpl(AvnAnnotations.CORRAL_MAIN_PROC, new List <Variable>(), new List <Variable>(), locals, blocks); mainProcImpl[0].AddAttribute("entrypoint"); prog.AddTopLevelDeclarations(mainProcImpl); }