private void DesugarConcurrency(Implementation impl, Graph <Block> graph, HashSet <Block> yieldingLoopHeaders)
        {
            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 returnBlock       = CreateReturnBlock();

            SplitBlocks(impl);

            // 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)
                    {
                        gotoCmd.labelNames.Add(yieldCheckerBlock.Label);
                        gotoCmd.labelTargets.Add(yieldCheckerBlock);
                    }
                }
Example #2
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);
                        }
                    }
                }