Up to index of Isabelle/HOL/Jinja/Slicing
theory DynPDGheader {* \isachapter{Dynamic Slicing}
\isaheader{Dynamic Program Dependence Graph} *}
theory DynPDG imports
"../Basic/DynDataDependence"
"../Basic/CFGExit_wf"
"../Basic/DynStandardControlDependence"
"../Basic/DynWeakControlDependence"
begin
subsection {* The dynamic PDG *}
locale DynPDG =
CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
for sourcenode :: "'edge => 'node" and targetnode :: "'edge => 'node"
and kind :: "'edge => 'state edge_kind" and valid_edge :: "'edge => bool"
and Entry :: "'node" ("'('_Entry'_')") and Def :: "'node => 'var set"
and Use :: "'node => 'var set" and state_val :: "'state => 'var => 'val"
and Exit :: "'node" ("'('_Exit'_')") +
fixes dyn_control_dependence :: "'node => 'node => 'edge list => bool"
("_ controls _ via _" [51,0,0])
assumes Exit_not_dyn_control_dependent:"n controls n' via as ==> n' ≠ (_Exit_)"
assumes dyn_control_dependence_path:
"n controls n' via as ==> n -as->* n' ∧ as ≠ []"
begin
inductive cdep_edge :: "'node => 'edge list => 'node => bool"
("_ -_->⇘cd⇙ _" [51,0,0] 80)
and ddep_edge :: "'node => 'var => 'edge list => 'node => bool"
("_ -'{_'}_->⇘dd⇙ _" [51,0,0,0] 80)
and DynPDG_edge :: "'node => 'var option => 'edge list => 'node => bool"
where
-- "Syntax"
"n -as->⇘cd⇙ n' == DynPDG_edge n None as n'"
| "n -{V}as->⇘dd⇙ n' == DynPDG_edge n (Some V) as n'"
-- "Rules"
| DynPDG_cdep_edge:
"n controls n' via as ==> n -as->⇘cd⇙ n'"
| DynPDG_ddep_edge:
"n influences V in n' via as ==> n -{V}as->⇘dd⇙ n'"
inductive DynPDG_path :: "'node => 'edge list => 'node => bool"
("_ -_->⇣d* _" [51,0,0] 80)
where DynPDG_path_Nil:
"valid_node n ==> n -[]->⇣d* n"
| DynPDG_path_Append_cdep:
"[|n -as->⇣d* n''; n'' -as'->⇘cd⇙ n'|] ==> n -as@as'->⇣d* n'"
| DynPDG_path_Append_ddep:
"[|n -as->⇣d* n''; n'' -{V}as'->⇘dd⇙ n'|] ==> n -as@as'->⇣d* n'"
lemma DynPDG_empty_path_eq_nodes:"n -[]->⇣d* n' ==> n = n'"
apply - apply(erule DynPDG_path.cases)
apply simp
apply(auto elim:DynPDG_edge.cases dest:dyn_control_dependence_path)
by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
lemma DynPDG_path_cdep:"n -as->⇘cd⇙ n' ==> n -as->⇣d* n'"
apply(subgoal_tac "n -[]@as->⇣d* n'")
apply simp
apply(rule DynPDG_path_Append_cdep, rule DynPDG_path_Nil)
by(auto elim!:DynPDG_edge.cases dest:dyn_control_dependence_path path_valid_node)
lemma DynPDG_path_ddep:"n -{V}as->⇘dd⇙ n' ==> n -as->⇣d* n'"
apply(subgoal_tac "n -[]@as->⇣d* n'")
apply simp
apply(rule DynPDG_path_Append_ddep, rule DynPDG_path_Nil)
by(auto elim!:DynPDG_edge.cases dest:path_valid_node simp:dyn_data_dependence_def)
lemma DynPDG_path_Append:
"[|n'' -as'->⇣d* n'; n -as->⇣d* n''|] ==> n -as@as'->⇣d* n'"
apply(induct rule:DynPDG_path.induct)
apply(auto intro:DynPDG_path.intros)
apply(rotate_tac 1,drule DynPDG_path_Append_cdep,simp+)
apply(rotate_tac 1,drule DynPDG_path_Append_ddep,simp+)
done
lemma DynPDG_path_Exit:"[|n -as->⇣d* n'; n' = (_Exit_)|] ==> n = (_Exit_)"
apply(induct rule:DynPDG_path.induct)
by(auto elim:DynPDG_edge.cases dest:Exit_not_dyn_control_dependent
simp:dyn_data_dependence_def)
lemma DynPDG_path_not_inner:
"[|n -as->⇣d* n'; ¬ inner_node n'|] ==> n = n'"
proof(induct rule:DynPDG_path.induct)
case (DynPDG_path_Nil n)
thus ?case by simp
next
case (DynPDG_path_Append_cdep n as n'' as' n')
from `n'' -as'->⇘cd⇙ n'` `¬ inner_node n'` have False
apply -
apply(erule DynPDG_edge.cases) apply(auto simp:inner_node_def)
apply(fastforce dest:dyn_control_dependence_path path_valid_node)
apply(fastforce dest:dyn_control_dependence_path path_valid_node)
by(fastforce dest:Exit_not_dyn_control_dependent)
thus ?case by simp
next
case (DynPDG_path_Append_ddep n as n'' V as' n')
from `n'' -{V}as'->⇘dd⇙ n'` `¬ inner_node n'` have False
apply -
apply(erule DynPDG_edge.cases)
by(auto dest:path_valid_node simp:inner_node_def dyn_data_dependence_def)
thus ?case by simp
qed
lemma DynPDG_cdep_edge_CFG_path:
assumes "n -as->⇘cd⇙ n'" shows "n -as->* n'" and "as ≠ []"
using `n -as->⇘cd⇙ n'`
by(auto elim:DynPDG_edge.cases dest:dyn_control_dependence_path)
lemma DynPDG_ddep_edge_CFG_path:
assumes "n -{V}as->⇘dd⇙ n'" shows "n -as->* n'" and "as ≠ []"
using `n -{V}as->⇘dd⇙ n'`
by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
lemma DynPDG_path_CFG_path:
"n -as->⇣d* n' ==> n -as->* n'"
proof(induct rule:DynPDG_path.induct)
case DynPDG_path_Nil thus ?case by(rule empty_path)
next
case (DynPDG_path_Append_cdep n as n'' as' n')
from `n'' -as'->⇘cd⇙ n'` have "n'' -as'->* n'"
by(rule DynPDG_cdep_edge_CFG_path(1))
with `n -as->* n''` show ?case by(rule path_Append)
next
case (DynPDG_path_Append_ddep n as n'' V as' n')
from `n'' -{V}as'->⇘dd⇙ n'` have "n'' -as'->* n'"
by(rule DynPDG_ddep_edge_CFG_path(1))
with `n -as->* n''` show ?case by(rule path_Append)
qed
lemma DynPDG_path_split:
"n -as->⇣d* n' ==>
(as = [] ∧ n = n') ∨
(∃n'' asx asx'. (n -asx->⇘cd⇙ n'') ∧ (n'' -asx'->⇣d* n') ∧
(as = asx@asx')) ∨
(∃n'' V asx asx'. (n -{V}asx->⇘dd⇙ n'') ∧ (n'' -asx'->⇣d* n') ∧
(as = asx@asx'))"
proof(induct rule:DynPDG_path.induct)
case (DynPDG_path_Nil n) thus ?case by auto
next
case (DynPDG_path_Append_cdep n as n'' as' n')
note IH = `as = [] ∧ n = n'' ∨
(∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx') ∨
(∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx')`
from IH show ?case
proof
assume "as = [] ∧ n = n''"
with `n'' -as'->⇘cd⇙ n'` have "valid_node n'"
by(fastforce intro:path_valid_node(2) DynPDG_path_CFG_path
DynPDG_path_cdep)
with `as = [] ∧ n = n''` `n'' -as'->⇘cd⇙ n'`
have "∃n'' asx asx'. n -asx->⇘cd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by(auto intro:DynPDG_path_Nil)
thus ?thesis by simp
next
assume "(∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx') ∨
(∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx')"
thus ?thesis
proof
assume "∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx'"
then obtain nx asx asx' where "n -asx->⇘cd⇙ nx" and "nx -asx'->⇣d* n''"
and "as = asx@asx'" by auto
from `n'' -as'->⇘cd⇙ n'` have "n'' -as'->⇣d* n'" by(rule DynPDG_path_cdep)
with `nx -asx'->⇣d* n''` have "nx -asx'@as'->⇣d* n'"
by(fastforce intro:DynPDG_path_Append)
with `n -asx->⇘cd⇙ nx` `as = asx@asx'`
have "∃n'' asx asx'. n -asx->⇘cd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by auto
thus ?thesis by simp
next
assume "∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx'"
then obtain nx V asx asx' where "n -{V}asx->⇘dd⇙ nx" and "nx -asx'->⇣d* n''"
and "as = asx@asx'" by auto
from `n'' -as'->⇘cd⇙ n'` have "n'' -as'->⇣d* n'" by(rule DynPDG_path_cdep)
with `nx -asx'->⇣d* n''` have "nx -asx'@as'->⇣d* n'"
by(fastforce intro:DynPDG_path_Append)
with `n -{V}asx->⇘dd⇙ nx` `as = asx@asx'`
have "∃n'' V asx asx'. n -{V}asx->⇘dd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by auto
thus ?thesis by simp
qed
qed
next
case (DynPDG_path_Append_ddep n as n'' V as' n')
note IH = `as = [] ∧ n = n'' ∨
(∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx') ∨
(∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx')`
from IH show ?case
proof
assume "as = [] ∧ n = n''"
with `n'' -{V}as'->⇘dd⇙ n'` have "valid_node n'"
by(fastforce intro:path_valid_node(2) DynPDG_path_CFG_path
DynPDG_path_ddep)
with `as = [] ∧ n = n''` `n'' -{V}as'->⇘dd⇙ n'`
have "∃n'' V asx asx'. n -{V}asx->⇘dd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by(fastforce intro:DynPDG_path_Nil)
thus ?thesis by simp
next
assume "(∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx') ∨
(∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx')"
thus ?thesis
proof
assume "∃nx asx asx'. n -asx->⇘cd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx'"
then obtain nx asx asx' where "n -asx->⇘cd⇙ nx" and "nx -asx'->⇣d* n''"
and "as = asx@asx'" by auto
from `n'' -{V}as'->⇘dd⇙ n'` have "n'' -as'->⇣d* n'" by(rule DynPDG_path_ddep)
with `nx -asx'->⇣d* n''` have "nx -asx'@as'->⇣d* n'"
by(fastforce intro:DynPDG_path_Append)
with `n -asx->⇘cd⇙ nx` `as = asx@asx'`
have "∃n'' asx asx'. n -asx->⇘cd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by auto
thus ?thesis by simp
next
assume "∃nx V asx asx'. n -{V}asx->⇘dd⇙ nx ∧ nx -asx'->⇣d* n'' ∧ as = asx@asx'"
then obtain nx V' asx asx' where "n -{V'}asx->⇘dd⇙ nx" and "nx -asx'->⇣d* n''"
and "as = asx@asx'" by auto
from `n'' -{V}as'->⇘dd⇙ n'` have "n'' -as'->⇣d* n'" by(rule DynPDG_path_ddep)
with `nx -asx'->⇣d* n''` have "nx -asx'@as'->⇣d* n'"
by(fastforce intro:DynPDG_path_Append)
with `n -{V'}asx->⇘dd⇙ nx` `as = asx@asx'`
have "∃n'' V asx asx'. n -{V}asx->⇘dd⇙ n'' ∧ n'' -asx'->⇣d* n' ∧ as@as' = asx@asx'"
by auto
thus ?thesis by simp
qed
qed
qed
lemma DynPDG_path_rev_cases [consumes 1,
case_names DynPDG_path_Nil DynPDG_path_cdep_Append DynPDG_path_ddep_Append]:
"[|n -as->⇣d* n'; [|as = []; n = n'|] ==> Q;
!!n'' asx asx'. [|n -asx->⇘cd⇙ n''; n'' -asx'->⇣d* n';
as = asx@asx'|] ==> Q;
!!V n'' asx asx'. [|n -{V}asx->⇘dd⇙ n''; n'' -asx'->⇣d* n';
as = asx@asx'|] ==> Q|]
==> Q"
by(blast dest:DynPDG_path_split)
lemma DynPDG_ddep_edge_no_shorter_ddep_edge:
assumes ddep:"n -{V}as->⇘dd⇙ n'"
shows "∀as' a as''. tl as = as'@a#as'' --> ¬ sourcenode a -{V}a#as''->⇘dd⇙ n'"
proof -
from ddep have influence:"n influences V in n' via as"
by(auto elim!:DynPDG_edge.cases)
then obtain a asx where as:"as = a#asx"
and notin:"n ∉ set (sourcenodes asx)"
by(auto dest:dyn_influence_source_notin_tl_edges simp:dyn_data_dependence_def)
from influence as
have imp:"∀nx ∈ set (sourcenodes asx). V ∉ Def nx"
by(auto simp:dyn_data_dependence_def)
{ fix as' a' as''
assume eq:"tl as = as'@a'#as''"
and ddep':"sourcenode a' -{V}a'#as''->⇘dd⇙ n'"
from eq as notin have noteq:"sourcenode a' ≠ n" by(auto simp:sourcenodes_def)
from ddep' have "V ∈ Def (sourcenode a')"
by(auto elim!:DynPDG_edge.cases simp:dyn_data_dependence_def)
with eq as noteq imp have False by(auto simp:sourcenodes_def) }
thus ?thesis by blast
qed
lemma no_ddep_same_state:
assumes path:"n -as->* n'" and Uses:"V ∈ Use n'" and preds:"preds (kinds as) s"
and no_dep:"∀as' a as''. as = as'@a#as'' --> ¬ sourcenode a -{V}a#as''->⇘dd⇙ n'"
shows "state_val (transfers (kinds as) s) V = state_val s V"
proof -
{ fix n''
assume inset:"n'' ∈ set (sourcenodes as)" and Defs:"V ∈ Def n''"
hence "∃nx ∈ set (sourcenodes as). V ∈ Def nx" by auto
then obtain nx ns' ns'' where nodes:"sourcenodes as = ns'@nx#ns''"
and Defs':"V ∈ Def nx" and notDef:"∀nx' ∈ set ns''. V ∉ Def nx'"
by(fastforce elim!:rightmost_element_property)
from nodes obtain as' a as''
where as'':"sourcenodes as'' = ns''" and as:"as=as'@a#as''"
and source:"sourcenode a = nx"
by(fastforce elim:map_append_append_maps simp:sourcenodes_def)
from as path have path':"sourcenode a -a#as''->* n'"
by(fastforce dest:path_split_second)
from notDef as'' source
have "∀n'' ∈ set (sourcenodes as''). V ∉ Def n''"
by(auto simp:sourcenodes_def)
with path' Defs' Uses source
have influence:"nx influences V in n' via (a#as'')"
by(simp add:dyn_data_dependence_def)
hence "nx ∉ set (sourcenodes as'')" by(rule dyn_influence_source_notin_tl_edges)
with influence source
have "∃asx a'. sourcenode a' -{V}a'#asx->⇘dd⇙ n' ∧ sourcenode a' = nx ∧
(∃asx'. a#as'' = asx'@a'#asx)"
by(fastforce intro:DynPDG_ddep_edge)
with nodes no_dep as have False by(auto simp:sourcenodes_def) }
hence "∀n ∈ set (sourcenodes as). V ∉ Def n" by auto
with wf path preds show ?thesis by(fastforce intro:CFG_path_no_Def_equal)
qed
lemma DynPDG_ddep_edge_only_first_edge:
"[|n -{V}a#as->⇘dd⇙ n'; preds (kinds (a#as)) s|] ==>
state_val (transfers (kinds (a#as)) s) V = state_val (transfer (kind a) s) V"
apply -
apply(erule DynPDG_edge.cases)
apply auto
apply(frule dyn_influence_Cons_source)
apply(frule dyn_influence_source_notin_tl_edges)
by(erule dyn_influence_only_first_edge)
lemma Use_value_change_implies_DynPDG_ddep_edge:
assumes "n -as->* n'" and "V ∈ Use n'" and "preds (kinds as) s"
and "preds (kinds as) s'" and "state_val s V = state_val s' V"
and "state_val (transfers (kinds as) s) V ≠
state_val (transfers (kinds as) s') V"
obtains as' a as'' where "as = as'@a#as''"
and "sourcenode a -{V}a#as''->⇘dd⇙ n'"
and "state_val (transfers (kinds as) s) V =
state_val (transfers (kinds (as'@[a])) s) V"
and "state_val (transfers (kinds as) s') V =
state_val (transfers (kinds (as'@[a])) s') V"
proof(atomize_elim)
show "∃as' a as''. as = as'@a#as'' ∧
sourcenode a -{V}a#as''->⇘dd⇙ n' ∧
state_val (transfers (kinds as) s) V =
state_val (transfers (kinds (as'@[a])) s) V ∧
state_val (transfers (kinds as) s') V =
state_val (transfers (kinds (as'@[a])) s') V"
proof(cases "∀as' a as''. as = as'@a#as'' -->
¬ sourcenode a -{V}a#as''->⇘dd⇙ n'")
case True
with `n -as->* n'` `V ∈ Use n'` `preds (kinds as) s` `preds (kinds as) s'`
have "state_val (transfers (kinds as) s) V = state_val s V"
and "state_val (transfers (kinds as) s') V = state_val s' V"
by(auto intro:no_ddep_same_state)
with `state_val s V = state_val s' V`
`state_val (transfers (kinds as) s) V ≠ state_val (transfers (kinds as) s') V`
show ?thesis by simp
next
case False
then obtain as' a as'' where [simp]:"as = as'@a#as''"
and "sourcenode a -{V}a#as''->⇘dd⇙ n'" by auto
from `preds (kinds as) s` have "preds (kinds (a#as'')) (transfers (kinds as') s)"
by(simp add:kinds_def preds_split)
with `sourcenode a -{V}a#as''->⇘dd⇙ n'` have all:
"state_val (transfers (kinds (a#as'')) (transfers (kinds as') s)) V =
state_val (transfer (kind a) (transfers (kinds as') s)) V"
by(auto dest!:DynPDG_ddep_edge_only_first_edge)
from `preds (kinds as) s'`
have "preds (kinds (a#as'')) (transfers (kinds as') s')"
by(simp add:kinds_def preds_split)
with `sourcenode a -{V}a#as''->⇘dd⇙ n'` have all':
"state_val (transfers (kinds (a#as'')) (transfers (kinds as') s')) V =
state_val (transfer (kind a) (transfers (kinds as') s')) V"
by(auto dest!:DynPDG_ddep_edge_only_first_edge)
hence eq:"!!s. transfers (kinds as) s =
transfers (kinds (a#as'')) (transfers (kinds as') s)"
by(simp add:transfers_split[THEN sym] kinds_def)
with all have "state_val (transfers (kinds as) s) V =
state_val (transfers (kinds (as'@[a])) s) V"
by(simp add:transfers_split kinds_def)
moreover
from eq all' have "state_val (transfers (kinds as) s') V =
state_val (transfers (kinds (as'@[a])) s') V"
by(simp add:transfers_split kinds_def)
ultimately show ?thesis using `sourcenode a -{V}a#as''->⇘dd⇙ n'` by simp blast
qed
qed
end
subsection {* Instantiate dynamic PDG *}
subsubsection {* Standard control dependence *}
locale DynStandardControlDependencePDG =
Postdomination sourcenode targetnode kind valid_edge Entry Exit +
CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
for sourcenode :: "'edge => 'node" and targetnode :: "'edge => 'node"
and kind :: "'edge => 'state edge_kind" and valid_edge :: "'edge => bool"
and Entry :: "'node" ("'('_Entry'_')") and Def :: "'node => 'var set"
and Use :: "'node => 'var set" and state_val :: "'state => 'var => 'val"
and Exit :: "'node" ("'('_Exit'_')")
begin
lemma DynPDG_scd:
"DynPDG sourcenode targetnode kind valid_edge (_Entry_)
Def Use state_val (_Exit_) dyn_standard_control_dependence"
proof(unfold_locales)
fix n n' as assume "n controls⇣s n' via as"
show "n' ≠ (_Exit_)"
proof
assume "n' = (_Exit_)"
with `n controls⇣s n' via as` show False
by(fastforce intro:Exit_not_dyn_standard_control_dependent)
qed
next
fix n n' as assume "n controls⇣s n' via as"
thus "n -as->* n' ∧ as ≠ []"
by(fastforce simp:dyn_standard_control_dependence_def)
qed
end
subsubsection {* Weak control dependence *}
locale DynWeakControlDependencePDG =
StrongPostdomination sourcenode targetnode kind valid_edge Entry Exit +
CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
for sourcenode :: "'edge => 'node" and targetnode :: "'edge => 'node"
and kind :: "'edge => 'state edge_kind" and valid_edge :: "'edge => bool"
and Entry :: "'node" ("'('_Entry'_')") and Def :: "'node => 'var set"
and Use :: "'node => 'var set" and state_val :: "'state => 'var => 'val"
and Exit :: "'node" ("'('_Exit'_')")
begin
lemma DynPDG_wcd:
"DynPDG sourcenode targetnode kind valid_edge (_Entry_)
Def Use state_val (_Exit_) dyn_weak_control_dependence"
proof(unfold_locales)
fix n n' as assume "n weakly controls n' via as"
show "n' ≠ (_Exit_)"
proof
assume "n' = (_Exit_)"
with `n weakly controls n' via as` show False
by(fastforce intro:Exit_not_dyn_weak_control_dependent)
qed
next
fix n n' as assume "n weakly controls n' via as"
thus "n -as->* n' ∧ as ≠ []"
by(fastforce simp:dyn_weak_control_dependence_def)
qed
end
subsection {* Data slice *}
definition (in CFG) empty_control_dependence :: "'node => 'node => 'edge list => bool"
where "empty_control_dependence n n' as ≡ False"
lemma (in CFGExit_wf) DynPDG_scd:
"DynPDG sourcenode targetnode kind valid_edge (_Entry_)
Def Use state_val (_Exit_) empty_control_dependence"
proof(unfold_locales)
fix n n' as assume "empty_control_dependence n n' as"
thus "n' ≠ (_Exit_)" by(simp add:empty_control_dependence_def)
next
fix n n' as assume "empty_control_dependence n n' as"
thus "n -as->* n' ∧ as ≠ []" by(simp add:empty_control_dependence_def)
qed
end