Beispiel #1
0
        private void DesugarConcurrency(Implementation impl)
        {
            var allYieldPredicates         = CollectYields(impl);
            var allNonemptyYieldPredicates = allYieldPredicates.Values.Where(x => x.Count > 0);

            if (allNonemptyYieldPredicates.Count() > 0)
            {
                yieldCheckerDecls.AddRange(noninterferenceInstrumentation.CreateYieldCheckerProcImpl(impl, allNonemptyYieldPredicates));
            }

            var yieldCheckerBlock      = CreateYieldCheckerBlock();
            var refinementCheckerBlock = CreateRefinementCheckerBlock();
            var refinementCheckerForYieldingLoopsBlock = CreateRefinementCheckerBlockForYieldingLoops();
            var returnBlock = CreateReturnBlock();

            SplitBlocks(impl);

            HashSet <Block> yieldingLoopHeaders;
            HashSet <Block> blocksInYieldingLoops;

            ComputeYieldingLoops(impl, out yieldingLoopHeaders, out blocksInYieldingLoops);
            foreach (Block header in yieldingLoopHeaders)
            {
                foreach (Block pred in header.Predecessors)
                {
                    var gotoCmd = pred.TransferCmd as GotoCmd;
                    AddEdge(gotoCmd, yieldCheckerBlock);
                    if (blocksInYieldingLoops.Contains(pred))
                    {
                        AddEdge(gotoCmd, refinementCheckerForYieldingLoopsBlock);
                    }
                    else
                    {
                        AddEdge(gotoCmd, refinementCheckerBlock);
                    }
                }
                List <Cmd> firstCmds;
                List <Cmd> secondCmds;
                SplitCmds(header.Cmds, out firstCmds, out secondCmds);
                List <Cmd> newCmds = new List <Cmd>();
                newCmds.AddRange(firstCmds);
                newCmds.AddRange(globalSnapshotInstrumentation.CreateUpdatesToOldGlobalVars());
                newCmds.AddRange(refinementInstrumentation.CreateUpdatesToOldOutputVars());
                newCmds.AddRange(noninterferenceInstrumentation.CreateUpdatesToPermissionCollector(header));
                newCmds.AddRange(secondCmds);
                header.Cmds = newCmds;
            }

            // add jumps to yieldCheckerBlock and returnBlock
            foreach (var b in impl.Blocks)
            {
                if (b.TransferCmd is GotoCmd gotoCmd)
                {
                    var addEdge = false;
                    foreach (var nextBlock in gotoCmd.labelTargets)
                    {
                        if (nextBlock.cmds.Count > 0)
                        {
                            var cmd = nextBlock.cmds[0];
                            if (cmd is YieldCmd)
                            {
                                addEdge = true;
                            }
                            else if (cmd is CallCmd callCmd && yieldingProcs.Contains(callCmd.Proc))
                            {
                                addEdge = true;
                            }
                            else if (cmd is ParCallCmd)
                            {
                                addEdge = true;
                            }
                        }
                    }
                    if (addEdge)
                    {
                        AddEdge(gotoCmd, yieldCheckerBlock);
                        if (blocksInYieldingLoops.Contains(b))
                        {
                            AddEdge(gotoCmd, refinementCheckerForYieldingLoopsBlock);
                        }
                        else
                        {
                            AddEdge(gotoCmd, refinementCheckerBlock);
                        }
                    }
                }
Beispiel #2
0
        private void DesugarConcurrency(Implementation impl, List <Cmd> preconditions)
        {
            var noninterferenceCheckerBlock            = CreateNoninterferenceCheckerBlock();
            var refinementCheckerBlock                 = CreateRefinementCheckerBlock();
            var refinementCheckerForYieldingLoopsBlock = CreateRefinementCheckerBlockForYieldingLoops();
            var returnCheckerBlock = CreateReturnCheckerBlock();
            var returnBlock        = new Block(Token.NoToken, civlTypeChecker.AddNamePrefix("UnifiedReturn"), new List <Cmd>(), new ReturnCmd(Token.NoToken));

            SplitBlocks(impl);

            HashSet <Block> yieldingLoopHeaders;
            HashSet <Block> blocksInYieldingLoops;

            ComputeYieldingLoops(impl, out yieldingLoopHeaders, out blocksInYieldingLoops);
            foreach (Block header in yieldingLoopHeaders)
            {
                foreach (Block pred in header.Predecessors)
                {
                    var gotoCmd = pred.TransferCmd as GotoCmd;
                    AddEdge(gotoCmd, noninterferenceCheckerBlock);
                    if (blocksInYieldingLoops.Contains(pred))
                    {
                        AddEdge(gotoCmd, refinementCheckerForYieldingLoopsBlock);
                    }
                    else
                    {
                        AddEdge(gotoCmd, refinementCheckerBlock);
                    }
                }

                List <Cmd> firstCmds;
                List <Cmd> secondCmds;
                SplitCmds(header.Cmds, out firstCmds, out secondCmds);
                List <Cmd> newCmds = new List <Cmd>();
                newCmds.AddRange(firstCmds);
                newCmds.AddRange(refinementInstrumentation.CreateAssumeCmds());
                newCmds.AddRange(
                    InlineYieldLoopInvariants(civlTypeChecker.yieldingLoops[absyMap.Original(header)].yieldInvariants));
                newCmds.AddRange(YieldingLoopDummyAssignment());
                newCmds.AddRange(globalSnapshotInstrumentation.CreateUpdatesToOldGlobalVars());
                newCmds.AddRange(refinementInstrumentation.CreateUpdatesToOldOutputVars());
                newCmds.AddRange(noninterferenceInstrumentation.CreateUpdatesToPermissionCollector(header));
                newCmds.AddRange(secondCmds);
                header.Cmds = newCmds;
            }

            // add jumps to noninterferenceCheckerBlock, returnBlock, and refinement blocks
            var implRefinementCheckingBlocks = new List <Block>();

            foreach (var b in impl.Blocks)
            {
                if (b.TransferCmd is GotoCmd gotoCmd)
                {
                    var targetBlocks = new List <Block>();
                    var addEdge      = false;
                    foreach (var nextBlock in gotoCmd.labelTargets)
                    {
                        if (nextBlock.cmds.Count > 0)
                        {
                            var cmd = nextBlock.cmds[0];
                            if (cmd is YieldCmd)
                            {
                                addEdge = true;
                            }
                            else if (cmd is ParCallCmd parCallCmd)
                            {
                                foreach (var callCmd in parCallCmd.CallCmds)
                                {
                                    if (refinementBlocks.ContainsKey(callCmd))
                                    {
                                        var targetBlock = refinementBlocks[callCmd];
                                        FixUpImplRefinementCheckingBlock(targetBlock,
                                                                         IsCallMarked(callCmd)
                        ? returnCheckerBlock
                        : refinementCheckerForYieldingLoopsBlock);
                                        targetBlocks.Add(targetBlock);
                                        implRefinementCheckingBlocks.Add(targetBlock);
                                    }
                                }

                                addEdge = true;
                            }
                        }
                    }

                    gotoCmd.labelNames.AddRange(targetBlocks.Select(block => block.Label));
                    gotoCmd.labelTargets.AddRange(targetBlocks);
                    if (addEdge)
                    {
                        AddEdge(gotoCmd, noninterferenceCheckerBlock);
                        AddEdge(gotoCmd,
                                blocksInYieldingLoops.Contains(b)
                ? refinementCheckerForYieldingLoopsBlock
                : refinementCheckerBlock);
                    }
                }
                else
                {
                    b.TransferCmd = new GotoCmd(b.TransferCmd.tok,
                                                new List <string> {
                        returnCheckerBlock.Label, returnBlock.Label, noninterferenceCheckerBlock.Label
                    },
                                                new List <Block> {
                        returnCheckerBlock, returnBlock, noninterferenceCheckerBlock
                    });
                }
            }

            // desugar YieldCmd, CallCmd, and ParCallCmd
            foreach (Block b in impl.Blocks)
            {
                if (b.cmds.Count > 0)
                {
                    var cmd = b.cmds[0];
                    if (cmd is YieldCmd)
                    {
                        DesugarYieldCmdInBlock(b, blocksInYieldingLoops.Contains(b));
                    }
                    else if (cmd is ParCallCmd)
                    {
                        DesugarParCallCmdInBlock(b, blocksInYieldingLoops.Contains(b));
                    }
                }
            }

            impl.Blocks.Add(noninterferenceCheckerBlock);
            impl.Blocks.Add(refinementCheckerBlock);
            impl.Blocks.Add(refinementCheckerForYieldingLoopsBlock);
            impl.Blocks.Add(returnCheckerBlock);
            impl.Blocks.Add(returnBlock);
            impl.Blocks.AddRange(implRefinementCheckingBlocks);
            impl.Blocks.Insert(0, CreateInitialBlock(impl, preconditions));
        }