/* Ċ Ġ* ĠL 2 _ DI VID E _ INT _ BY _ INT . kt Ċ Ġ* ĠCopyright ĠÂ© Ġ 1 9 9 3 - 2 0 2 0 , ĠThe ĠAv ail ĠFoundation , ĠLLC . Ċ Ġ* ĠAll Ġrights Ġreserved . Ċ Ġ* Ċ Ġ* ĠRedistribution Ġand Ġuse Ġin Ġsource Ġand Ġbinary Ġforms , Ġwith Ġor Ġwithout Ċ Ġ* Ġmodification , Ġare Ġpermitted Ġprovided Ġthat Ġthe Ġfollowing Ġconditions Ġare Ġmet : Ċ Ġ* Ċ Ġ* Ġ* ĠRedistributions Ġof Ġsource Ġcode Ġmust Ġretain Ġthe Ġabove Ġcopyright Ġnotice , Ġthis Ċ Ġ* ĠĠ Ġlist Ġof Ġconditions Ġand Ġthe Ġfollowing Ġdisclaimer . Ċ Ġ* Ċ Ġ* Ġ* ĠRedistributions Ġin Ġbinary Ġform Ġmust Ġreproduce Ġthe Ġabove Ġcopyright Ġnotice , Ċ Ġ* ĠĠ Ġthis Ġlist Ġof Ġconditions Ġand Ġthe Ġfollowing Ġdisclaimer Ġin Ġthe Ġdocumentation Ċ Ġ* ĠĠ Ġand / or Ġother Ġmaterials Ġprovided Ġwith Ġthe Ġdistribution . Ċ Ġ* Ċ Ġ* Ġ* ĠNeither Ġthe Ġname Ġof Ġthe Ġcopyright Ġholder Ġnor Ġthe Ġnames Ġof Ġthe Ġcontributors Ċ Ġ* ĠĠ Ġmay Ġbe Ġused Ġto Ġendorse Ġor Ġpromote Ġproducts Ġderived Ġfrom Ġthis Ġsoftware Ċ Ġ* ĠĠ Ġwithout Ġspecific Ġprior Ġwritten Ġpermission . Ċ Ġ* Ċ Ġ* ĠTHIS ĠSOFTWARE ĠIS ĠPROVIDED ĠBY ĠTHE ĠCOPYRIGHT ĠHOLDERS ĠAND ĠCONTRIBUTORS Ġ" AS ĠIS " Ċ Ġ* ĠAND ĠANY ĠEXPRESS ĠOR ĠIMPLIED ĠWARRANTIES , ĠINCLUDING , ĠBUT ĠNOT ĠLIMITED ĠTO , ĠTHE Ċ Ġ* ĠIMPLIED ĠWARRANTIES ĠOF ĠMERCHANTABILITY ĠAND ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE Ċ Ġ* ĠARE ĠDISCLAIMED . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE ĠCOPYRIGHT ĠHOLDER ĠOR ĠCONTRIBUTORS ĠBE Ċ Ġ* ĠLIABLE ĠFOR ĠANY ĠDIRECT , ĠINDIRECT , ĠINCIDENTAL , ĠSPECIAL , ĠEXEMPLARY , ĠOR Ċ Ġ* ĠCONSEQUENTIAL ĠDAMAGES Ġ( INCLUDING , ĠBUT ĠNOT ĠLIMITED ĠTO , ĠPROCUREMENT ĠOF Ċ Ġ* ĠSUBSTITUTE ĠGOODS ĠOR ĠSERVICES ; ĠLOSS ĠOF ĠUSE , ĠDATA , ĠOR ĠPROFITS ; ĠOR ĠBUSINESS Ċ Ġ* ĠINTERRUPTION ) ĠHOWEVER ĠCAUSED ĠAND ĠON ĠANY ĠTHEORY ĠOF ĠLIABILITY , ĠWHETHER ĠIN Ċ Ġ* ĠCONTRACT , ĠSTRICT ĠLIABILITY , ĠOR ĠTORT Ġ( INCLUDING ĠNEGLIGENCE ĠOR ĠOTHERWISE ) Ċ Ġ* ĠARISING ĠIN ĠANY ĠWAY ĠOUT ĠOF ĠTHE ĠUSE ĠOF ĠTHIS ĠSOFTWARE , ĠEVEN ĠIF ĠADVISED ĠOF ĠTHE Ċ Ġ* ĠPOSSIBILITY ĠOF ĠSUCH ĠDAMAGE . Ċ Ġ*/ Ċ package Ġcom . avail . interpreter . level Two . operation Ċ Ċ import Ġcom . avail . descriptor . numbers . Integer Descriptor . Companion . zero Ċ import Ġcom . avail . interpreter . level Two . L 2 Instruction Ċ import Ġcom . avail . interpreter . level Two . L 2 Named Operand Type Ċ import Ġcom . avail . interpreter . level Two . L 2 Operand Type Ċ import Ġcom . avail . interpreter . level Two . operand . L 2 Pc Operand Ċ import Ġcom . avail . interpreter . level Two . operand . L 2 ReadInt Operand Ċ import Ġcom . avail . interpreter . level Two . operand . L 2 Write Int Operand Ċ import Ġcom . avail . interpreter . level Two . operand . Type Restriction . Companion . restriction For Constant Ċ import Ġcom . avail . interpreter . level Two . operand . Type Restriction . Restriction Flag Encoding . UN BOX ED _ INT Ċ import Ġcom . avail . optimizer . L 2 Value Manifest Ċ import Ġcom . avail . optimizer . jvm . JVM Translator Ċ import Ġorg . object web . asm . Label Ċ import Ġorg . object web . asm . Method Visitor Ċ import Ġorg . object web . asm . Op codes Ċ import Ġorg . object web . asm . Type Ċ Ċ /** Ċ Ġ* ĠIf Ġthe Ġdivisor Ġis Ġzero , Ġthen Ġjump Ġto Ġthe Ġzero Ġdivisor Ġlabel . Ġ ĠOtherwise Ċ Ġ* Ġdivide Ġthe Ġdiv id end Ġint Ġby Ġthe Ġdivisor Ġint . Ġ ĠIf Ġthe Ġquot ient Ġand Ġremainder Ċ Ġ* Ġeach Ġfit Ġin Ġan Ġ[ Int ], Ġthen Ġstore Ġthem Ġand Ġcontinue , Ġotherwise Ġjump Ġto Ċ Ġ* Ġan Ġout - of - range Ġlabel . Ċ Ġ* Ċ Ġ* Ġ@ author ĠMark Ġvan ĠG ul ik Ġ& lt ; mark @ avail lang . org & gt ; Ċ Ġ* Ġ@ author ĠT odd ĠL ĠSmith Ġ& lt ; tod d @ avail lang . org & gt ; Ċ Ġ*/ Ċ object ĠL 2 _ DI VID E _ INT _ BY _ INT Ġ: ĠL 2 Control Flow Operation ( Ċ ĉ L 2 Operand Type . READ _ INT . named (" divid end "), Ċ ĉ L 2 Operand Type . READ _ INT . named (" div isor "), Ċ ĉ L 2 Operand Type . WRITE _ INT . named (" quot ient ", ĠL 2 Named Operand Type . Purpose . SUCCESS ), Ċ ĉ L 2 Operand Type . WRITE _ INT . named (" remainder ", ĠL 2 Named Operand Type . Purpose . SUCCESS ), Ċ ĉ L 2 Operand Type . PC . named (" out Ġof Ġrange ", ĠL 2 Named Operand Type . Purpose . FAILURE ), Ċ ĉ L 2 Operand Type . PC . named (" zero Ġdivisor ", ĠL 2 Named Operand Type . Purpose . OFF _ R AMP ), Ċ ĉ L 2 Operand Type . PC . named (" success ", ĠL 2 Named Operand Type . Purpose . SUCCESS )) Ċ { Ċ ĉ // ĠIt Ġjumps Ġfor Ġdivision Ġby Ġzero Ġor Ġout - of - range . Ċ ĉ override Ġfun Ġhas Side Effect (): ĠBoolean Ġ= Ġtrue ĊĊ ĉ override Ġfun Ġinstruction Was Added ( Ċĉ ĉ instruction : ĠL 2 Instruction , Ġmanifest : ĠL 2 Value Manifest ) Ċ ĉ { Ċĉ ĉ assert ( this Ġ== Ġinstruction . operation ()) Ċĉ ĉ // ĉ ĉ final ĠL 2 ReadInt Operand Ġdiv id end Ġ= Ġinstruction . operand ( 0 ); Ċĉ ĉ val Ġdivisor Ġ= Ċĉĉ ĉ instruction . operand < L 2 ReadInt Operand >( 1 ) Ċĉ ĉ // ĉ ĉ final ĠL 2 Write Int Operand Ġquot ient Ġ= Ġinstruction . operand ( 2 ); Ċ // ĉ ĉ final ĠL 2 Write Int Operand Ġremainder Ġ= Ġinstruction . operand ( 3 ); Ċ // ĉ ĉ final ĠL 2 Pc Operand Ġout Of Range Ġ= Ġinstruction . operand ( 4 ); Ċĉ ĉ val Ġzero Div isor Ġ= Ċĉĉ ĉ instruction . operand < L 2 Pc Operand >( 5 ) Ċĉ ĉ // ĉ ĉ final ĠL 2 Pc Operand Ġsuccess Ġ= Ġinstruction . operand ( 6 ); Ċĉ ĉ super . instruction Was Added ( instruction , Ġmanifest ) ĊĊĉ ĉ // ĠOn Ġthe Ġzero Div isor Ġedge , Ġthe Ġdivisor Ġis Ġdefinitely Ġzero . Ċĉ ĉ zero Div isor . manifest (). set Restriction ( Ċĉĉ ĉ div isor . semantic Value (), Ċĉĉ ĉ restriction For Constant ( zero (), ĠUN BOX ED _ INT )) Ċ ĉ } ĊĊ ĉ override Ġfun Ġappend To With Warnings ( Ċĉ ĉ instruction : ĠL 2 Instruction , Ċĉ ĉ desired Types : ĠSet < L 2 Operand Type >, Ċĉ ĉ builder : ĠStringBuilder , Ċĉ ĉ warning Style Change : Ġ( Boolean ) Ġ-> ĠUnit ) Ċ ĉ { Ċĉ ĉ assert ( this Ġ== Ġinstruction . operation ()) Ċĉ ĉ val Ġdiv id end Ġ= Ġinstruction . operand < L 2 ReadInt Operand >( 0 ) Ċĉ ĉ val Ġdivisor Ġ= Ġinstruction . operand < L 2 ReadInt Operand >( 1 ) Ċĉ ĉ val Ġquot ient Ġ= Ġinstruction . operand < L 2 Write Int Operand >( 2 ) Ċĉ ĉ val Ġremainder Ġ= Ġinstruction . operand < L 2 Write Int Operand >( 3 ) Ċĉ ĉ // ĉ ĉ final ĠL 2 Pc Operand Ġout Of Range Ġ= Ġinstruction . operand ( 4 ); Ċ // ĉ ĉ final ĠL 2 Pc Operand Ġzero Div isor Ġ= Ġinstruction . operand ( 5 ); Ċ // ĉ ĉ final ĠL 2 Pc Operand Ġsuccess Ġ= Ġinstruction . operand ( 6 ); Ċĉ ĉ render P reamble ( instruction , Ġbuilder ) Ċĉ ĉ builder . append (" quo =") Ċĉ ĉ builder . append ( quot ient . register String ()) Ċĉ ĉ builder . append (", Ġrem =") Ċĉ ĉ builder . append ( remainder . register String ()) Ċĉ ĉ builder . append (" ĠâĨ Ĳ Ġ") Ċĉ ĉ builder . append ( divid end . register String ()) Ċĉ ĉ builder . append (" ĠÃ· Ġ") Ċĉ ĉ builder . append ( div isor . register String ()) Ċĉ ĉ render Oper ands Starting At ( instruction , Ġ 4 , Ġdesired Types , Ġbuilder ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġtranslate To JVM ( Ċĉ ĉ translator : ĠJVM Translator , Ċĉ ĉ method : ĠMethod Visitor , Ċĉ ĉ instruction : ĠL 2 Instruction ) Ċ ĉ { Ċĉ ĉ val Ġdiv id end Ġ= Ġinstruction . operand < L 2 ReadInt Operand >( 0 ) Ċĉ ĉ val Ġdivisor Ġ= Ġinstruction . operand < L 2 ReadInt Operand >( 1 ) Ċĉ ĉ val Ġquot ient Ġ= Ġinstruction . operand < L 2 Write Int Operand >( 2 ) Ċĉ ĉ val Ġremainder Ġ= Ġinstruction . operand < L 2 Write Int Operand >( 3 ) Ċĉ ĉ val Ġout Of Range Ġ= Ġinstruction . operand < L 2 Pc Operand >( 4 ) Ċĉ ĉ val Ġzero Div isor Ġ= Ġinstruction . operand < L 2 Pc Operand >( 5 ) Ċĉ ĉ val Ġsuccess Ġ= Ġinstruction . operand < L 2 Pc Operand >( 6 ) ĊĊĉ ĉ // Ġ:: Ġif Ġ( div isor Ġ== Ġ 0 ) Ġgoto Ġzero Div isor Index ; Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ method . visit Jump Insn ( Op codes . IF EQ , Ġtranslator . label For ( zero Div isor . offset ())) ĊĊĉ ĉ // Ġa / b Ġfor Ġb < 0 : Ġ Ġuse Ġ-( a /- b ) Ċĉ ĉ // Ġ:: Ġif Ġ( div isor Ġ< Ġ 0 ) Ġquot ient Ġ= Ġ-( divid end Ġ/ Ġ- div isor ); Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ val Ġcheck Div id end Ġ= ĠLabel () Ċĉ ĉ method . visit Jump Insn ( Op codes . IF GE , Ġcheck Div id end ) Ċĉ ĉ translator . load ( method , Ġdiv id end . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . L NEG ) Ċĉ ĉ method . visit Insn ( Op codes . L DIV ) Ċĉ ĉ method . visit Insn ( Op codes . L NEG ) Ċĉ ĉ val Ġquot ient Long Ġ= Ġtranslator . next Local ( Type . LONG _ TYPE ) Ċĉ ĉ method . visit Var Insn ( Op codes . L STORE , Ġquot ient Long ) Ċĉ ĉ val Ġquot ient Computed Ġ= ĠLabel () Ċĉ ĉ method . visit Jump Insn ( Op codes . GOTO , Ġquot ient Computed ) ĊĊĉ ĉ // Ġa / b Ġfor Ġa < 0 , Ġb > 0 : Ġ Ġuse Ġ- 1 - (- 1 - a )/ b Ċĉ ĉ // Ġ:: Ġelse Ġif Ġ( divid end Ġ< Ġ 0 ) Ċĉ ĉ // Ġ:: ĠĠĠ Ġquot ient Ġ= Ġ- 1 L Ġ- Ġ(( - 1 L Ġ- Ġdiv id end ) Ġ/ Ġdivisor ); Ċĉ ĉ translator . load ( method , Ġdiv id end . register ()) Ċĉ ĉ val Ġboth Non Negative Ġ= ĠLabel () Ċĉ ĉ method . visit Jump Insn ( Op codes . IF GE , Ġboth Non Negative ) Ċĉ ĉ translator . long Constant ( method , Ġ- 1 ) Ċĉ ĉ method . visit Insn ( Op codes . DUP ) Ċĉ ĉ translator . load ( method , Ġdiv id end . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . LS UB ) Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . L DIV ) Ċĉ ĉ method . visit Insn ( Op codes . LS UB ) Ċĉ ĉ method . visit Var Insn ( Op codes . L STORE , Ġquot ient Long ) Ċĉ ĉ method . visit Jump Insn ( Op codes . GOTO , Ġquot ient Computed ) ĊĊĉ ĉ // Ġ:: Ġelse Ġquot ient Ġ= Ġdiv id end Ġ/ Ġdivisor ; Ċĉ ĉ translator . load ( method , Ġdiv id end . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . L DIV ) Ċĉ ĉ method . visit Var Insn ( Op codes . L STORE , Ġquot ient Long ) ĊĊĉ ĉ // ĠRem ain der Ġis Ġalways Ġnon - negative . Ċĉ ĉ // Ġ:: Ġremainder Ġ= Ġdiv id end Ġ- Ġ( quot ient Ġ* Ġdivisor ); Ċĉ ĉ method . visit Label ( quot ient Computed ) Ċĉ ĉ translator . load ( method , Ġdiv id end . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Var Insn ( Op codes . L LOAD , Ġquot ient Long ) Ċĉ ĉ translator . load ( method , Ġdivisor . register ()) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . L MUL ) Ċĉ ĉ method . visit Insn ( Op codes . LS UB ) Ċĉ ĉ val Ġremainder Long Ġ= Ġtranslator . next Local ( Type . LONG _ TYPE ) Ċĉ ĉ method . visit Var Insn ( Op codes . L STORE , Ġremainder Long ) ĊĊĉ ĉ // Ġ:: Ġif Ġ( quot ient Ġ!= Ġ( int ) Ġquot ient ) Ġgoto Ġout Of Range ; Ċĉ ĉ method . visit Var Insn ( Op codes . L LOAD , Ġquot ient Long ) Ċĉ ĉ method . visit Insn ( Op codes . DUP ) Ċĉ ĉ method . visit Insn ( Op codes . L 2 I ) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . LC MP ) Ċĉ ĉ translator . jump If ( method , ĠOp codes . IF NE , Ġout Of Range ) Ċĉ ĉ // Ġ:: Ġ Ġif Ġ( remainder Ġ!= Ġ( int ) Ġremainder ) Ġgoto Ġout Of Range ; Ċĉ ĉ method . visit Var Insn ( Op codes . L LOAD , Ġremainder Long ) Ċĉ ĉ method . visit Insn ( Op codes . DUP ) Ċĉ ĉ method . visit Insn ( Op codes . L 2 I ) Ċĉ ĉ method . visit Insn ( Op codes . I 2 L ) Ċĉ ĉ method . visit Insn ( Op codes . LC MP ) Ċĉ ĉ translator . jump If ( method , ĠOp codes . IF NE , Ġout Of Range ) Ċĉ ĉ // Ġ:: ĠĠĠ Ġint Quot ient Ġ= Ġ( int ) Ġquot ient ; Ċĉ ĉ method . visit Var Insn ( Op codes . L LOAD , Ġquot ient Long ) Ċĉ ĉ method . visit Insn ( Op codes . L 2 I ) Ċĉ ĉ translator . store ( method , Ġquot ient . register ()) Ċĉ ĉ // Ġ:: ĠĠĠ Ġint Remain der Ġ= Ġ( int ) Ġremainder ; Ċĉ ĉ method . visit Var Insn ( Op codes . L LOAD , Ġremainder Long ) Ċĉ ĉ method . visit Insn ( Op codes . L 2 I ) Ċĉ ĉ translator . store ( method , Ġremainder . register ()) Ċĉ ĉ // Ġ:: ĠĠĠ Ġgoto Ġsuccess ; Ċĉ ĉ translator . jump ( method , Ġsuccess ) Ċ ĉ } Ċ } Ċ