/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 5 ĠJetBrains Ġs . r . o . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . cfg . pseudo code Tra verser Ċ Ċ import Ġorg . jetbrains . kotlin . cfg . Control Flow Info Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . Pseudo code Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . instructions . Instruction Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . instructions . special . In lined Local Function Declaration Instruction Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . instructions . special . Local Function Declaration Instruction Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . instructions . special . Sub routine Enter Instruction Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code . instructions . special . Sub routine Sink Instruction Ċ import Ġorg . jetbrains . kotlin . cfg . pseudo code Tra verser . Traversal Order . FORWARD Ċ import Ġjava . util .* Ċ Ċ fun ĠP seudo code . traverse ( ĊĠĠĠ Ġtraversal Order : ĠTra versal Order , ĊĠĠĠ Ġanalyze Instruction : Ġ( Instruction ) Ġ-> ĠUnit Ċ ) Ġ{ ĊĠĠĠ Ġval Ġinstructions Ġ= Ġget Instructions ( traversal Order ) ĊĠĠĠ Ġfor Ġ( instruction Ġin Ġinstructions ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( instruction Ġis ĠLocal Function Declaration Instruction ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstruction . body . traverse ( traversal Order , Ġanalyze Instruction ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġanalyze Instruction ( instruction ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġ< D > ĠP seudo code . traverse ( ĊĠĠĠ Ġtraversal Order : ĠTra versal Order , ĊĠĠĠ Ġedges Map : ĠMap < Instruction , ĠEd ges < D >>, ĊĠĠĠ Ġanalyze Instruction : Ġ( Instruction , ĠD , ĠD ) Ġ-> ĠUnit Ċ ) Ġ{ ĊĠĠĠ Ġval Ġinstructions Ġ= Ġget Instructions ( traversal Order ) ĊĠĠĠ Ġfor Ġ( instruction Ġin Ġinstructions ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( instruction Ġis ĠLocal Function Declaration Instruction ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstruction . body . traverse ( traversal Order , Ġedges Map , Ġanalyze Instruction ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġedges Ġ= Ġedges Map [ instruction ] Ġ?: Ġcontinue ĊĠĠĠĠĠĠĠ Ġanalyze Instruction ( instruction , Ġedges . incoming , Ġedges . outgoing ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun ĠP seudo code . traverse In cluding Dead Code ( analyze Instruction : Ġ( Instruction ) Ġ-> ĠUnit ) Ġ{ ĊĠĠĠ Ġfor Ġ( instruction Ġin Ġinstructions In cluding Dead Code ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( instruction Ġis ĠLocal Function Declaration Instruction ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstruction . body . traverse In cluding Dead Code ( analyze Instruction ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġanalyze Instruction ( instruction ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġ< I Ġ: ĠControl Flow Info < *, Ġ*, Ġ* >> ĠP seudo code . collect Data ( ĊĠĠĠ Ġtraversal Order : ĠTra versal Order , ĊĠĠĠ Ġmerge Edges : Ġ( Instruction , ĠCollection < I >) Ġ-> ĠEd ges < I >, ĊĠĠĠ Ġupdate Edge : Ġ( Instruction , ĠInstruction , ĠI ) Ġ-> ĠI , ĊĠĠĠ Ġinitial Info : ĠI Ċ ): ĠMap < Instruction , ĠEd ges < I >> Ġ{ ĊĠĠĠ Ġval Ġedges Map Ġ= ĠLinkedHashMap < Instruction , ĠEd ges < I >>() ĊĠĠĠ Ġval Ġstart Instruction Ġ= Ġget Start Instruction ( traversal Order ) ĊĠĠĠ Ġedges Map [ start Instruction ] Ġ= ĠEd ges ( initial Info , Ġinitial Info ) ĊĊĠĠĠ Ġval Ġchanged Ġ= Ġmutable Map Of < Instruction , ĠBoolean >() ĊĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠ Ġcollect Data From Sub graph ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtraversal Order , Ġedges Map , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmerge Edges , Ġupdate Edge , ĠCollections . emptyList < Instruction >(), Ġchanged , Ġfalse ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ġwhile Ġ( changed . any Ġ{ Ġit . value Ġ}) ĊĊĠĠĠ Ġreturn Ġedges Map Ċ } Ċ Ċ private Ġfun Ġ< I Ġ: ĠControl Flow Info < *, Ġ*, Ġ* >> ĠP seudo code . collect Data From Sub graph ( ĊĠĠĠ Ġtraversal Order : ĠTra versal Order , ĊĠĠĠ Ġedges Map : ĠMutable Map < Instruction , ĠEd ges < I >>, ĊĠĠĠ Ġmerge Edges : Ġ( Instruction , ĠCollection < I >) Ġ-> ĠEd ges < I >, ĊĠĠĠ Ġupdate Edge : Ġ( Instruction , ĠInstruction , ĠI ) Ġ-> ĠI , ĊĠĠĠ Ġprevious Sub Graph Instructions : ĠCollection < Instruction >, ĊĠĠĠ Ġchanged : ĠMutable Map < Instruction , ĠBoolean >, ĊĠĠĠ Ġis Local : ĠBoolean Ċ ) Ġ{ ĊĠĠĠ Ġval Ġinstructions Ġ= Ġget Instructions ( traversal Order ) ĊĠĠĠ Ġval Ġstart Instruction Ġ= Ġget Start Instruction ( traversal Order ) ĊĊĠĠĠ Ġfor Ġ( instruction Ġin Ġinstructions ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġis Start Ġ= Ġinstruction . is Start Instruction ( traversal Order ) ĊĠĠĠĠĠĠĠ Ġif Ġ(! is Local Ġ&& Ġis Start ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĊĠĠĠĠĠĠĠ Ġval Ġprevious Instructions Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget Previous In cluding Sub Graph Instructions ( instruction , Ġtraversal Order , Ġstart Instruction , Ġprevious Sub Graph Instructions ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( instruction Ġis ĠLocal Function Declaration Instruction ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsubroutine Pseudo code Ġ= Ġinstruction . body ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubroutine Pseudo code . collect Data From Sub graph ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtraversal Order , Ġedges Map , Ġmerge Edges , Ġupdate Edge , Ġprevious Instructions , Ġchanged , Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSpecial Ġcase Ġfor Ġin lined Ġfunctions : Ġtake Ġflow Ġfrom ĠEXIT Ġinstructions Ġ( it Ġcontains Ġflow Ġwhich Ġexits Ġdeclaration Ġnormally ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Instruction Ġ= Ġif Ġ( instruction Ġis ĠIn lined Local Function Declaration Instruction Ġ&& Ġtraversal Order Ġ== ĠFOR WARD ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubroutine Pseudo code . exit Instruction ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubroutine Pseudo code . getLast Instruction ( traversal Order ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprevious Value Ġ= Ġedges Map [ instruction ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠnewValue Ġ= Ġedges Map [ last Instruction ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated Value Ġ= ĠnewValue ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEd ges ( update Edge ( last Instruction , Ġinstruction , Ġit . incoming ), Ġupdate Edge ( last Instruction , Ġinstruction , Ġit . outgoing )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Edge Data For Instruction ( instruction , Ġprevious Value , Ġupdated Value , Ġedges Map , Ġchanged ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġval Ġprevious Data Value Ġ= Ġedges Map [ instruction ] ĊĠĠĠĠĠĠĠ Ġif Ġ( previous Data Value Ġ!= Ġnull Ġ&& Ġprevious Instructions . all Ġ{ Ġchanged [ it ] Ġ== Ġfalse Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchanged [ instruction ] Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġincoming Edges Data Ġ= ĠHashSet < I >() ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( previous Instruction Ġin Ġprevious Instructions ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprevious Data Ġ= Ġedges Map [ previous Instruction ] Ġ?: Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġincoming Edges Data . add ( update Edge ( previous Instruction , Ġinstruction , Ġprevious Data . outgoing )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmerged Data Ġ= Ġmerge Edges ( instruction , Ġincoming Edges Data ) ĊĠĠĠĠĠĠĠ Ġupdate Edge Data For Instruction ( instruction , Ġprevious Data Value , Ġmerged Data , Ġedges Map , Ġchanged ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġget Previous In cluding Sub Graph Instructions ( ĊĠĠĠ Ġinstruction : ĠInstruction , ĊĠĠĠ Ġtraversal Order : ĠTra versal Order , ĊĠĠĠ Ġstart Instruction : ĠInstruction , ĊĠĠĠ Ġprevious Sub Graph Instructions : ĠCollection < Instruction > Ċ ): ĠCollection < Instruction > Ġ{ ĊĠĠĠ Ġval Ġprevious Ġ= Ġinstruction . get Previous Instructions ( traversal Order ) ĊĠĠĠ Ġif Ġ( instruction Ġ!= Ġstart Instruction Ġ|| Ġprevious Sub Graph Instructions . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġprevious ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġresult Ġ= ĠArrayList ( previous ) ĊĠĠĠ Ġresult . addAll ( previous Sub Graph Instructions ) ĊĠĠĠ Ġreturn Ġresult Ċ } Ċ Ċ private Ġfun Ġ< I Ġ: ĠControl Flow Info < *, Ġ*, Ġ* >> Ġupdate Edge Data For Instruction ( ĊĠĠĠ Ġinstruction : ĠInstruction , ĊĠĠĠ Ġprevious Value : ĠEd ges < I > ?, ĊĠĠĠ ĠnewValue : ĠEd ges < I > ?, ĊĠĠĠ Ġedges Map : ĠMutable Map < Instruction , ĠEd ges < I >>, ĊĠĠĠ Ġchanged : ĠMutable Map < Instruction , ĠBoolean > Ċ ) Ġ{ ĊĠĠĠ Ġif Ġ( previous Value Ġ!= ĠnewValue Ġ&& ĠnewValue Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġchanged [ instruction ] Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġedges Map [ instruction ] Ġ= ĠnewValue ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġchanged [ instruction ] Ġ= Ġfalse ĊĠĠĠ Ġ} Ċ } Ċ Ċ data Ġclass ĠEd ges < out ĠT >( val Ġincoming : ĠT , Ġval Ġoutgoing : ĠT ) Ċ Ċ enum Ġclass ĠTra verse Instruction Result Ġ{ ĊĠĠĠ ĠCONTINUE , ĊĠĠĠ ĠSKIP , ĊĠĠĠ ĠHAL T Ċ } Ċ Ċ // Ġreturns Ġfalse Ġwhen Ġinterrupted Ġby Ġhandler Ċ fun Ġtraverse Following Instructions ( ĊĠĠĠ Ġroot Instruction : ĠInstruction , ĊĠĠĠ Ġvisited : ĠMutable Set < Instruction > Ġ= ĠHashSet (), ĊĠĠĠ Ġorder : ĠTra versal Order Ġ= ĠFOR WARD , ĊĠĠĠ Ġ// Ġtrue Ġto Ġcontinue Ġtraversal ĊĠĠĠ Ġhandler : Ġ(( Instruction ) Ġ-> ĠTra verse Instruction Result )? Ċ ): ĠBoolean Ġ{ ĊĠĠĠ Ġval Ġstack Ġ= ĠArray Deque < Instruction >() ĊĠĠĠ Ġstack . push ( root Instruction ) ĊĊĠĠĠ Ġwhile Ġ(! stack . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinstruction Ġ= Ġstack . pop () ĊĠĠĠĠĠĠĠ Ġif Ġ(! visited . add ( instruction )) Ġcontinue ĊĠĠĠĠĠĠĠ Ġwhen Ġ( handler ?. let Ġ{ Ġit ( instruction ) Ġ} Ġ?: ĠTra verse Instruction Result . CONTINUE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTra verse Instruction Result . CONTINUE Ġ-> Ġinstruction . getNext Instructions ( order ). forEach Ġ{ Ġstack . push ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTra verse Instruction Result . SKIP Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTra verse Instruction Result . HAL T Ġ-> Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtrue Ċ } Ċ Ċ enum Ġclass ĠTra versal Order Ġ{ ĊĠĠĠ ĠFOR WARD , ĊĠĠĠ ĠBACK WARD Ċ } Ċ Ċ fun ĠP seudo code . getStart Instruction ( traversal Order : ĠTra versal Order ): ĠInstruction Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġenter Instruction Ġelse Ġsink Instruction Ċ Ċ fun ĠP seudo code . getLast Instruction ( traversal Order : ĠTra versal Order ): ĠInstruction Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġsink Instruction Ġelse Ġenter Instruction Ċ Ċ fun ĠP seudo code . get Instructions ( traversal Order : ĠTra versal Order ): ĠList < Instruction > Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġinstructions Ġelse Ġreversed Instructions Ċ Ċ fun ĠInstruction . getNext Instructions ( traversal Order : ĠTra versal Order ): ĠCollection < Instruction > Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġnext Instructions Ġelse Ġprevious Instructions Ċ Ċ fun ĠInstruction . get Previous Instructions ( traversal Order : ĠTra versal Order ): ĠCollection < Instruction > Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġprevious Instructions Ġelse Ġnext Instructions Ċ Ċ fun ĠInstruction . is Start Instruction ( traversal Order : ĠTra versal Order ): ĠBoolean Ġ= ĊĠĠĠ Ġif Ġ( traversal Order Ġ== ĠFOR WARD ) Ġthis Ġis ĠSub routine Enter Instruction Ġelse Ġthis Ġis ĠSub routine Sink Instruction Ċ