/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 7 Ġ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 . backend . common Ċ Ċ import Ġorg . jetbrains . kotlin . ir . Ir Element Ċ import Ġorg . jetbrains . kotlin . ir . declarations . Ir Class Ċ import Ġorg . jetbrains . kotlin . ir . declarations . Ir Function Ċ import Ġorg . jetbrains . kotlin . ir . expressions .* Ċ import Ġorg . jetbrains . kotlin . ir . util . uses Default Arguments Ċ import Ġorg . jetbrains . kotlin . ir . visitor s . Ir Element Visitor Ċ import Ġorg . jetbrains . kotlin . resolve . Descriptor Utils Ċ import Ġorg . jetbrains . kotlin . types . type Util . is Unit Ċ Ċ /** Ċ Ġ* ĠCollect s Ġcalls Ġto Ġbe Ġtreated Ġas Ġtail Ġrecursion . Ċ Ġ* ĠThe Ġchecks Ġare Ġpartially Ġbased Ġon Ġthe Ġfrontend Ġimplementation Ċ Ġ* Ġin Ġ` Control Flow Information Provider . mark And Check Recursive Tail Calls ()`. Ċ Ġ* Ċ Ġ* ĠThis Ġanalysis Ġis Ġnot Ġvery Ġprecise Ġand Ġcan Ġmiss Ġsome Ġcalls . Ċ Ġ* ĠIt Ġis Ġalso Ġnot Ġguaranteed Ġthat Ġeach Ġreturned Ġcall Ġis Ġdetected Ġas Ġtail Ġrecursion Ġby Ġthe Ġfrontend . Ċ Ġ* ĠHowever Ġany Ġreturned Ġcall Ġcan Ġbe Ġcorrectly Ġoptimized Ġas Ġtail Ġrecursion . Ċ Ġ*/ Ċ fun Ġcollect Tail Recursion Calls ( ir Function : ĠIr Function ): ĠSet < Ir Call > Ġ{ ĊĠĠĠ Ġif Ġ(! ir Function . descriptor . is Tail rec ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġempty Set () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġresult Ġ= Ġmutable Set Of < Ir Call >() ĊĊĠĠĠ Ġval Ġvisitor Ġ= Ġobject Ġ: ĠIr Element Visitor < Unit , ĠElement Kind > Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Element ( element : ĠIr Element , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġchild Kind Ġ= ĠElement Kind . NOT _ S URE Ġ// ĠNot Ġsure Ġby Ġdefault . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelement . accept Children ( this , Ġchild Kind ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Function ( declaration : ĠIr Function , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIgnore Ġlocal Ġfunctions . ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Class ( declaration : ĠIr Class , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIgnore Ġlocal Ġclasses . ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Try ( a Try : ĠIr Try , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġdo Ġnot Ġsupport Ġtail Ġcalls Ġin Ġtry - catch - finally , Ġfor Ġsimplicity Ġof Ġthe Ġment al Ġmodel ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġvery Ġfew Ġcases Ġthere Ġwould Ġbe Ġreal Ġtail - calls , Ġand Ġit 's Ġoften Ġnot Ġso Ġeasy Ġfor Ġthe Ġuser Ġto Ġsee Ġwhy ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Return ( expression : ĠIr Return , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Kind Ġ= Ġif Ġ( expression . return Target Ġ== Ġir Function . descriptor ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠElement Kind . TAIL _ STATE MENT ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠElement Kind . NOT _ S URE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . value . accept ( this , Ġvalue Kind ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Container Expression ( expression : ĠIr Container Expression , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . statements . forEach Indexed Ġ{ Ġindex , Ġir Statement Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstatement Kind Ġ= Ġif Ġ( index Ġ== Ġexpression . statements . last Index ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġlast Ġstatement Ġdefines Ġthe Ġresult Ġof Ġthe Ġcontainer Ġexpression , Ġso Ġit Ġhas Ġthe Ġsame Ġkind . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdata ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠElement Kind . NOT _ S URE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Statement . accept ( this , Ġstatement Kind ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit When ( expression : ĠIr When , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . branches . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . condition . accept ( this , ĠElement Kind . NOT _ S URE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . result . accept ( this , Ġdata ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit Call ( expression : ĠIr Call , Ġdata : ĠElement Kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . accept Children ( this , ĠElement Kind . NOT _ S URE ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIs Ġit Ġa Ġtail Ġcall ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Ġ!= ĠElement Kind . TAIL _ STATE MENT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIs Ġit Ġa Ġrecursive Ġcall ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( expression . descriptor . original Ġ!= Ġir Function . descriptor ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : Ġcheck Ġtype Ġarguments ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Descriptor Utils . is Override ( ir Function . descriptor ) Ġ&& Ġexpression . uses Default Arguments ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOver ridden Ġfunctions Ġusing Ġdefault Ġarguments Ġat Ġtail Ġcall Ġare Ġnot Ġincluded : ĠK T - 4 2 8 5 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . dispatch Receiver ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it Ġ! is ĠIr GetValue Ġ|| Ġit . descriptor Ġ!= Ġir Function . descriptor . dispatch Receiver Parameter ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠA Ġtail Ġcall Ġis Ġnot Ġallowed Ġto Ġchange Ġdispatch Ġreceiver ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠ Ġclass ĠC Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠ Ġfun Ġfoo ( other : ĠC ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠĠĠĠ Ġother . foo ( this ) Ġ// Ġnot Ġa Ġtail Ġcall ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( expression ) ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġbody Ġ= Ġir Function . body ĊĠĠĠ Ġif Ġ( body Ġ! is ĠIr Block Body ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġempty Set () Ġ// ĠTODO : Ġshould Ġan Ġassert Ġbe Ġhere Ġinstead ? ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġbody . statements . forEach Indexed Ġ{ Ġindex , Ġir Statement Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġkind Ġ= Ġif Ġ( index Ġ== Ġbody . statements . last Index Ġ&& Ġir Function . descriptor . returnType ?. is Unit () Ġ== Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠElement Kind . TAIL _ STATE MENT ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠElement Kind . NOT _ S URE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġir Statement . accept ( visitor , Ġkind ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġresult Ċ } Ċ Ċ /** Ċ Ġ* ĠThe Ġkind Ġof ĠIR Ġelement Ġused Ġto Ġdetect Ġtail Ġcalls . Ċ Ġ*/ Ċ private Ġenum Ġclass ĠElement Kind Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThis Ġelement Ġis Ġthe Ġlast Ġstatement Ġto Ġbe Ġexecuted Ġbefore Ġthe Ġreturn Ġfrom Ġthe Ġfunction . ĊĠĠĠĠ Ġ* ĠIf Ġthe Ġreturn Ġtype Ġis Ġnot Ġ` Unit `, Ġthe Ġresult Ġof Ġthis Ġstatement Ġdefines Ġthe Ġresult Ġof Ġthe Ġentire Ġfunction . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ ĠT AIL _ STATE MENT , ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠNot Ġsure Ġif Ġthe Ġelement Ġme ets Ġthe Ġrequirements Ġto Ġbe Ġ[ TAIL _ STATE MENT ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ ĠNOT _ S URE Ċ } Ċ