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); } } }
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)); }