@@ -3,43 +3,42 @@ open Queue
33open Cil
44include CompareAST
55
6- (* Non propagating version of &&>>. Discards the new rename_mapping and alwas propagates the one in prev_result*)
6+ (* Non propagating version of &&>>. Discards the new rename_mapping and alwas propagates the one in prev_result. However propagates the renames_on_success *)
77let (&&<>) (prev_result : bool * rename_mapping ) f : bool * rename_mapping =
88 let (prev_equal, prev_rm) = prev_result in
9+ let (a, b, c, _) = prev_rm in
10+
911 if prev_equal then
10- let (r, _ ) = f prev_rm in
11- (r, prev_rm )
12+ let (r, (_, _, _, updated_renames_on_success) ) = f prev_rm in
13+ (r, (a, b, c, updated_renames_on_success) )
1214 else false , prev_rm
1315
14- let eq_node (x , fun1 ) (y , fun2 ) : bool =
15- let empty_rename_mapping: rename_mapping = emptyRenameMapping in
16+ let eq_node (x , fun1 ) (y , fun2 ) rename_mapping =
1617 match x,y with
17- | Statement s1 , Statement s2 -> eq_stmt ~cfg_comp: true (s1, fun1) (s2, fun2) empty_rename_mapping |> fst
18- | Function f1 , Function f2 -> eq_varinfo f1.svar f2.svar empty_rename_mapping |> fst
19- | FunctionEntry f1 , FunctionEntry f2 -> eq_varinfo f1.svar f2.svar empty_rename_mapping |> fst
20- | _ -> false
18+ | Statement s1 , Statement s2 -> eq_stmt ~cfg_comp: true (s1, fun1) (s2, fun2) rename_mapping
19+ | Function f1 , Function f2 -> eq_varinfo f1.svar f2.svar rename_mapping
20+ | FunctionEntry f1 , FunctionEntry f2 -> eq_varinfo f1.svar f2.svar rename_mapping
21+ | _ -> false , rename_mapping
2122
2223(* TODO: compare ASMs properly instead of simply always assuming that they are not the same *)
23- let eq_edge x y =
24- let empty_rename_mapping: rename_mapping = emptyRenameMapping in
25- let (r, _) = match x, y with
26- | Assign (lv1 , rv1 ), Assign (lv2 , rv2 ) -> eq_lval lv1 lv2 empty_rename_mapping &&<> eq_exp rv1 rv2
27- | Proc (None,f1 ,ars1 ), Proc (None,f2 ,ars2 ) -> eq_exp f1 f2 empty_rename_mapping &&<> forward_list_equal eq_exp ars1 ars2
28- | Proc (Some r1 ,f1 ,ars1 ), Proc (Some r2 ,f2 ,ars2 ) ->
29- eq_lval r1 r2 empty_rename_mapping &&<> eq_exp f1 f2 &&<> forward_list_equal eq_exp ars1 ars2
30- | Entry f1 , Entry f2 -> eq_varinfo f1.svar f2.svar empty_rename_mapping
31- | Ret (None,fd1 ), Ret (None,fd2 ) -> eq_varinfo fd1.svar fd2.svar empty_rename_mapping
32- | Ret (Some r1 ,fd1 ), Ret (Some r2 ,fd2 ) -> eq_exp r1 r2 empty_rename_mapping &&<> eq_varinfo fd1.svar fd2.svar
33- | Test (p1 ,b1 ), Test (p2 ,b2 ) -> eq_exp p1 p2 empty_rename_mapping &&> (b1 = b2)
34- | ASM _ , ASM _ -> false , empty_rename_mapping
35- | Skip , Skip -> true , empty_rename_mapping
36- | VDecl v1 , VDecl v2 -> eq_varinfo v1 v2 empty_rename_mapping
37- | _ -> false , empty_rename_mapping
38- in
39- r
24+ let eq_edge x y rename_mapping =
25+ match x, y with
26+ | Assign (lv1 , rv1 ), Assign (lv2 , rv2 ) -> eq_lval lv1 lv2 rename_mapping &&<> eq_exp rv1 rv2
27+ | Proc (None,f1 ,ars1 ), Proc (None,f2 ,ars2 ) -> eq_exp f1 f2 rename_mapping &&<> forward_list_equal eq_exp ars1 ars2
28+ | Proc (Some r1 ,f1 ,ars1 ), Proc (Some r2 ,f2 ,ars2 ) ->
29+ eq_lval r1 r2 rename_mapping &&<> eq_exp f1 f2 &&<> forward_list_equal eq_exp ars1 ars2
30+ | Entry f1 , Entry f2 -> eq_varinfo f1.svar f2.svar rename_mapping
31+ | Ret (None,fd1 ), Ret (None,fd2 ) -> eq_varinfo fd1.svar fd2.svar rename_mapping
32+ | Ret (Some r1 ,fd1 ), Ret (Some r2 ,fd2 ) -> eq_exp r1 r2 rename_mapping &&<> eq_varinfo fd1.svar fd2.svar
33+ | Test (p1 ,b1 ), Test (p2 ,b2 ) -> eq_exp p1 p2 rename_mapping &&> (b1 = b2)
34+ | ASM _ , ASM _ -> false , rename_mapping
35+ | Skip , Skip -> true , rename_mapping
36+ | VDecl v1 , VDecl v2 -> eq_varinfo v1 v2 rename_mapping
37+ | _ -> false , rename_mapping
38+
4039
4140(* The order of the edges in the list is relevant. Therefore compare them one to one without sorting first *)
42- let eq_edge_list xs ys = GobList. equal eq_edge xs ys
41+ let eq_edge_list xs ys = forward_list_equal ~prop F:( &&<> ) eq_edge xs ys
4342
4443let to_edge_list ls = List. map (fun (loc , edge ) -> edge) ls
4544
@@ -52,38 +51,41 @@ type biDirectionNodeMap = {node1to2: node NH.t; node2to1: node NH.t}
5251 * in the succesors of fromNode2 in the new CFG. Matching node tuples are added to the waitingList to repeat the matching
5352 * process on their successors. If a node from the old CFG can not be matched, it is added to diff and no further
5453 * comparison is done for its successors. The two function entry nodes make up the tuple to start the comparison from. *)
55- let compareCfgs (module CfgOld : CfgForward ) (module CfgNew : CfgForward ) fun1 fun2 =
54+
55+ let compareCfgs (module CfgOld : CfgForward ) (module CfgNew : CfgForward ) fun1 fun2 rename_mapping : biDirectionNodeMap * unit NH.t * rename_mapping =
5656 let diff = NH. create 113 in
5757 let same = {node1to2= NH. create 113 ; node2to1= NH. create 113 } in
5858 let waitingList : (node * node) t = Queue. create () in
5959
60- let rec compareNext () =
61- if Queue. is_empty waitingList then ()
60+ let rec compareNext () rename_mapping : rename_mapping =
61+ if Queue. is_empty waitingList then rename_mapping
6262 else
6363 let fromNode1, fromNode2 = Queue. take waitingList in
6464 let outList1 = CfgOld. next fromNode1 in
6565 let outList2 = CfgNew. next fromNode2 in
6666
6767 (* Find a matching edge and successor node for (edgeList1, toNode1) in the list of successors of fromNode2.
6868 * If successful, add the matching node tuple to same, else add toNode1 to the differing nodes. *)
69- let findMatch (edgeList1 , toNode1 ) =
70- let rec aux remSuc = match remSuc with
71- | [] -> NH. replace diff toNode1 ()
69+ let findMatch (edgeList1 , toNode1 ) rename_mapping : rename_mapping =
70+ let rec aux remSuc rename_mapping : rename_mapping = match remSuc with
71+ | [] -> NH. replace diff toNode1 () ; rename_mapping
7272 | (locEdgeList2 , toNode2 )::remSuc' ->
7373 let edgeList2 = to_edge_list locEdgeList2 in
7474 (* TODO: don't allow pseudo return node to be equal to normal return node, could make function unchanged, but have different sallstmts *)
75- if eq_node (toNode1, fun1) (toNode2, fun2) && eq_edge_list edgeList1 edgeList2 then
75+ let (isEq, updatedRenameMapping) = (true , rename_mapping) &&>> eq_node (toNode1, fun1) (toNode2, fun2) &&>> eq_edge_list edgeList1 edgeList2 in
76+ if isEq then
7677 begin
7778 match NH. find_opt same.node1to2 toNode1 with
78- | Some n2 -> if not (Node. equal n2 toNode2) then NH. replace diff toNode1 ()
79- | None -> NH. replace same.node1to2 toNode1 toNode2; NH. replace same.node2to1 toNode2 toNode1; Queue. add (toNode1, toNode2) waitingList
79+ | Some n2 -> if not (Node. equal n2 toNode2) then NH. replace diff toNode1 () ; updatedRenameMapping
80+ | None -> NH. replace same.node1to2 toNode1 toNode2; NH. replace same.node2to1 toNode2 toNode1; Queue. add (toNode1, toNode2) waitingList;
81+ updatedRenameMapping
8082 end
81- else aux remSuc' in
82- aux outList2 in
83+ else aux remSuc' updatedRenameMapping in
84+ aux outList2 rename_mapping in
8385 (* For a toNode1 from the list of successors of fromNode1, check whether it might have duplicate matches.
8486 * In that case declare toNode1 as differing node. Else, try finding a match in the list of successors
8587 * of fromNode2 in the new CFG using findMatch. *)
86- let iterOuts (locEdgeList1 , toNode1 ) =
88+ let iterOuts (locEdgeList1 , toNode1 ) rename_mapping : rename_mapping =
8789 let edgeList1 = to_edge_list locEdgeList1 in
8890 (* Differentiate between a possibly duplicate Test(1,false) edge and a single occurence. In the first
8991 * case the edge is directly added to the diff set to avoid undetected ambiguities during the recursive
@@ -94,13 +96,18 @@ let compareCfgs (module CfgOld : CfgForward) (module CfgNew : CfgForward) fun1 f
9496 let posAmbigEdge edgeList = let findTestFalseEdge (ll ,_ ) = testFalseEdge (snd (List. hd ll)) in
9597 let numDuplicates l = List. length (List. find_all findTestFalseEdge l) in
9698 testFalseEdge (List. hd edgeList) && (numDuplicates outList1 > 1 || numDuplicates outList2 > 1 ) in
97- if posAmbigEdge edgeList1 then NH. replace diff toNode1 ()
98- else findMatch (edgeList1, toNode1) in
99- List. iter iterOuts outList1; compareNext () in
99+ if posAmbigEdge edgeList1 then (NH. replace diff toNode1 () ; rename_mapping)
100+ else findMatch (edgeList1, toNode1) rename_mapping in
101+ let updatedRenameMapping = List. fold_left (fun rm e -> iterOuts e rm) rename_mapping outList1 in
102+ compareNext () updatedRenameMapping
103+ in
100104
101105 let entryNode1, entryNode2 = (FunctionEntry fun1, FunctionEntry fun2) in
102- NH. replace same.node1to2 entryNode1 entryNode2; NH. replace same.node2to1 entryNode2 entryNode1;
103- Queue. push (entryNode1,entryNode2) waitingList; compareNext () ; (same, diff)
106+ NH. replace same.node1to2 entryNode1 entryNode2;
107+ NH. replace same.node2to1 entryNode2 entryNode1;
108+ Queue. push (entryNode1,entryNode2) waitingList;
109+ let updatedRenameMapping = compareNext () rename_mapping in
110+ same, diff, updatedRenameMapping
104111
105112(* This is the second phase of the CFG comparison of functions. It removes the nodes from the matching node set 'same'
106113 * that have an incoming backedge in the new CFG that can be reached from a differing new node. This is important to
@@ -123,7 +130,8 @@ let reexamine f1 f2 (same : biDirectionNodeMap) (diffNodes1 : unit NH.t) (module
123130 repeat () ;
124131 NH. to_seq same.node1to2, NH. to_seq_keys diffNodes1
125132
126- let compareFun (module CfgOld : CfgForward ) (module CfgNew : CfgBidir ) fun1 fun2 =
127- let same, diff = Stats. time " compare-phase1" (fun () -> compareCfgs (module CfgOld ) (module CfgNew ) fun1 fun2) () in
133+
134+ let compareFun (module CfgOld : CfgForward ) (module CfgNew : CfgBidir ) fun1 fun2 rename_mapping : (node * node) list * node list * rename_mapping =
135+ let same, diff, rename_mapping = Stats. time " compare-phase1" (fun () -> compareCfgs (module CfgOld ) (module CfgNew ) fun1 fun2 rename_mapping) () in
128136 let unchanged, diffNodes1 = Stats. time " compare-phase2" (fun () -> reexamine fun1 fun2 same diff (module CfgOld ) (module CfgNew )) () in
129- List. of_seq unchanged, List. of_seq diffNodes1
137+ List. of_seq unchanged, List. of_seq diffNodes1, rename_mapping
0 commit comments