123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710(**************************************************************************)(* *)(* OCaml *)(* *)(* Jacob Van Buren, Jane Street, New York *)(* *)(* Copyright 2025 Jane Street Group LLC *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)typeany_locality_mode=Any_locality_modeletequal_any_locality_modeAny_locality_modeAny_locality_mode=trueletignore_locality_=Any_locality_modemoduleMaybe_naked=structtype('a,'b)t=|Valueof'a|Nakedof'bmoduleMake1(M:sigtype'atvalall:any_locality_modetlistvalmap:'at->f:('a->'b)->'btvalto_string:any_locality_modet->stringvalnaked_sort:any_locality_modet->Jkind_types.Sort.Const.tvalequal:('a->'b->bool)->'at->'bt->boolend)=structtypenonrec'at=('aM.t,any_locality_modeM.t)tletmap(t:_t)~f=matchtwith|Naked(_:any_locality_modeM.t)ast->t|Valuet->Value(M.mapt~f)letwidth:_t->any_locality_modeM.t=function|Nakedt->t|Valuet->M.mapt~f:ignore_localityletto_string=function|Valuem->M.to_stringm|Nakedm->M.to_stringm^"#"letignore_locality=map~f:ignore_localityletall=List.concat_map(funm->[Valuem;Nakedm])M.allletsort=function|Value(_:any_locality_modeM.t)->Jkind_types.Sort.Const.scannable|Nakedt->M.naked_sorttletequaleqxy=matchx,ywith|Valuex,Valuey->M.equaleqxy|Value_,_->false|Nakedx,Nakedy->M.equalequal_any_locality_modexy|Naked_,_->falseendendletnakedn=Maybe_naked.NakednmoduleIntegral=structmoduleTaggable=structmoduleWidth=structtypet=|Int8|Int16|Intletall=[Int8;Int16;Int]letto_string=function|Int8->"int8"|Int16->"int16"|Int->"int"letnaked_sort=function|Int8->Jkind_types.Sort.Const.bits8|Int16->Jkind_types.Sort.Const.bits16|Int->Jkind_types.Sort.Const.untagged_immediateletequal_eq((Int8|Int16|Int)asx)y=x=yendincludeMaybe_naked.Make1(structincludeWidthtypenonrec'at=tletmapt~f:_=tend)endmoduleBoxable=structmoduleWidth=structtype'modet=|Int32of'mode|Nativeintof'mode|Int64of'modeletall=[Int32Any_locality_mode;NativeintAny_locality_mode;Int64Any_locality_mode]letmapt~f=matchtwith|Int32mode->Int32(fmode)|Nativeintmode->Nativeint(fmode)|Int64mode->Int64(fmode)letto_string=function|Int32Any_locality_mode->"int32"|NativeintAny_locality_mode->"nativeint"|Int64Any_locality_mode->"int64"letnaked_sort=function|Int32Any_locality_mode->Jkind_types.Sort.Const.bits32|Int64Any_locality_mode->Jkind_types.Sort.Const.bits64|NativeintAny_locality_mode->Jkind_types.Sort.Const.wordletequaleqxy=matchx,ywith|Int32x,Int32y->eqxy|Int32_,_->false|Nativeintx,Nativeinty->eqxy|Nativeint_,_->false|Int64x,Int64y->eqxy|Int64_,_->falseendincludeMaybe_naked.Make1(Width)endmoduleWidth=structtype'modet=|TaggableofTaggable.Width.t|Boxableof'modeBoxable.Width.tletall=List.concat[List.map(funt->Taggablet)Taggable.Width.all;List.map(funt->Boxablet)Boxable.Width.all]letmapt~f=matchtwith|Taggable(Int8|Int16|Int)ast->t|Boxableb->Boxable(Boxable.Width.mapb~f)letto_string=function|Taggablet->Taggable.Width.to_stringt|Boxableb->Boxable.Width.to_stringbletnaked_sort=function|Taggablet->Taggable.Width.naked_sortt|Boxableb->Boxable.Width.naked_sortbletequaleqxy=matchx,ywith|Taggablex,Taggabley->Taggable.Width.equaleqxy|Taggable_,_->false|Boxablex,Boxabley->Boxable.Width.equaleqxy|Boxable_,_->falseendincludeMaybe_naked.Make1(Width)endmoduleFloating=structmoduleWidth=structtype'modet=|Float32of'mode|Float64of'modeletall=[Float32Any_locality_mode;Float64Any_locality_mode]letmapt~f=matchtwith|Float32mode->Float32(fmode)|Float64mode->Float64(fmode)letto_string=function|Float32Any_locality_mode->"float32"|Float64Any_locality_mode->"float"letnaked_sort=function|Float32Any_locality_mode->Jkind_types.Sort.Const.float32|Float64Any_locality_mode->Jkind_types.Sort.Const.float64letequaleqxy=matchx,ywith|Float32x,Float32y->eqxy|Float32_,_->false|Float64x,Float64y->eqxy|Float64_,_->falseendincludeMaybe_naked.Make1(Width)endmoduleWidth=structtype'modet=|Floatingof'modeFloating.Width.t|Integralof'modeIntegral.Width.tletall=List.concat[List.map(funt->Floatingt)Floating.Width.all;List.map(funt->Integralt)Integral.Width.all]letmapt~f=matchtwith|Floatingg->Floating(Floating.Width.mapg~f)|Integrali->Integral(Integral.Width.mapi~f)letnaked_sort=function|Floatingf->Floating.Width.naked_sortf|Integrali->Integral.Width.naked_sortiletignore_locality=map~f:ignore_localityletto_string=function|Floatingf->Floating.Width.to_stringf|Integrali->Integral.Width.to_stringiletequaleqxy=matchx,ywith|Floatingx,Floatingy->Floating.Width.equaleqxy|Floating_,_->false|Integralx,Integraly->Integral.Width.equaleqxy|Integral_,_->falseendincludeMaybe_naked.Make1(Width)letintegral:'aIntegral.t->'at=function|Valuei->Value(Integrali)|Nakedi->Naked(Integrali)letfloating:'aFloating.t->'at=function|Valuef->Value(Floatingf)|Nakedf->Naked(Floatingf)moduleSignedness=structtypet=|Signed|Unsignedletall=[Signed;Unsigned]letequal((Signed|Unsigned)asx:t)(y:t)=(* polymorphic equality is fast and simple when they are all constant constructors *)x=yletprintppft=matchtwith|Signed->Format.pp_print_stringppf"signed"|Unsigned->Format.pp_print_stringppf"unsigned"endmoduleInteger_comparison=structtypet=|Ceq|Cne|Clt|Cgt|Cle|Cge|Cult|Cugt|Cule|Cugeletall=[Ceq;Cne;Clt;Cgt;Cle;Cge;Cult;Cugt;Cule;Cuge]letequal((Ceq|Cne|Clt|Cgt|Cle|Cge|Cult|Cugt|Cule|Cuge)asx:t)(y:t)=(* polymorphic equality is fast and simple when they are all constant constructors *)x=yletto_string=function|Ceq->"equal"|Cne->"notequal"|Cgt->"greaterthan"|Cge->"greaterequal"|Clt->"lessthan"|Cle->"lessequal"|Cugt->"unsigned_greaterthan"|Cuge->"unsigned_greaterequal"|Cult->"unsigned_lessthan"|Cule->"unsigned_lessequal"letnegate=function|Ceq->Cne|Cne->Ceq|Clt->Cge|Cle->Cgt|Cgt->Cle|Cge->Clt|Cult->Cuge|Cule->Cugt|Cugt->Cule|Cuge->Cultletswap=function|Ceq->Ceq|Cne->Cne|Clt->Cgt|Cle->Cge|Cgt->Clt|Cge->Cle|Cult->Cugt|Cule->Cuge|Cugt->Cult|Cuge->Culeletcreatesignedness~lt~eq~gt=matchlt,eq,gt,(signedness:Signedness.t)with|false,true,false,(Signed|Unsigned)->OkCeq|true,false,true,(Signed|Unsigned)->OkCne|true,false,false,Signed->OkClt|false,false,true,Signed->OkCgt|true,true,false,Signed->OkCle|false,true,true,Signed->OkCge|true,false,false,Unsigned->OkCult|false,false,true,Unsigned->OkCugt|true,true,false,Unsigned->OkCule|false,true,true,Unsigned->OkCuge|true,true,true,(Signed|Unsigned)->Errortrue|false,false,false,(Signed|Unsigned)->ErrorfalseendmoduleFloat_comparison=structtypet=|CFeq|CFneq|CFlt|CFnlt|CFgt|CFngt|CFle|CFnle|CFge|CFngeletall=[CFeq;CFneq;CFlt;CFnlt;CFgt;CFngt;CFle;CFnle;CFge;CFnge]letto_string=function|CFeq->"ordered_and_equal"|CFgt->"ordered_and_greaterthan"|CFge->"ordered_and_greaterequal"|CFlt->"ordered_and_lessthan"|CFle->"ordered_and_lessequal"|CFneq->"unordered_or_notequal"|CFngt->"unordered_or_lessequal"|CFnge->"unordered_or_lessthan"|CFnlt->"unordered_or_greaterequal"|CFnle->"unordered_or_greaterthan"letnegate=function|CFeq->CFneq|CFneq->CFeq|CFlt->CFnlt|CFnlt->CFlt|CFgt->CFngt|CFngt->CFgt|CFle->CFnle|CFnle->CFle|CFge->CFnge|CFnge->CFgeletswap=function|CFeq->CFeq|CFneq->CFneq|CFlt->CFgt|CFnlt->CFngt|CFle->CFge|CFnle->CFnge|CFgt->CFlt|CFngt->CFnlt|CFge->CFle|CFnge->CFnleendmoduleOperation=structtype'modeinfo={can_raise:bool;result:'modet}(* CR jvanburen: nullary primitives for 0/1/-1/min/max once we can put
unboxed values into structures?
*)moduleUnary=struct(* Remember to update [all] right below this if you add a constructor *)moduleInt_op=structtypet=|Neg|Succ(** add 1 *)|Pred(** subtract 1 *)|Bswapletall=[Neg;Succ;Pred;Bswap]letto_string=function|Neg->"neg"|Succ->"succ"|Pred->"pred"|Bswap->"bswap"endmoduleFloat_op=structtypet=|Neg|Absletall=[Neg;Abs]letto_string=functionNeg->"neg"|Abs->"abs"endtypenonrec'modet=(* CR jvanburen: logical Not, int Abs, float bitcast *)|Integralof'modeIntegral.t*Int_op.t|Floatingof'modeFloating.t*Float_op.t|Static_castof{src:any_locality_modet;dst:'modet}letall=List.concat[ListLabels.concat_mapIntegral.all~f:(funsize->ListLabels.mapInt_op.all~f:(funop->Integral(size,op)));ListLabels.concat_mapFloating.all~f:(funsize->ListLabels.mapFloat_op.all~f:(funop->Floating(size,op)));ListLabels.concat_mapall~f:(funsrc->ListLabels.concat_mapall~f:(fundst->ifsrc=dstthen[]else[Static_cast{src;dst}]))]letmap(typeab)(t:at)~(f:a->b):bt=matchtwith|Integral(size,op)->Integral(Integral.mapsize~f,op)|Floating(size,op)->Floating(Floating.mapsize~f,op)|Static_cast{src;dst}->Static_cast{src;dst=mapdst~f}letinfo=function|Integral(size,(Neg|Bswap|Succ|Pred))->{result=integralsize;can_raise=false}|Floating(size,(Neg|Abs))->{result=floatingsize;can_raise=false}|Static_cast{src=_;dst}->{result=dst;can_raise=false}letto_stringt=leti=Integral.to_stringinletf=Floating.to_stringinmatchtwith|Integral(size,op)->Printf.sprintf"%s_%s"(isize)(Int_op.to_stringop)|Floating(size,op)->Printf.sprintf"%s_%s"(fsize)(Float_op.to_stringop)|Static_cast{src;dst}->Printf.sprintf"%s_of_%s"(to_stringdst)(to_stringsrc)letsort=function|Integral(width,_)->letsort=Integral.sortwidthinsort,sort|Floating(width,_)->letsort=Floating.sortwidthinsort,sort|Static_cast{src;dst}->sortsrc,sortdstendmoduleBinary=structmoduleInt_op=structtypedivision_is_safe=|Safe|Unsafetypet=|Add|Sub|Mul|Divofdivision_is_safe|Modofdivision_is_safe|And|Or|Xorletall=[Add;Sub;Mul;DivSafe;DivUnsafe;ModSafe;ModUnsafe;And;Or;Xor]letto_string=function|Add->"add"|Sub->"sub"|Mul->"mul"|DivSafe->"div"|DivUnsafe->"unsafe_div"|ModSafe->"mod"|ModUnsafe->"unsafe_mod"|And->"and"|Or->"or"|Xor->"xor"endmoduleShift_op=structmoduleRhs=struct(* CR jvanburen: expand this to all of [Integral.t] *)typet=Intletall=[Int]endtypet=|Lsl|Asr|Lsrletall=[Lsl;Asr;Lsr]letto_string=functionLsl->"lsl"|Asr->"asr"|Lsr->"lsr"endmoduleFloat_op=structtypet=|Add|Sub|Mul|Divletall=[Add;Sub;Mul;Div]letto_string=function|Add->"add"|Sub->"sub"|Mul->"mul"|Div->"div"end(* CR jvanburen: comparisons that return naked values *)(** comparisons return a tagged immediate *)type'modet=(* CR jvanburen: Fmod, Min, Max? *)|Integralof'modeIntegral.t*Int_op.t|Shiftof'modeIntegral.t*Shift_op.t*Shift_op.Rhs.t|Floatingof'modeFloating.t*Float_op.t|Icmpofany_locality_modeIntegral.t*Integer_comparison.t|Fcmpofany_locality_modeFloating.t*Float_comparison.t|Three_way_compare_intofSignedness.t*any_locality_modeIntegral.t|Three_way_compare_floatofany_locality_modeFloating.tletall=List.concat[ListLabels.concat_mapIntegral.all~f:(funsize->ListLabels.mapInt_op.all~f:(funop->Integral(size,op)));ListLabels.concat_mapFloating.all~f:(funsize->ListLabels.mapFloat_op.all~f:(funop->Floating(size,op)));ListLabels.concat_mapIntegral.all~f:(funsize->ListLabels.concat_mapShift_op.all~f:(funop->ListLabels.mapShift_op.Rhs.all~f:(funrhs->Shift(size,op,rhs))));ListLabels.concat_mapInteger_comparison.all~f:(funcmp->List.map(funsize->Icmp(size,cmp))Integral.all);ListLabels.concat_mapFloat_comparison.all~f:(funcmp->List.map(funsize->Fcmp(size,cmp))Floating.all);ListLabels.concat_mapSignedness.all~f:(funsignedness->ListLabels.mapIntegral.all~f:(funsize->Three_way_compare_int(signedness,size)));ListLabels.mapFloating.all~f:(funsize->Three_way_compare_floatsize)]letsort=function|Integral(width,(Add|Sub|Mul|Div(Safe|Unsafe)|Mod(Safe|Unsafe)|And|Or|Xor))->letsort=Integral.sortwidthinsort,sort,sort|Shift(width,(Lsl|Lsr|Asr),Int)->letsort=Integral.sortwidthinsort,Jkind_types.Sort.Const.scannable,sort|Floating(width,(Add|Sub|Mul|Div))->letsort=Floating.sortwidthinsort,sort,sort|Icmp(width,(_:Integer_comparison.t))->letsort=Integral.sortwidthinsort,sort,Jkind_types.Sort.Const.scannable|Fcmp(width,(_:Float_comparison.t))->letsort=Floating.sortwidthinsort,sort,Jkind_types.Sort.Const.scannable|Three_way_compare_int((Signed|Unsigned),width)->letsort=Integral.sortwidthinsort,sort,Jkind_types.Sort.Const.scannable|Three_way_compare_floatwidth->letsort=Floating.sortwidthinsort,sort,Jkind_types.Sort.Const.scannableletto_stringt=letmakesizename=String.concat"_"[to_stringsize;name]inmatchtwith|Integral(size,op)->make(integralsize)(Int_op.to_stringop)|Floating(size,op)->make(floatingsize)(Float_op.to_stringop)|Shift(size,op,Int)->make(integralsize)(Shift_op.to_stringop)|Icmp(size,cmp)->make(integralsize)(Integer_comparison.to_stringcmp)|Fcmp(size,cmp)->make(floatingsize)(Float_comparison.to_stringcmp)|Three_way_compare_int(Signed,size)->make(integralsize)"compare"|Three_way_compare_int(Unsigned,size)->make(integralsize)"unsigned_compare"|Three_way_compare_floatsize->make(floatingsize)"compare"letmapt~f=matchtwith|Integral(size,op)->Integral(Integral.mapsize~f,op)|Floating(size,op)->Floating(Floating.mapsize~f,op)|Shift(size,op,rhs)->Shift(Integral.mapsize~f,op,rhs)|Icmp(size,cmp)->Icmp(size,cmp)|Fcmp(size,cmp)->Fcmp(size,cmp)|Three_way_compare_int(signedness,size)->Three_way_compare_int(signedness,size)|Three_way_compare_floatsize->Three_way_compare_floatsizeletinfo=function|Integral(size,(Add|Sub|Mul|DivUnsafe|ModUnsafe|And|Or|Xor))|Shift(size,(Lsl|Lsr|Asr),Int)->{result=integralsize;can_raise=false}|Integral(size,(DivSafe|ModSafe))->{result=integralsize;can_raise=true}|Floating(size,(Add|Sub|Mul|Div))->{result=floatingsize;can_raise=false}|Icmp((_:any_locality_modeIntegral.t),(_:Integer_comparison.t))|Fcmp((_:any_locality_modeFloating.t),(_:Float_comparison.t))|Three_way_compare_int((Signed|Unsigned),(_:any_locality_modeIntegral.t))|Three_way_compare_float(_:any_locality_modeFloating.t)->{result=integral(Value(TaggableInt));can_raise=false}endtype'modet=|Unaryof'modeUnary.t|Binaryof'modeBinary.tletall=List.concat[List.map(funu->Unaryu)Unary.all;List.map(funb->Binaryb)Binary.all]letsort=function|Unaryu->letx,y=Unary.sortuin[x;y]|Binaryb->letx,y,z=Binary.sortbin[x;y;z]letmapt~f=matchtwith|Unaryu->Unary(Unary.mapu~f)|Binaryb->Binary(Binary.mapb~f)letinfo=functionUnaryu->Unary.infou|Binaryb->Binary.infobletto_string=function|Unaryu->Unary.to_stringu|Binaryb->Binary.to_stringbletarity=functionUnary_->1|Binary_->2letof_string=letmoduleTbl=Misc.Stdlib.String.Tblinlettbl=lazy(lettbl=Tbl.create(2*List.lengthall)inListLabels.iterall~f:(funt->Tbl.addtbl(to_stringt)t);tbl)infuns->Tbl.find(Lazy.forcetbl)smoduleWith_percent_prefix=structtypenonrect=any_locality_modetletto_stringt="%"^to_stringtletof_strings=letlen=String.lengthsiniflen=0||s.[0]<>'%'thenraiseNot_foundelseof_string(StringLabels.subs~pos:1~len:(len-1))endend