Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file eval.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999(* SPDX-License-Identifier: MIT *)(* Copyright (C) 2023-2024 formalsec *)(* Written by the Smtml programmers *)(* Adapted from: *)(* - https://github.com/WebAssembly/spec/blob/main/interpreter/exec/ixx.ml, *)(* - https://github.com/WebAssembly/spec/blob/main/interpreter/exec/fxx.ml, and *)(* - https://github.com/WebAssembly/spec/blob/main/interpreter/exec *)typeop_type=[`UnopofTy.Unop.t|`BinopofTy.Binop.t|`RelopofTy.Relop.t|`TriopofTy.Triop.t|`CvtopofTy.Cvtop.t|`NaryopofTy.Naryop.t]letpp_op_typefmt=function|`Unopop->Fmt.pffmt"unop '%a'"Ty.Unop.ppop|`Binopop->Fmt.pffmt"binop '%a'"Ty.Binop.ppop|`Relopop->Fmt.pffmt"relop '%a'"Ty.Relop.ppop|`Triopop->Fmt.pffmt"triop '%a'"Ty.Triop.ppop|`Cvtopop->Fmt.pffmt"cvtop '%a'"Ty.Cvtop.ppop|`Naryopop->Fmt.pffmt"naryop '%a'"Ty.Naryop.ppoptypetype_error_info={index:int;value:Value.t;ty:Ty.t;op:op_type;msg:string}typeerror_kind=[`Divide_by_zero|`Conversion_to_integer|`Integer_overflow|`Index_out_of_bounds|`Invalid_format_conversion|`Unsupported_operatorofop_type*Ty.t|`Unsupported_theoryofTy.t|`Type_erroroftype_error_info]exceptionEval_erroroferror_kindexceptionValueofTy.t(* Exception helpers *)leteval_errorkind=raise(Eval_errorkind)lettype_errornvtyopmsg=eval_error(`Type_error{index=n;value=v;ty;op;msg})leterr_strnopty_expectedty_actual=Fmt.str"Argument %d of %a expected type %a but got %a instead."npp_op_typeopTy.ppty_expectedTy.ppty_actuallet[@inline]of_argfnvop=tryfvwithValueexpected_ty->letactual_ty=Value.type_ofvinletmsg=err_strnopexpected_tyactual_tyintype_errornvexpected_tyopmsg(* Coercion helpers *)letof_intnopv=of_arg(functionIntx->x|_->raise_notrace(ValueTy_int))nvoplet[@inline]to_intx=Value.Intxletof_realnopv=of_arg(functionRealx->x|_->raise_notrace(ValueTy_real))nvoplet[@inline]to_realx=Value.Realxletof_boolnopv=of_arg(function|True->true|False->false|_->raise_notrace(ValueTy_bool))nvoplet[@inline]to_boolx=ifxthenValue.TrueelseFalseletof_strnopv=of_arg(functionStrx->x|_->raise_notrace(ValueTy_str))nvoplet[@inline]to_strx=Value.Strxletof_listnopv=of_arg(functionListx->x|_->raise_notrace(ValueTy_list))nvopletof_bitvnopv=of_arg(functionBitvx->x|_->raise_notrace(Value(Ty_bitv0)))nvopletint32_of_bitvnopv=of_bitvnopv|>Bitvector.to_int32letint64_of_bitvnopv=of_bitvnopv|>Bitvector.to_int64let[@inline]to_bitvx=Value.Bitvxlet[@inline]bitv_of_int32x=to_bitv(Bitvector.of_int32x)let[@inline]bitv_of_int64x=to_bitv(Bitvector.of_int64x)letof_fp32iopv:int32=of_arg(functionNum(F32f)->f|_->raise_notrace(Value(Ty_fp32)))ivoplet[@inline]to_fp32(x:int32)=Value.Num(F32x)let[@inline]fp32_of_float(x:float)=to_fp32(Int32.bits_of_floatx)letof_fp64iopv:int64=of_arg(functionNum(F64f)->f|_->raise_notrace(Value(Ty_fp32)))ivoplet[@inline]to_fp64(x:int64)=Value.Num(F64x)let[@inline]fp64_of_float(x:float)=to_fp64(Int64.bits_of_floatx)(* Operator evaluation *)moduleInt=structletunop(op:Ty.Unop.t)(v:Value.t):Value.t=letf=matchopwith|Neg->Int.neg|Not->Int.lognot|Abs->Int.abs|_->eval_error(`Unsupported_operator(`Unopop,Ty_int))into_int(f(of_int1(`Unopop)v))letexp_by_squaringxn=letrecexp_by_squaring2yxn=ifn<0thenexp_by_squaring2y(1/x)~-nelseifn=0thenyelseifnmod2=0thenexp_by_squaring2y(x*x)(n/2)elsebeginassert(nmod2=1);exp_by_squaring2(x*y)(x*x)((n-1)/2)endinexp_by_squaring21xnletbinop(op:Ty.Binop.t)(v1:Value.t)(v2:Value.t):Value.t=letf=matchopwith|Add->Int.add|Sub->Int.sub|Mul->Int.mul|Div->Int.div|Rem->Int.rem|Pow->exp_by_squaring|Min->Int.min|Max->Int.max|And->Int.logand|Or->Int.logor|Xor->Int.logxor|Shl->Int.shift_left|ShrL->Int.shift_right_logical|ShrA->Int.shift_right|_->eval_error(`Unsupported_operator(`Binopop,Ty_int))into_int(f(of_int1(`Binopop)v1)(of_int2(`Binopop)v2))letrelop(op:Ty.Relop.t)(v1:Value.t)(v2:Value.t):bool=letf=matchopwith|Lt->(<)|Le->(<=)|Gt->(>)|Ge->(>=)|Eq->Int.equal|Ne->funab->not(Int.equalab)|_->eval_error(`Unsupported_operator(`Relopop,Ty_int))inf(of_int1(`Relopop)v1)(of_int2(`Relopop)v2)letof_bool:Value.t->int=function|True->1|False->0|_->assertfalse[@@inline]letcvtop(op:Ty.Cvtop.t)(v:Value.t):Value.t=matchopwith|OfBool->to_int(of_boolv)|Reinterpret_float->Int(Int.of_float(of_real1(`Cvtopop)v))|_->eval_error(`Unsupported_operator(`Cvtopop,Ty_int))endmoduleReal=structletunop(op:Ty.Unop.t)(v:Value.t):Value.t=letv=of_real1(`Unopop)vinmatchopwith|Neg->to_real@@Float.negv|Abs->to_real@@Float.absv|Sqrt->to_real@@Float.sqrtv|Nearest->to_real@@Float.roundv|Ceil->to_real@@Float.ceilv|Floor->to_real@@Float.floorv|Trunc->to_real@@Float.truncv|Is_nan->ifFloat.is_nanvthenValue.TrueelseValue.False|_->eval_error(`Unsupported_operator(`Unopop,Ty_real))letbinop(op:Ty.Binop.t)(v1:Value.t)(v2:Value.t):Value.t=letf=matchopwith|Add->Float.add|Sub->Float.sub|Mul->Float.mul|Div->Float.div|Rem->Float.rem|Min->Float.min|Max->Float.max|Pow->Float.pow|_->eval_error(`Unsupported_operator(`Binopop,Ty_real))into_real(f(of_real1(`Binopop)v1)(of_real2(`Binopop)v2))letrelop(op:Ty.Relop.t)(v1:Value.t)(v2:Value.t):bool=letf=matchopwith|Lt->Float.Infix.(<)|Le->Float.Infix.(<=)|Gt->Float.Infix.(>)|Ge->Float.Infix.(>=)|Eq->Float.Infix.(=)|Ne->Float.Infix.(<>)|_->eval_error(`Unsupported_operator(`Relopop,Ty_real))inf(of_real1(`Relopop)v1)(of_real2(`Relopop)v2)letcvtop(op:Ty.Cvtop.t)(v:Value.t):Value.t=letop'=`Cvtopopinmatchopwith|ToString->Str(Float.to_string(of_real1op'v))|OfString->beginmatchfloat_of_string_opt(of_str1op'v)with|None->eval_error`Invalid_format_conversion|Somev->to_realvend|Reinterpret_int->to_real(float_of_int(of_int1op'v))|Reinterpret_float->to_int(Float.to_int(of_real1op'v))|_->eval_error(`Unsupported_operator(op',Ty_real))endmoduleBool=structletunop(op:Ty.Unop.t)v=letb=of_bool1(`Unopop)vinmatchopwith|Not->to_bool(notb)|_->eval_error(`Unsupported_operator(`Unopop,Ty_bool))letxorb1b2=match(b1,b2)with|true,true->false|true,false->true|false,true->true|false,false->falseletbinop(op:Ty.Binop.t)v1v2=letf=matchopwith|And->(&&)|Or->(||)|Xor->xor|_->eval_error(`Unsupported_operator(`Binopop,Ty_bool))into_bool(f(of_bool1(`Binopop)v1)(of_bool2(`Binopop)v2))lettriop(op:Ty.Triop.t)cv1v2=matchopwith|Ite->(matchof_bool1(`Triopop)cwithtrue->v1|false->v2)|_->eval_error(`Unsupported_operator(`Triopop,Ty_bool))letrelop(op:Ty.Relop.t)v1v2=matchopwith|Eq->Value.equalv1v2|Ne->not(Value.equalv1v2)|_->eval_error(`Unsupported_operator(`Relopop,Ty_bool))letnaryop(op:Ty.Naryop.t)vs=letb=matchopwith|Logand->List.fold_left(&&)true(List.mapi(funi->of_booli(`Naryopop))vs)|Logor->List.fold_left(||)false(List.mapi(funi->of_booli(`Naryopop))vs)|_->eval_error(`Unsupported_operator(`Naryopop,Ty_bool))into_boolbendmoduleStr=structletreplacestt'=letlen_s=String.lengthsinletlen_t=String.lengthtinletrecloopi=ifi>=len_sthenselseifi+len_t>len_sthenselseifString.equal(String.subsilen_t)tthenlets'=Fmt.str"%s%s"(String.subs0i)t'inlets''=String.subs(i+len_t)(len_s-i-len_t)inFmt.str"%s%s"s's''elseloop(i+1)inloop0letindexofssubstart=letlen_s=String.lengthsinletlen_sub=String.lengthsubinletmax_i=len_s-1inletrecloopi=ifi>max_ithen~-1elseifi+len_sub>len_sthen~-1elseifString.equalsub(String.subsilen_sub)thenielseloop(i+1)inifstart<=0thenloop0elseloopstartletcontainsssub=ifindexofssub0<0thenfalseelsetrueletunop(op:Ty.Unop.t)v=letstr=of_str1(`Unopop)vinmatchopwith|Length->to_int(String.lengthstr)|Trim->to_str(String.trimstr)|_->eval_error(`Unsupported_operator(`Unopop,Ty_str))letbinop(op:Ty.Binop.t)v1v2=letop'=`Binopopinletstr=of_str1op'v1inmatchopwith|At->beginleti=of_int2op'v2intryto_str(Fmt.str"%c"(String.getstri))withInvalid_argument_->eval_error`Index_out_of_boundsend|String_prefix->to_bool(String.starts_with~prefix:str(of_str2op'v2))|String_suffix->to_bool(String.ends_with~suffix:str(of_str2op'v2))|String_contains->to_bool(containsstr(of_str2op'v2))|_->eval_error(`Unsupported_operator(op',Ty_str))lettriop(op:Ty.Triop.t)v1v2v3=letop'=`Triopopinletstr=of_str1op'v1inmatchopwith|String_extract->beginleti=of_int2op'v2inletlen=of_int3op'v3intryto_str(String.substrilen)withInvalid_argument_->eval_error`Index_out_of_boundsend|String_replace->lett=of_str2op'v2inlett'=of_str2op'v3into_str(replacestrtt')|String_index->lett=of_str2op'v2inleti=of_int3op'v3into_int(indexofstrti)|_->eval_error(`Unsupported_operator(`Triopop,Ty_str))letrelop(op:Ty.Relop.t)v1v2=letf=matchopwith|Lt->(<)|Le->(<=)|Gt->(>)|Ge->(>=)|Eq->(=)|Ne->(<>)|_->eval_error(`Unsupported_operator(`Relopop,Ty_str))inletfxy=f(String.comparexy)0inf(of_str1(`Relopop)v1)(of_str2(`Relopop)v2)letcvtop(op:Ty.Cvtop.t)v=letop'=`Cvtopopinmatchopwith|String_to_code->letstr=of_str1op'vinto_int(Char.codestr.[0])|String_from_code->letcode=of_int1op'vinto_str(String.make1(Char.chrcode))|String_to_int->beginlets=of_str1op'vinmatchint_of_string_optswith|None->eval_error`Invalid_format_conversion|Somex->to_intxend|String_from_int->to_str(string_of_int(of_int1op'v))|String_to_float->beginlets=of_str1op'vinmatchfloat_of_string_optswith|None->eval_error`Invalid_format_conversion|Somef->to_realfend|_->eval_error(`Unsupported_operator(`Cvtopop,Ty_str))letnaryop(op:Ty.Naryop.t)vs=letop'=`Naryopopinmatchopwith|Concat->to_str(String.concat""(List.map(of_str0op')vs))|_->eval_error(`Unsupported_operator(`Naryopop,Ty_str))endmoduleLst=structletunop(op:Ty.Unop.t)(v:Value.t):Value.t=letlst=of_list1(`Unopop)vinmatchopwith|Head->begin(* FIXME: Exception handling *)matchlstwith|hd::_tl->hd|[]->assertfalseend|Tail->begin(* FIXME: Exception handling *)matchlstwith|_hd::tl->Listtl|[]->assertfalseend|Length->to_int(List.lengthlst)|Reverse->List(List.revlst)|_->eval_error(`Unsupported_operator(`Unopop,Ty_list))letbinop(op:Ty.Binop.t)v1v2=letop'=`Binopopinmatchopwith|At->letlst=of_list1op'v1inleti=of_int2op'v2in(* TODO: change datastructure? *)beginmatchList.nth_optlstiwith|None->eval_error`Index_out_of_bounds|Somev->vend|List_cons->List(v1::of_list1op'v2)|List_append->List(of_list1op'v1@of_list2op'v2)|_->eval_error(`Unsupported_operator(`Binopop,Ty_list))lettriop(op:Ty.Triop.t)(v1:Value.t)(v2:Value.t)(v3:Value.t):Value.t=letop'=`Triopopinmatchopwith|List_set->letlst=of_list1op'v1inleti=of_int2op'v2inletrecsetilstvacc=match(i,lst)with|0,_::tl->List.rev_appendacc(v::tl)|i,hd::tl->set(i-1)tlv(hd::acc)|_,[]->eval_error`Index_out_of_boundsinList(setilstv3[])|_->eval_error(`Unsupported_operator(`Triopop,Ty_list))letnaryop(op:Ty.Naryop.t)(vs:Value.tlist):Value.t=letop'=`Naryopopinmatchopwith|Concat->List(List.concat_map(of_list0op')vs)|_->eval_error(`Unsupported_operator(`Naryopop,Ty_list))endmoduleI64=structletcmp_uxopy=opInt64.(addxmin_int)Int64.(addymin_int)[@@inline]letlt_uxy=cmp_uxInt64.Infix.(<)y[@@inline]endmoduleBitv=structletunopopbv=letbv=of_bitv1(`Unopop)bvinto_bitv@@matchopwith|Ty.Unop.Neg->Bitvector.negbv|Not->Bitvector.lognotbv|Clz->Bitvector.clzbv|Ctz->Bitvector.ctzbv|Popcnt->Bitvector.popcntbv|_->eval_error(`Unsupported_operator(`Unopop,Ty_bitv(Bitvector.numbitsbv)))letbinopopbv1bv2=letbv1=of_bitv1(`Binopop)bv1inletbv2=of_bitv2(`Binopop)bv2into_bitv@@matchopwith|Ty.Binop.Add->Bitvector.addbv1bv2|Sub->Bitvector.subbv1bv2|Mul->Bitvector.mulbv1bv2|Div->Bitvector.divbv1bv2|DivU->Bitvector.div_ubv1bv2|Rem->Bitvector.rembv1bv2|RemU->Bitvector.rem_ubv1bv2|And->Bitvector.logandbv1bv2|Or->Bitvector.logorbv1bv2|Xor->Bitvector.logxorbv1bv2|Shl->Bitvector.shlbv1bv2|ShrL->Bitvector.lshrbv1bv2|ShrA->Bitvector.ashrbv1bv2|Rotl->Bitvector.rotate_leftbv1bv2|Rotr->Bitvector.rotate_rightbv1bv2|_->eval_error(`Unsupported_operator(`Binopop,Ty_bitv0))letrelopopbv1bv2=letbv1=of_bitv1(`Relopop)bv1inletbv2=of_bitv2(`Relopop)bv2inmatchopwith|Ty.Relop.Lt->Bitvector.ltbv1bv2|LtU->Bitvector.lt_ubv1bv2|Le->Bitvector.lebv1bv2|LeU->Bitvector.le_ubv1bv2|Gt->Bitvector.gtbv1bv2|GtU->Bitvector.gt_ubv1bv2|Ge->Bitvector.gebv1bv2|GeU->Bitvector.ge_ubv1bv2|Eq->Bitvector.equalbv1bv2|Ne->not@@Bitvector.equalbv1bv2endmoduleF32=struct(* Stolen from Owi *)letabsx=Int32.logandxInt32.max_intletnegx=Int32.logxorxInt32.min_intletunop(op:Ty.Unop.t)(v:Value.t):Value.t=letf=Int32.float_of_bits(of_fp321(`Unopop)v)inmatchopwith|Neg->to_fp32@@neg@@of_fp321(`Unopop)v|Abs->to_fp32@@abs@@of_fp321(`Unopop)v|Sqrt->fp32_of_float@@Float.sqrtf|Nearest->fp32_of_float@@Float.roundf|Ceil->fp32_of_float@@Float.ceilf|Floor->fp32_of_float@@Float.floorf|Trunc->fp32_of_float@@Float.truncf|Is_nan->ifFloat.is_nanfthenValue.TrueelseValue.False|_->eval_error(`Unsupported_operator(`Unopop,Ty_fp32))(* Stolen from Owi *)letcopy_signxy=Int32.logor(absx)(Int32.logandyInt32.min_int)letbinop(op:Ty.Binop.t)(v1:Value.t)(v2:Value.t):Value.t=leta=Int32.float_of_bits@@of_fp321(`Binopop)v1inletb=Int32.float_of_bits@@of_fp321(`Binopop)v2inmatchopwith|Add->fp32_of_float@@Float.addab|Sub->fp32_of_float@@Float.subab|Mul->fp32_of_float@@Float.mulab|Div->fp32_of_float@@Float.divab|Rem->fp32_of_float@@Float.remab|Min->fp32_of_float@@Float.minab|Max->fp32_of_float@@Float.maxab|Copysign->leta=of_fp321(`Binopop)v1inletb=of_fp321(`Binopop)v2into_fp32(copy_signab)|_->eval_error(`Unsupported_operator(`Binopop,Ty_fp32))letrelop(op:Ty.Relop.t)(v1:Value.t)(v2:Value.t):bool=letf=matchopwith|Eq->Float.Infix.(=)|Ne->Float.Infix.(<>)|Lt->Float.Infix.(<)|Le->Float.Infix.(<=)|Gt->Float.Infix.(>)|Ge->Float.Infix.(>=)|_->eval_error(`Unsupported_operator(`Relopop,Ty_fp32))inleta=Int32.float_of_bits@@of_fp321(`Relopop)v1inletb=Int32.float_of_bits@@of_fp322(`Relopop)v2infabendmoduleF64=struct(* Stolen from owi *)letabsx=Int64.logandxInt64.max_intletnegx=Int64.logxorxInt64.min_intletunop(op:Ty.Unop.t)(v:Value.t):Value.t=letf=Int64.float_of_bits@@of_fp641(`Unopop)vinmatchopwith|Neg->to_fp64@@neg@@of_fp641(`Unopop)v|Abs->to_fp64@@abs@@of_fp641(`Unopop)v|Sqrt->fp64_of_float@@Float.sqrtf|Nearest->fp64_of_float@@Float.roundf|Ceil->fp64_of_float@@Float.ceilf|Floor->fp64_of_float@@Float.floorf|Trunc->fp64_of_float@@Float.truncf|Is_nan->ifFloat.is_nanfthenValue.TrueelseValue.False|_->Fmt.failwith{|unop: Unsupported f32 operator "%a"|}Ty.Unop.ppopletcopy_signxy=Int64.logor(absx)(Int64.logandyInt64.min_int)letbinop(op:Ty.Binop.t)(v1:Value.t)(v2:Value.t):Value.t=leta=Int64.float_of_bits@@of_fp641(`Binopop)v1inletb=Int64.float_of_bits@@of_fp642(`Binopop)v2inmatchopwith|Add->fp64_of_float@@Float.addab|Sub->fp64_of_float@@Float.subab|Mul->fp64_of_float@@Float.mulab|Div->fp64_of_float@@Float.divab|Rem->fp64_of_float@@Float.remab|Min->fp64_of_float@@Float.minab|Max->fp64_of_float@@Float.maxab|Copysign->leta=of_fp641(`Binopop)v1inletb=of_fp642(`Binopop)v2into_fp64@@copy_signab|_->eval_error(`Unsupported_operator(`Binopop,Ty_fp64))letrelop(op:Ty.Relop.t)(v1:Value.t)(v2:Value.t):bool=letf=matchopwith|Eq->Float.Infix.(=)|Ne->Float.Infix.(<>)|Lt->Float.Infix.(<)|Le->Float.Infix.(<=)|Gt->Float.Infix.(>)|Ge->Float.Infix.(>=)|_->eval_error(`Unsupported_operator(`Relopop,Ty_fp64))inleta=Int64.float_of_bits@@of_fp641(`Relopop)v1inletb=Int64.float_of_bits@@of_fp642(`Relopop)v2infabendmoduleI32CvtOp=structlettrunc_f32_s(x:int32)=ifInt32.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf>=-.Int32.(to_floatmin_int)||xf<Int32.(to_floatmin_int))theneval_error`Integer_overflowelseInt32.of_floatxflettrunc_f32_u(x:int32)=ifInt32.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf>=-.Int32.(to_floatmin_int)*.2.0||xf<=-1.0)theneval_error`Integer_overflowelseInt32.of_floatxflettrunc_f64_s(x:int64)=ifInt64.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)||xf<Int64.(to_floatmin_int))theneval_error`Integer_overflowelseInt32.of_floatxflettrunc_f64_u(x:int64)=ifInt64.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0||xf<=-1.0)theneval_error`Integer_overflowelseInt32.of_floatxflettrunc_sat_f32_sx=ifInt32.Infix.(x<>x)then0lelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf<Int32.(to_floatmin_int))thenInt32.min_intelseifFloat.Infix.(xf>=-.Int32.(to_floatmin_int))thenInt32.max_intelseInt32.of_floatxflettrunc_sat_f32_ux=ifInt32.Infix.(x<>x)then0lelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf<=-1.0)then0lelseifFloat.Infix.(xf>=-.Int32.(to_floatmin_int)*.2.0)then-1lelseInt32.of_floatxflettrunc_sat_f64_sx=ifInt64.Infix.(x<>x)then0lelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf<Int64.(to_floatmin_int))thenInt32.min_intelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt32.max_intelseInt32.of_floatxflettrunc_sat_f64_ux=ifInt64.Infix.(x<>x)then0lelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf<=-1.0)then0lelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0)then-1lelseInt32.of_floatxfletcvtopopv=letop'=`Cvtopopinmatchopwith|Ty.Cvtop.WrapI64->bitv_of_int32(Int64.to_int32(int64_of_bitv1op'v))|TruncSF32->bitv_of_int32(trunc_f32_s(of_fp321op'v))|TruncUF32->bitv_of_int32(trunc_f32_u(of_fp321op'v))|TruncSF64->bitv_of_int32(trunc_f64_s(of_fp641op'v))|TruncUF64->bitv_of_int32(trunc_f64_u(of_fp641op'v))|Trunc_sat_f32_s->bitv_of_int32(trunc_sat_f32_s(of_fp321op'v))|Trunc_sat_f32_u->bitv_of_int32(trunc_sat_f32_u(of_fp321op'v))|Trunc_sat_f64_s->bitv_of_int32(trunc_sat_f64_s(of_fp641op'v))|Trunc_sat_f64_u->bitv_of_int32(trunc_sat_f64_u(of_fp641op'v))|Reinterpret_float->bitv_of_int32(of_fp321op'v)|Sign_extendn->to_bitv(Bitvector.sign_extendn(of_bitv1op'v))|Zero_extendn->to_bitv(Bitvector.zero_extendn(of_bitv1op'v))|OfBool->v(* v is already a number here *)|ToBool|_->eval_error(`Unsupported_operator(op',Ty_bitv32))endmoduleI64CvtOp=structletextend_i32_u(x:int32)=Int64.(logand(of_int32x)0x0000_0000_ffff_ffffL)lettrunc_f32_s(x:int32)=ifInt32.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)||xf<Int64.(to_floatmin_int))theneval_error`Integer_overflowelseInt64.of_floatxflettrunc_f32_u(x:int32)=ifInt32.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0||xf<=-1.0)theneval_error`Integer_overflowelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.(logxor(of_float(xf-.0x1p63))min_int)elseInt64.of_floatxflettrunc_f64_s(x:int64)=ifInt64.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)||xf<Int64.(to_floatmin_int))theneval_error`Integer_overflowelseInt64.of_floatxflettrunc_f64_u(x:int64)=ifInt64.Infix.(x<>x)theneval_error`Conversion_to_integerelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0||xf<=-1.0)theneval_error`Integer_overflowelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.(logxor(of_float(xf-.0x1p63))min_int)elseInt64.of_floatxflettrunc_sat_f32_s(x:int32)=ifInt32.Infix.(x<>x)then0Lelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf<Int64.(to_floatmin_int))thenInt64.min_intelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.max_intelseInt64.of_floatxflettrunc_sat_f32_u(x:int32)=ifInt32.Infix.(x<>x)then0Lelseletxf=Int32.float_of_bitsxinifFloat.Infix.(xf<=-1.0)then0LelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0)then-1LelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.(logxor(of_float(xf-.0x1p63))min_int)elseInt64.of_floatxflettrunc_sat_f64_s(x:int64)=ifInt64.Infix.(x<>x)then0Lelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf<Int64.(to_floatmin_int))thenInt64.min_intelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.max_intelseInt64.of_floatxflettrunc_sat_f64_u(x:int64)=ifInt64.Infix.(x<>x)then0Lelseletxf=Int64.float_of_bitsxinifFloat.Infix.(xf<=-1.0)then0LelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int)*.2.0)then-1LelseifFloat.Infix.(xf>=-.Int64.(to_floatmin_int))thenInt64.(logxor(of_float(xf-.0x1p63))min_int)elseInt64.of_floatxfletcvtop(op:Ty.Cvtop.t)(v:Value.t):Value.t=letop'=`Cvtopopinmatchopwith|Sign_extendn->to_bitv(Bitvector.sign_extendn(of_bitv1op'v))|Zero_extendn->to_bitv(Bitvector.zero_extendn(of_bitv1op'v))|TruncSF32->bitv_of_int64(trunc_f32_s(of_fp321op'v))|TruncUF32->bitv_of_int64(trunc_f32_u(of_fp321op'v))|TruncSF64->bitv_of_int64(trunc_f64_s(of_fp641op'v))|TruncUF64->bitv_of_int64(trunc_f64_u(of_fp641op'v))|Trunc_sat_f32_s->bitv_of_int64(trunc_sat_f32_s(of_fp321op'v))|Trunc_sat_f32_u->bitv_of_int64(trunc_sat_f32_u(of_fp321op'v))|Trunc_sat_f64_s->bitv_of_int64(trunc_sat_f64_s(of_fp641op'v))|Trunc_sat_f64_u->bitv_of_int64(trunc_sat_f64_u(of_fp641op'v))|Reinterpret_float->bitv_of_int64(of_fp641op'v)|WrapI64->type_error1v(Ty_bitv64)op'"Cannot wrapI64 on an I64"|ToBool|OfBool|_->eval_error(`Unsupported_operator(op',Ty_bitv64))endmoduleF32CvtOp=structletdemote_f64x=letxf=Int64.float_of_bitsxinifFloat.Infix.(xf=xf)thenInt32.bits_of_floatxfelseletnan64bits=xinletsign_field=Int64.(shift_left(shift_right_logicalnan64bits63)31)inletsignificand_field=Int64.(shift_right_logical(shift_leftnan64bits12)41)inletfields=Int64.logorsign_fieldsignificand_fieldinInt32.logor0x7fc0_0000l(Int64.to_int32fields)letconvert_i32_sx=Int32.bits_of_float(Int32.to_floatx)letconvert_i32_ux=Int32.bits_of_floatInt32.(Int32.Infix.(ifx>=0lthento_floatxelseto_float(logor(shift_right_logicalx1)(logandx1l))*.2.0))letconvert_i64_sx=Int32.bits_of_floatInt64.(Int64.Infix.(ifabsx<0x10_0000_0000_0000Lthento_floatxelseletr=iflogandx0xfffL=0Lthen0Lelse1Linto_float(logor(shift_rightx12)r)*.0x1p12))letconvert_i64_ux=Int32.bits_of_floatInt64.(Int64.Infix.(ifI64.lt_ux0x10_0000_0000_0000Lthento_floatxelseletr=iflogandx0xfffL=0Lthen0Lelse1Linto_float(logor(shift_right_logicalx12)r)*.0x1p12))letcvtop(op:Ty.Cvtop.t)(v:Value.t):Value.t=letop'=`Cvtopopinmatchopwith|DemoteF64->to_fp32(demote_f64(of_fp641op'v))|ConvertSI32->to_fp32(convert_i32_s(int32_of_bitv1op'v))|ConvertUI32->to_fp32(convert_i32_u(int32_of_bitv1op'v))|ConvertSI64->to_fp32(convert_i64_s(int64_of_bitv1op'v))|ConvertUI64->to_fp32(convert_i64_u(int64_of_bitv1op'v))|Reinterpret_int->to_fp32(int32_of_bitv1op'v)|PromoteF32->type_error1v(Ty_fp32)op'"F64 must promote F32"|ToString|OfString|_->eval_error(`Unsupported_operator(op',Ty_fp32))endmoduleF64CvtOp=structletpromote_f32x=letxf=Int32.float_of_bitsxinifFloat.Infix.(xf=xf)thenInt64.bits_of_floatxfelseletnan32bits=I64CvtOp.extend_i32_uxinletsign_field=Int64.(shift_left(shift_right_logicalnan32bits31)63)inletsignificand_field=Int64.(shift_right_logical(shift_leftnan32bits41)12)inletfields=Int64.logorsign_fieldsignificand_fieldinInt64.logor0x7ff8_0000_0000_0000Lfieldsletconvert_i32_sx=Int64.bits_of_float(Int32.to_floatx)(*
* Unlike the other convert_u functions, the high half of the i32 range is
* within the range where f32 can represent odd numbers, so we can't do the
* shift. Instead, we can use int64 signed arithmetic.
*)letconvert_i32_ux=Int64.bits_of_floatInt64.(to_float(logand(of_int32x)0x0000_0000_ffff_ffffL))letconvert_i64_sx=Int64.bits_of_float(Int64.to_floatx)(*
* Values in the low half of the int64 range can be converted with a signed
* conversion. The high half is beyond the range where f64 can represent odd
* numbers, so we can shift the value right, adjust the least significant
* bit to round correctly, do a conversion, and then scale it back up.
*)letconvert_i64_u(x:int64)=Int64.bits_of_floatInt64.(Int64.Infix.(ifx>=0Lthento_floatxelseto_float(logor(shift_right_logicalx1)(logandx1L))*.2.0))letcvtop(op:Ty.Cvtop.t)v:Value.t=letop'=`Cvtopopinmatchopwith|PromoteF32->to_fp64(promote_f32(of_fp321op'v))|ConvertSI32->to_fp64(convert_i32_s(int32_of_bitv1op'v))|ConvertUI32->to_fp64(convert_i32_u(int32_of_bitv1op'v))|ConvertSI64->to_fp64(convert_i64_s(int64_of_bitv1op'v))|ConvertUI64->to_fp64(convert_i64_u(int64_of_bitv1op'v))|Reinterpret_int->to_fp64(int64_of_bitv1op'v)|DemoteF64->type_error1v(Ty_fp64)op'"F32 must demote a F64"|ToString|OfString|_->eval_error(`Unsupported_operator(op',Ty_fp64))end(* Dispatch *)letopintrealboolstrlstbvf32f64tyop=matchtywith|Ty.Ty_int->intop|Ty_real->realop|Ty_bool->boolop|Ty_str->strop|Ty_list->lstop|Ty_bitv_->bvop|Ty_fp32->f32op|Ty_fp64->f64op|Ty_fp_|Ty_app|Ty_unit|Ty_none|Ty_regexp|Ty_roundingMode->eval_error(`Unsupported_theoryty)[@@inline]letunop=opInt.unopReal.unopBool.unopStr.unopLst.unopBitv.unopF32.unopF64.unopletbinop=opInt.binopReal.binopBool.binopStr.binopLst.binopBitv.binopF32.binopF64.binoplettriop=function|Ty.Ty_bool->Bool.triop|Ty_str->Str.triop|Ty_list->Lst.triop|ty->eval_error(`Unsupported_theoryty)letrelop=function|Ty.Ty_int->Int.relop|Ty_real->Real.relop|Ty_bool->Bool.relop|Ty_str->Str.relop|Ty_bitv_->Bitv.relop|Ty_fp32->F32.relop|Ty_fp64->F64.relop|ty->eval_error(`Unsupported_theoryty)letcvtop=function|Ty.Ty_int->Int.cvtop|Ty_real->Real.cvtop|Ty_str->Str.cvtop|Ty_bitv32->I32CvtOp.cvtop|Ty_bitv64->I64CvtOp.cvtop|Ty_fp32->F32CvtOp.cvtop|Ty_fp64->F64CvtOp.cvtop|ty->eval_error(`Unsupported_theoryty)letnaryop=function|Ty.Ty_bool->Bool.naryop|Ty_str->Str.naryop|Ty_list->Lst.naryop|ty->eval_error(`Unsupported_theoryty)