private void RefactorFunctionPointersAcrossCalls(Block block) { if (block.Cmds.Count == 0) { return; } var cmds = block.Cmds.Where(v => !((v is AssumeCmd) && (v as AssumeCmd).Expr.Equals(Expr.True))).ToList(); if (cmds.Count == 0) { return; } for (int idx = 0; idx < cmds.Count - 1; idx++) { if (!(cmds[idx] is AssignCmd && cmds[idx + 1] is CallCmd)) { continue; } var assign = cmds[idx] as AssignCmd; var call = cmds[idx + 1] as CallCmd; var lhs = assign.Lhss[0].DeepAssignedIdentifier; var inParam = call.Ins.FirstOrDefault(v => v is IdentifierExpr && (v as IdentifierExpr).Name.Equals(lhs.Name)); if (inParam == null) { continue; } int index = -1; for (int i = 0; i < call.Ins.Count; i++) { if (call.Ins[i] is IdentifierExpr && (call.Ins[i] as IdentifierExpr).Name.Equals(lhs.Name)) { index = i; break; } } if (index < 0) { continue; } var callImpl = this.AC.GetImplementation(call.callee); if (callImpl == null) { continue; } var funcPtrBlocks = this.GetFuncPtrBlocks(callImpl, index); if (funcPtrBlocks.Item2.Count > 0) { for (int bIdx = 0; bIdx < block.Cmds.Count; bIdx++) { if (block.Cmds[bIdx].Equals(assign)) { var assume = block.Cmds[bIdx + 1] as AssumeCmd; QKeyValue curr = assume.Attributes; while (curr != null) { if (curr.Key.Equals("sourceloc")) { break; } curr = curr.Next; } Contract.Requires(curr.Key.Equals("sourceloc") && curr.Params.Count == 3); int line = Int32.Parse(string.Format("{0}", curr.Params[1])); HashSet <string> funcPtrs = null; if (FunctionPointerInformation.TryGetFromLine(line, out funcPtrs)) { var blocks = new List <Block>(); foreach (var ptrBlock in funcPtrBlocks.Item2) { if (!funcPtrs.Contains(ptrBlock.Key)) { blocks.Add(ptrBlock.Value); } } call.callee = this.CreateNewImplementation(funcPtrBlocks.Item1, blocks); } break; } } } } }
private List <Block> RefactorFunctionPointers(Implementation impl, Block block) { var blocks = new List <Block>(); if (block.Cmds.Count == 0 || !(block.TransferCmd is GotoCmd)) { return(blocks); } var cmds = block.Cmds.Where(v => !((v is AssumeCmd) && (v as AssumeCmd).Expr.Equals(Expr.True))).ToList(); if (cmds.Count == 0 || !(cmds[cmds.Count - 1] is AssignCmd)) { return(blocks); } var transferCmd = block.TransferCmd as GotoCmd; var assign = cmds[cmds.Count - 1] as AssignCmd; var lhs = assign.Lhss[0].DeepAssignedIdentifier; var funcPtrBlocks = this.GetFuncPtrBlocks(transferCmd.labelTargets, lhs.Name); if (funcPtrBlocks.Count > 0) { for (int bIdx = 0; bIdx < block.Cmds.Count; bIdx++) { if (block.Cmds[bIdx].Equals(assign)) { var assume = block.Cmds[bIdx + 1] as AssumeCmd; QKeyValue curr = assume.Attributes; while (curr != null) { if (curr.Key.Equals("sourceloc")) { break; } curr = curr.Next; } Contract.Requires(curr.Key.Equals("sourceloc") && curr.Params.Count == 3); int line = Int32.Parse(string.Format("{0}", curr.Params[1])); HashSet <string> funcPtrs = null; if (FunctionPointerInformation.TryGetFromLine(line, out funcPtrs)) { foreach (var ptrBlock in funcPtrBlocks) { if (!funcPtrs.Contains(ptrBlock.Key)) { transferCmd.labelTargets.Remove(ptrBlock.Value); transferCmd.labelNames.Remove(ptrBlock.Value.Label); blocks.Add(ptrBlock.Value); } } break; } Tuple <string, string> macro = null; FunctionPointerInformation.TryGetFromMacro(line, out macro); var rhs = (assign.Rhss[0] as NAryExpr).Args[1]; HashSet <Expr> ptrExprs = null; new PointerArithmeticAnalyser(this.AC, this.EP, impl).TryComputeRootPointers(rhs, out ptrExprs); var ptrExpr = ptrExprs.FirstOrDefault(); if (ptrExpr == null) { break; } var index = -1; if (!this.TryGetIndex(impl, ptrExpr, out index)) { break; } var outcome = new Stack <Tuple <Implementation, CallCmd> >(); this.RefactorFunctionPointersInCallGraph(impl, index, macro, funcPtrBlocks, outcome); break; } } } return(blocks); }