123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)letbyte_size=(Basic_types.Constants.bytesize:>int)typesize=inttype'ainterval='aInterval.t={lo:'a;hi:'a}typeendianness=Machine.endianness=LittleEndian|BigEndianletpp_endiannesssppf=function|LittleEndian->Format.pp_print_charppf'L'|BigEndian->Format.pp_print_charppf'B'typeunary=Uandbinary=Btype_operator=|Not:unaryoperator|Sext:size->unaryoperator|Uext:size->unaryoperator|Restrict:intinterval->unaryoperator|Plus:binaryoperator|Minus:_operator|Mul:binaryoperator|Udiv:binaryoperator(* Corresponds to *)|Urem:binaryoperator(* the truncated division *)|Sdiv:binaryoperator(* of C99 and most *)|Srem:binaryoperator(* processors *)|Or:binaryoperator|And:binaryoperator|Xor:binaryoperator|Concat:binaryoperator|Lsl:binaryoperator|Lsr:binaryoperator|Asr:binaryoperator|Rol:binaryoperator|Ror:binaryoperator|Eq:binaryoperator|Diff:binaryoperator|Ule:binaryoperator|Ult:binaryoperator|Uge:binaryoperator|Ugt:binaryoperator|Sle:binaryoperator|Slt:binaryoperator|Sge:binaryoperator|Sgt:binaryoperatormoduleOp=structtype'at='aoperatorexternalto_int:'at->int="%identity"letequal:typeab.at->bt->bool=funtt'->match(t,t')with|((Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt),(Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt))->to_intt=to_intt'|Sextn,Sextn'|Uextn,Uextn'->n=n'|Restrict{hi;lo},Restrict{hi=hi';lo=lo'}->hi=hi'&&lo=lo'|((Not|Sext_|Uext_|Restrict_|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt),(Not|Sext_|Uext_|Restrict_|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt))->falseletcompare:typeab.at->bt->int=funtt'->match(t,t')with|((Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt),(Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt))->to_intt-to_intt'|Sextn,Sextn'|Uextn,Uextn'->n-n'|Restrict{hi;lo},Restrict{hi=hi';lo=lo'}->letd=hi-hi'inifd=0thenlo-lo'elsed|((Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt),Sext_)->-1|(Sext_,(Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt))->1|((Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt|Sext_),Uext_)->-1|(Uext_,(Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt|Sext_))->1|((Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt|Sext_|Uext_),Restrict_)->-1|(Restrict_,(Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt|Sext_|Uext_))->1lethash:typea.at->int=funt->matchtwith|Sext_|Uext_|Restrict_->Hashtbl.hasht|Not|Plus|Minus|Mul|Udiv|Urem|Sdiv|Srem|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt->to_inttletpp:typea.Format.formatter->aoperator->unit=funppf->function|Minus->Format.pp_print_charppf'-'|Not->Format.pp_print_charppf'!'|Sextn->Format.fprintfppf"sext +%d"n|Uextn->Format.fprintfppf"uext +%d"n|Restrict{lo;hi}->iflo=hithenFormat.fprintfppf"select %d"loelseFormat.fprintfppf"select <%d .. %d>"hilo|Plus->Format.pp_print_charppf'+'|Mul->Format.pp_print_charppf'*'|Udiv->Format.pp_print_stringppf"udiv"|Sdiv->Format.pp_print_stringppf"sdiv"|Urem->Format.pp_print_stringppf"urem"|Srem->Format.pp_print_stringppf"srem"|Or->Format.pp_print_stringppf"or"|And->Format.pp_print_stringppf"and"|Xor->Format.pp_print_stringppf"xor"|Concat->Format.pp_print_stringppf"::"|Lsl->Format.pp_print_stringppf"lsl"|Lsr->Format.pp_print_stringppf"lsr"|Asr->Format.pp_print_stringppf"asr"|Rol->Format.pp_print_stringppf"rol"|Ror->Format.pp_print_stringppf"ror"|Eq->Format.pp_print_charppf'='|Diff->Format.pp_print_stringppf"<>"|Ule->Format.pp_print_stringppf"ule"|Ult->Format.pp_print_stringppf"ult"|Uge->Format.pp_print_stringppf"uge"|Ugt->Format.pp_print_stringppf"ugt"|Sle->Format.pp_print_stringppf"sle"|Slt->Format.pp_print_stringppf"slt"|Sge->Format.pp_print_stringppf"sge"|Sgt->Format.pp_print_stringppf"sgt"endtype(_,'a,'b)t=|Var:{hash:int;size:size;name:string;label:'a;}->([<`Var|`Loc|`Exp],'a,_)t|Load:{hash:int;len:size;dir:endianness;mutableaddr:([`Exp],'a,'b)t;label:'b;}->([<`Mem|`Loc|`Exp],'a,'b)t|Cst:Bitvector.t->([<`Cst|`Exp],_,_)t|Unary:{hash:int;size:size;f:unaryoperator;mutablex:([`Exp],'a,'b)t;}->([<`Unary|`Exp],'a,'b)t|Binary:{hash:int;size:size;f:binaryoperator;mutablex:([`Exp],'a,'b)t;mutabley:([`Exp],'a,'b)t;}->([<`Binary|`Exp],'a,'b)t|Ite:{hash:int;size:size;mutablec:([`Exp],'a,'b)t;mutablet:([`Exp],'a,'b)t;mutablee:([`Exp],'a,'b)t;}->([<`Ite|`Exp],'a,'b)tletrecpp:typek.Format.formatter->(k,'a,'b)t->unit=funppf->function|Var{name;size;_}->Format.fprintfppf"%s<%d>"namesize|Load{len;dir;addr;_}->Format.fprintfppf"%@[%a]%d%a"ppaddrlenpp_endiannesssdir|Cstbv->Bitvector.pp_hex_or_binppfbv|Unary{f;x;_}->Format.fprintfppf"@[(%a %a)@]"Op.ppfppx|Binary{f;x;y;_}->Format.fprintfppf"@[(%a %a %a)@]"Op.ppfppxppy|Ite{c;t;e;_}->Format.fprintfppf"@[(%a ? %a : %a)@]"ppcpptppeletto_stringt=Format.asprintf"%a"pptletabortt=raise(Invalid_argument(to_stringt))lethash:typek.(k,_,_)t->int=function|Cstbv->Bitvector.hashbv|Load{hash;_}->hash|Var{hash;_}->hash|Unary{hash;_}->hash|Binary{hash;_}->hash|Ite{hash;_}->hashletsizeof:typek.(k,_,_)t->int=function|Cstbv->Bitvector.size_ofbv|Load{len;_}->byte_size*len|Var{size;_}->size|Unary{size;_}->size|Binary{size;_}->size|Ite{size;_}->sizetype('a,'b)any=Term:(_,'a,'b)t->('a,'b)any[@@unboxed]letto_expt=matchTermtwith|Term(Var_asv)->v|Term(Load_asl)->l|Term(Cst_asc)->c|Term(Unary_asu)->u|Term(Binary_asb)->b|Term(Ite_asi)->iletto_vart=matchTermtwithTerm(Var_asv)->Somev|_->Noneletto_var_exnt=matchTermtwithTerm(Var_asv)->v|_->aborttletto_loct=matchTermtwith|Term(Var_asv)->Somev|Term(Load_asl)->Somel|_->Noneletto_loc_exnt=matchTermtwith|Term(Var_asv)->v|Term(Load_asl)->l|_->aborttletto_memt=matchTermtwithTerm(Load_asl)->Somel|_->Noneletto_mem_exnt=matchTermtwithTerm(Load_asl)->l|_->aborttletto_cstt=matchTermtwithTerm(Cst_asc)->Somec|_->Noneletto_cst_exnt=matchTermtwithTerm(Cst_asc)->c|_->aborttmoduleBv=structincludeBitvectorletunaryfx=matchfwith|Not->lognotx|Minus->negx|Uextn->extendx(size_ofx+n)|Sextn->extend_signedx(size_ofx+n)|Restrict{hi;lo}->extract~hi~loxletbinaryfxy=letn=size_ofxiniff<>Concat&&n<>size_ofythenabort(Binary{f;x=Cstx;y=Csty;size=n;hash=0})elsematchfwith|Plus->addxy|Minus->subxy|Mul->mulxy|Udiv->udivxy|Urem->uremxy|Sdiv->sdivxy|Srem->sremxy|Or->logorxy|And->logandxy|Xor->logxorxy|Eq->of_bool(equalxy)|Diff->of_bool(diffxy)|Ule->of_bool(ulexy)|Ult->of_bool(ultxy)|Uge->of_bool(ugexy)|Ugt->of_bool(ugtxy)|Sle->of_bool(slexy)|Slt->of_bool(sltxy)|Sge->of_bool(sgexy)|Sgt->of_bool(sgtxy)|Lsl->shift_leftx(to_uinty)|Lsr->shift_rightx(to_uinty)|Asr->shift_right_signedx(to_uinty)|Rol->rotate_leftx(to_uinty)|Ror->rotate_rightx(to_uinty)|Concat->appendxyendmoduletypeS=sigtypeaandbtypenonrecsize=sizetypenonrec'ainterval='ainterval={lo:'a;hi:'a}typenonrecendianness=endianness=LittleEndian|BigEndiantype'aop='aoperator=|Not:unaryop|Sext:size->unaryop|Uext:size->unaryop|Restrict:intinterval->unaryop|Plus:binaryop|Minus:_op|Mul:binaryop|Udiv:binaryop(* Corresponds to *)|Urem:binaryop(* the truncated division *)|Sdiv:binaryop(* of C99 and most *)|Srem:binaryop(* processors *)|Or:binaryop|And:binaryop|Xor:binaryop|Concat:binaryop|Lsl:binaryop|Lsr:binaryop|Asr:binaryop|Rol:binaryop|Ror:binaryop|Eq:binaryop|Diff:binaryop|Ule:binaryop|Ult:binaryop|Uge:binaryop|Ugt:binaryop|Sle:binaryop|Slt:binaryop|Sge:binaryop|Sgt:binaryoptype('k,'a,'b)term=('k,'a,'b)t=private|Var:{hash:int;size:size;name:string;label:'a;}->([<`Var|`Loc|`Exp],'a,_)term|Load:{hash:int;len:size;dir:endianness;mutableaddr:([`Exp],'a,'b)term;label:'b;}->([<`Mem|`Loc|`Exp],'a,'b)term|Cst:Bitvector.t->([<`Cst|`Exp],_,_)term|Unary:{hash:int;size:size;f:unaryoperator;mutablex:([`Exp],'a,'b)term;}->([<`Unary|`Exp],'a,'b)term|Binary:{hash:int;size:size;f:binaryoperator;mutablex:([`Exp],'a,'b)term;mutabley:([`Exp],'a,'b)term;}->([<`Binary|`Exp],'a,'b)term|Ite:{hash:int;size:size;mutablec:([`Exp],'a,'b)term;mutablet:([`Exp],'a,'b)term;mutablee:([`Exp],'a,'b)term;}->([<`Ite|`Exp],'a,'b)termtypet=([`Exp],a,b)term(** {2 Smart constructors} *)valvar:string->size->a->t(** [var name bitsize label] *)valload:size->endianness->t->b->t(** [load nbytes endianness addr label] *)valconstant:Bitvector.t->t(** [constant bv] creates a constant expression from the bitvector [bv]. *)valunary:unaryop->t->t(** [unary f x] creates a unary application of [f] on [x]. *)valbinary:binaryop->t->t->t(** [binary f x y] creates a binary application of [f] on [x] and [y]. *)valite:t->t->t->t(** [ite c t e] creates an if-then-else expression [c] ? [t] : [e]. *)valuminus:t->tvaladd:t->t->tvalsub:t->t->tvalmul:t->t->tvalsrem:t->t->tvalurem:t->t->tvaludiv:t->t->tvalsdiv:t->t->tvalappend:t->t->tvalequal:t->t->tvaldiff:t->t->tvalule:t->t->tvaluge:t->t->tvalult:t->t->tvalugt:t->t->tvalsle:t->t->tvalsge:t->t->tvalslt:t->t->tvalsgt:t->t->tvallogand:t->t->tvallogor:t->t->tvallognot:t->tvallogxor:t->t->tvalshift_left:t->t->tvalshift_right:t->t->tvalshift_right_signed:t->t->t(** [shift_(left|right) e q] shifts expression [e] by quantity [q], padding
with zeroes *)valrotate_left:t->t->tvalrotate_right:t->t->t(** [rotate_(left|right) e q] rotates expression [e] by quantity [q] *)valsext:size->t->t(** [sext sz e] performs a signed extension of expression [e] to size [sz] *)valuext:size->t->t(** [uext sz e] performs an unsigned extension expression [e] to size [sz] *)valrestrict:lo:int->hi:int->t->t(** [restrict lo hi e] creates [Dba.ExprUnary(Restrict(lo, hi), e)] if
[hi >= lo && lo >=0] . *)valbit_restrict:int->t->t(** [bit_restrict o e] is [restrict o o e] *)valbyte_swap:t->t(** [byte_swap e] reverses the byte order of the expression [e] *)(** {3 Specific constants}*)valzeros:int->t(** [zeros n] creates a constant expression of value 0 with length [n] *)valones:int->t(** [ones n] creates a constant expression of value 1 with length [n]. I.e.;
it has (n - 1) zeros in binary. *)valone:tvalzero:tvaladdi:t->int->tvaladdz:t->Z.t->t(** {2 Utils} *)valhash:t->int(** [hash t] returns the hash of [t] in constant time. *)valis_equal:t->t->boolvalcompare:t->t->intvalsizeof:t->size(** [sizeof t] returns the bit size of [t] in constant time. *)valmap:(string->int->'a->t)->(int->Machine.endianness->t->'b->t)->(_,'a,'b)term->t(** {2 Raw constructors} *)val_unary:unaryop->t->t(** [_unary f x] creates a unary application of [f] on [x]. *)val_binary:binaryop->t->t->t(** [_binary f x y] creates a binary application of [f] on [x] and [y]. *)val_ite:t->t->t->t(** [_ite c t e] creates an if-then-else expression [c] ? [t] : [e]. *)endmoduleMake(A:Sigs.HASHABLE)(B:Sigs.HASHABLE):Swithtypea:=A.tandtypeb:=B.t=structtypenonrecsize=sizetypenonrec'ainterval='ainterval={lo:'a;hi:'a}typenonrecendianness=endianness=LittleEndian|BigEndiantype'aop='aoperator=|Not:unaryop|Sext:size->unaryop|Uext:size->unaryop|Restrict:intinterval->unaryop|Plus:binaryop|Minus:_op|Mul:binaryop|Udiv:binaryop(* Corresponds to *)|Urem:binaryop(* the truncated division *)|Sdiv:binaryop(* of C99 and most *)|Srem:binaryop(* processors *)|Or:binaryop|And:binaryop|Xor:binaryop|Concat:binaryop|Lsl:binaryop|Lsr:binaryop|Asr:binaryop|Rol:binaryop|Ror:binaryop|Eq:binaryop|Diff:binaryop|Ule:binaryop|Ult:binaryop|Uge:binaryop|Ugt:binaryop|Sle:binaryop|Slt:binaryop|Sge:binaryop|Sgt:binaryoptype('k,'a,'b)term=('k,'a,'b)t=|Var:{hash:int;size:size;name:string;label:'a;}->([<`Var|`Loc|`Exp],'a,_)term|Load:{hash:int;len:size;dir:endianness;mutableaddr:([`Exp],'a,'b)term;label:'b;}->([<`Mem|`Loc|`Exp],'a,'b)term|Cst:Bitvector.t->([<`Cst|`Exp],_,_)term|Unary:{hash:int;size:size;f:unaryoperator;mutablex:([`Exp],'a,'b)term;}->([<`Unary|`Exp],'a,'b)term|Binary:{hash:int;size:size;f:binaryoperator;mutablex:([`Exp],'a,'b)term;mutabley:([`Exp],'a,'b)term;}->([<`Binary|`Exp],'a,'b)term|Ite:{hash:int;size:size;mutablec:([`Exp],'a,'b)term;mutablet:([`Exp],'a,'b)term;mutablee:([`Exp],'a,'b)term;}->([<`Ite|`Exp],'a,'b)termtypet=([`Exp],A.t,B.t)termlethash=hashexternal(<!):'a->'a->bool="cstubs_hashcons_older"[@@noalloc]letset_load_addr:([`Mem],A.t,B.t)term->t->unit=fun(Loadr)e->r.addr<-eandset_unary_x:([`Unary],A.t,B.t)term->t->unit=fun(Unaryr)e->r.x<-eandset_binary_x:([`Binary],A.t,B.t)term->t->unit=fun(Binaryr)e->r.x<-eandset_binary_y:([`Binary],A.t,B.t)term->t->unit=fun(Binaryr)e->r.y<-eandset_ite_c:([`Ite],A.t,B.t)term->t->unit=fun(Iter)e->r.c<-eandset_ite_t:([`Ite],A.t,B.t)term->t->unit=fun(Iter)e->r.t<-eandset_ite_e:([`Ite],A.t,B.t)term->t->unit=fun(Iter)e->r.e<-eletis_equal=letrecis_equal_matchtt'=match(t,t')with|Cstbv,Cstbv'->Bv.equalbvbv'|Varr,Varr'->r.hash=r'.hash&&r.size=r'.size&&String.equalr.namer'.name&&A.equalr.labelr'.label|(Loadrasl),(Loadr'asl')->r.hash=r'.hash&&r.len=r'.len&&r.dir=r'.dir&&is_equal_unifyr.addrr'.addrset_load_addrll'&&B.equalr.labelr'.label|(Unaryrasu),(Unaryr'asu')->r.hash=r'.hash&&r.f=r'.f&&is_equal_unifyr.xr'.xset_unary_xuu'|(Binaryrasb),(Binaryr'asb')->r.hash=r'.hash&&r.f=r'.f&&is_equal_unifyr.xr'.xset_binary_xbb'&&is_equal_unifyr.yr'.yset_binary_ybb'|(Iterasi),(Iter'asi')->r.hash=r'.hash&&is_equal_unifyr.cr'.cset_ite_cii'&&is_equal_unifyr.tr'.tset_ite_tii'&&is_equal_unifyr.er'.eset_ite_eii'|_,_->falseandis_equal_unify:typea.t->t->((a,A.t,B.t)term->t->unit)->(a,A.t,B.t)term->(a,A.t,B.t)term->bool=funtt'fpp'->t==t'||is_equal_matchtt'&&(ift<!t'thenfp'telsefpt';true)infuntt'->t==t'||is_equal_matchtt'letcompare=letreccompare_matchtt'=match(t,t')with|Cstbv,Cstbv'->Bv.comparebvbv'|Cst_,Load_->-1|Cst_,Unary_->-1|Cst_,Binary_->-1|Cst_,Ite_->-1|Cst_,Var_->-1|Load_,Cst_->1|(Loadrasl),(Loadr'asl')->letd=r.len-r'.leninifd<>0thendelseletd=comparer.dirr'.dirinifd<>0thendelseletd=compare_unifyr.addrr'.addrset_load_addrll'inifd<>0thendelseB.comparer.labelr'.label|Load_,Unary_->-1|Load_,Binary_->-1|Load_,Ite_->-1|Load_,Var_->-1|Unary_,Cst_->1|Unary_,Load_->1|(Unaryrasu),(Unaryr'asu')->letd=Op.comparer.fr'.finifd<>0thendelseletd=r.size-r'.sizeinifd<>0thendelsecompare_unifyr.xr'.xset_unary_xuu'|Unary_,Binary_->-1|Unary_,Ite_->-1|Unary_,Var_->-1|Binary_,Cst_->1|Binary_,Load_->1|Binary_,Unary_->1|(Binaryrasb),(Binaryr'asb')->letd=Op.comparer.fr'.finifd<>0thendelseletd=r.size-r'.sizeinifd<>0thendelseletd=r.hash-r'.hashinifd<>0thendelseletd=compare_unifyr.xr'.xset_binary_xbb'inifd<>0thendelsecompare_unifyr.yr'.yset_binary_ybb'|Binary_,Ite_->-1|Binary_,Var_->-1|Ite_,Cst_->1|Ite_,Load_->1|Ite_,Unary_->1|Ite_,Binary_->1|(Iterasi),(Iter'asi')->letd=r.size-r'.sizeinifd<>0thendelseletd=r.hash-r'.hashinifd<>0thendelseletd=compare_unifyr.cr'.cset_ite_cii'inifd<>0thendelseletd=compare_unifyr.tr'.tset_ite_tii'inifd<>0thendelsecompare_unifyr.er'.eset_ite_eii'|Ite_,Var_->-1|Var_,Cst_->1|Var_,Load_->1|Var_,Unary_->1|Var_,Binary_->1|Var_,Ite_->1|Varr,Varr'->letd=r.size-r'.sizeinifd<>0thendelseletd=String.comparer.namer'.nameinifd<>0thendelseA.comparer.labelr'.labelandcompare_unify:typea.t->t->((a,A.t,B.t)term->t->unit)->(a,A.t,B.t)term->(a,A.t,B.t)term->int=funtt'fpp'->ift==t'then0elseletd=compare_matchtt'inifd=0thenift<!t'thenfp'telsefpt';dinfuntt'->ift==t'then0elsecompare_matchtt'letis_trivial_lognotxy=match(x,y)with|Unary{f=Not;x;_},y|y,Unary{f=Not;x;_}->comparexy=0|Binary{f=Eq;x=a;y=b;_},Binary{f=Diff;x=c;y=d;_}|Binary{f=Diff;x=a;y=b;_},Binary{f=Eq;x=c;y=d;_}|Binary{f=Ule;x=a;y=b;_},Binary{f=Ugt;x=c;y=d;_}|Binary{f=Ugt;x=a;y=b;_},Binary{f=Ule;x=c;y=d;_}|Binary{f=Uge;x=a;y=b;_},Binary{f=Ult;x=c;y=d;_}|Binary{f=Ult;x=a;y=b;_},Binary{f=Uge;x=c;y=d;_}|Binary{f=Sle;x=a;y=b;_},Binary{f=Sgt;x=c;y=d;_}|Binary{f=Sgt;x=a;y=b;_},Binary{f=Sle;x=c;y=d;_}|Binary{f=Sge;x=a;y=b;_},Binary{f=Slt;x=c;y=d;_}|Binary{f=Slt;x=a;y=b;_},Binary{f=Sge;x=c;y=d;_}->compareac=0&&comparebd=0|_->falseletsizeof=sizeofletvarnamesizelabel=Var{name;size;label;hash=Hash.(return@@fold_int(fold_string(seed0x48206212)name)size);}letloadlendiraddrlabel=Load{len;dir;addr;label;hash=Hash.(return@@fold_int(fold_int(seed0x64dba348)len)(hashaddr));}letconstantbv=Cstbvletmk_unaryfx=letsize=matchfwith|Uextn|Sextn->n+sizeofx|Restrict{lo;hi}->hi-lo+1|Not|Minus->sizeofxinUnary{f;x;size;hash=Hash.(return@@fold_int(fold_int(seed0xec9576a)(Hashtbl.hashf))(hashx));}letmk_binaryfxy=letsize=matchfwith|Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt->1|Concat->sizeofx+sizeofy|_->sizeofxinBinary{f;x;y;size;hash=Hash.(return@@fold_int(fold_int(fold_int(seed0x4b8498a0)(Hashtbl.hashf))(hashx))(hashy));}letmk_itecte=Ite{c;t;e;size=sizeoft;hash=Hash.(return@@fold_int(fold_int(fold_int(seed0x4bfe92b2)(hashc))(hasht))(hashe));}letzerosn=Cst(Bv.zerosn)letonesn=Cst(Bv.onesn)letone=CstBv.oneletzero=CstBv.zeroletrecunaryfx=match(f,x)with(* safety pattern guard *)(* TODO: move outside of the rec pattern if the rewriter is trusted *)|(Uextn,_|Sextn,_)whenn<0->abort@@mk_unaryfx|Restrict{lo;hi},twhenlo<0||hi<lo||sizeoft<=hi->abort@@mk_unaryfx(* constant folding *)|_,Cstbv->constant(Bv.unaryfbv)(* identity *)|Sext0,x|Uext0,x->x|Restrict{lo=0;hi},xwhenhi=sizeofx-1->x|Not,Unary{f=Not;x;_}->x|Minus,Unary{f=Minus;x;_}->x|Minus,xwhensizeofx=1->x(* inversion *)|Minus,Binary{f=Minus;x;y;size;_}->binaryMinusyxsize|Not,Binary{f=Eq;x;y;size;_}->binaryDiffxysize|Not,Binary{f=Diff;x;y;size;_}->binaryEqxysize|Not,Binary{f=Ule;x;y;size;_}->binaryUgtxysize|Not,Binary{f=Ult;x;y;size;_}->binaryUgexysize|Not,Binary{f=Uge;x;y;size;_}->binaryUltxysize|Not,Binary{f=Ugt;x;y;size;_}->binaryUlexysize|Not,Binary{f=Sle;x;y;size;_}->binarySgtxysize|Not,Binary{f=Slt;x;y;size;_}->binarySgexysize|Not,Binary{f=Sge;x;y;size;_}->binarySltxysize|Not,Binary{f=Sgt;x;y;size;_}->binarySlexysize(* TODO: more to come like de morgan's law, etc.. *)(* combining *)|Uextn,Unary{f=Uextp;x;_}|Sextn,Unary{f=Uextp;x;_}->unary(Uext(n+p))x|Sextn,Unary{f=Sextp;x;_}->unary(Sext(n+p))x|Restrict{lo;hi},Unary{f=Restrict{lo=lo';_};x;_}->unary(Restrict{lo=lo'+lo;hi=lo'+hi})x(* revert -- extract only inside the initial term t *)|Restrict{hi;_},Unary{f=Uext_;x;_}|Restrict{hi;_},Unary{f=Sext_;x;_}whenhi<sizeofx->unaryfx(* absorbing element -- extract only the inserted bits *)|Restrict{lo;hi},Unary{f=Uext_;x;_}whensizeofx<=lo->zeros(hi-lo+1)|Restrict{lo;hi},Unary{f=Sext_;x;_}whensizeofx<=lo->unary(Sext(hi-lo))(unary(Restrict{lo=sizeofx-1;hi=sizeofx-1})x)(* reorder -- extension on top *)|Restrict{lo;hi},Unary{f=Uext_;x;_}->unary(Uext(hi-sizeofx+1))(unary(Restrict{lo;hi=sizeofx-1})x)|Restrict{lo;hi},Unary{f=Sext_;x;_}->unary(Sext(hi-sizeofx+1))(unary(Restrict{lo;hi=sizeofx-1})x)(* absorbing element -- extract only the inserted bits *)|Restrict{lo;hi},Binary{f=Lsl;y=Cstbv;_}whenhi<Bv.to_uintbv->zeros(hi-lo+1)|Restrict{lo;hi},Binary{f=Lsr;x;y=Cstbv;_}whensizeofx-Bv.to_uintbv<=lo->zeros(hi-lo+1)|Restrict{lo;hi},Binary{f=Asr;x;y=Cstbv;_}whensizeofx-Bv.to_uintbv-1<=lo->unary(Sext(hi-lo))(unary(Restrict{lo=sizeofx-1;hi=sizeofx-1})x)(* combining -- extract is still inside the initial term t *)|Restrict{lo;hi},Binary{f=Lsl;x;y=Cstbv;_}whenBv.to_uintbv<=lo->unary(Restrict{lo=lo-Bv.to_uintbv;hi=hi-Bv.to_uintbv})x|Restrict{lo;hi},Binary{f=Lsr;x;y=Cstbv;_}|Restrict{lo;hi},Binary{f=Asr;x;y=Cstbv;_}whenhi+Bv.to_uintbv<sizeofx->unary(Restrict{lo=lo+Bv.to_uintbv;hi=hi+Bv.to_uintbv})x(* reorder -- extension on top *)|Restrict{lo;hi},Binary{f=Lsr;x;y=Cstbv;_}->unary(Uext(hi-sizeofx+Bv.to_uintbv+1))(unary(Restrict{lo=lo+Bv.to_uintbv;hi=sizeofx-1})x)|Restrict{lo;hi},Binary{f=Asr;x;y=Cstbv;_}->unary(Sext(hi-sizeofx+Bv.to_uintbv+1))(unary(Restrict{lo=lo+Bv.to_uintbv;hi=sizeofx-1})x)(* split concatenation *)|Restrict{hi;_},Binary{f=Concat;y;_}whenhi<sizeofy->unaryfy|Restrict{lo;hi},Binary{f=Concat;x;y;_}whensizeofy<=lo->unary(Restrict{lo=lo-sizeofy;hi=hi-sizeofy})x|(Restrict{hi;lo},Binary{f=Concat;x=Binary{f=Concat;_}asx;y;_})->letsz=sizeofyinbinaryConcat(unary(Restrict{hi=hi-sz;lo=0})x)(unary(Restrict{hi=sz-1;lo})y)(hi-sz+1)|Restrict{hi;lo},Binary{f=Concat;x=Cstbv;y;_}->letshift=sizeofyinbinaryConcat(constant(Bv.extract~hi:(hi-shift)~lo:0bv))(unary(Restrict{hi=shift-1;lo})x)(hi-shift+1)|Restrict{hi;lo},Binary{f=Concat;x;y=Cstbv;_}->letshift=Bv.size_ofbvinbinaryConcat(unary(Restrict{hi=hi-shift;lo=0})x)(constant(Bv.extract~hi:(shift-1)~lobv))(hi-shift+1)(* TODO: more to come when term is "splitable" -- eg. t land cst *)(* elimination *)|Restrict{hi;lo=0},Binary{f=And;x;y=Cstbv;_}whenletv=Bv.value_ofbvinlets=Z.numbitsvinhi<s&&s=Z.popcountv->unaryfx|(Restrict{hi;lo=0},Binary{f=(Plus|Minus|Mul|And|Or|Xor)asbop;x=(Unary{f=Uext_|Sext_;_}|Binary{f=Concat;_})asx;y=Cstbv;_;})->binarybop(unaryfx)(constant(Bv.extract~lo:0~hibv))(hi+1)|(Restrict{hi;lo=0},Binary{f=(Plus|Minus|Mul|And|Or|Xor)asbop;x=(Unary{f=Uext_|Sext_;_}|Binary{f=Concat;_})asx;y=(Unary{f=Uext_|Sext_;_}|Binary{f=Concat;_})asy;_;})->binarybop(unaryfx)(unaryfy)(hi+1)|(Restrict{hi;lo},Binary{f=(And|Or)asbop;x=(Unary{f=Uext_|Sext_;_}|Binary{f=Concat;_})asx;y=Cstbv;_;})->binarybop(unaryfx)(constant(Bv.extract~hi~lobv))(hi-lo+1)(* bit test *)|(Restrict{hi;lo}asf),Binary{f=And;x;y;_}whenhi=lo->binaryAnd(unaryfx)(unaryfy)1|(Restrict_asf),Unary{f=Not;x;_}->unaryNot(unaryfx)(* sign extraction *)|(Restrict{hi;lo},Binary{f=Minus;x=Unary{f=Sextn;x;_};y=Cstbv;size;_})whenhi=lo&&hi=size-1&&Z.numbits(Bv.value_ofbv)<size-n->binarySltx(constant(Bv.extract~hi:(size-n-1)~lo:0bv))(size-n)|(Restrict{hi;lo},Binary{f=Minus;x=Unary{f=Uextn;x;_};y=Cstbv;size;_})whenhi=lo&&hi=size-1&&Z.numbits(Bv.value_ofbv)<size-n->binaryUltx(constant(Bv.extract~hi:(size-n-1)~lo:0bv))(size-n)(* | ( Restrict { hi; lo },
Unary
{
f = Not;
x =
Binary
{
f = Minus;
x = Unary { f = Sext n; x; _ };
y = Cst bv;
size;
_;
};
_;
} )
when hi = lo && hi = size - 1 && Z.numbits (Bv.value_of bv) < size - n ->
binary Sge x
(constant (Bv.extract ~hi:(size - n - 1) ~lo:0 bv))
(size - n) *)(* parity *)(* | Restrict { hi = 0; lo = 0 }, Binary { f = Xor | Plus; x; y; _ } -> *)(* binary Xor (unary f x) (unary f y) 1 *)(* forward ite *)|f,Ite{c;t=Cstbv;e;_}->itec(constant(Bv.unaryfbv))(unaryfe)|f,Ite{c;t;e=Cstbv;_}->itec(unaryft)(constant(Bv.unaryfbv))(* default case *)|_,_->mk_unaryfxandbinaryfxysx=match(f,x,y)with(* safety pattern guard *)(* TODO: move outside of the rec pattern if the rewriter is trusted *)(* | _, _, _ when f <> Concat && sizeof x <> sizeof y -> *)(* abort @@ mk_binary f x y *)(* special boolean replacement *)|(Plus,_,_|Minus,_,_)whensx=1->binaryXorxysx(* constant folding *)|_,Cstx,Csty->constant(Bv.binaryfxy)|Plus,Binary{f=Plus;x=a;y=Cstb;_},Cstc->binaryPlusa(constant(Bv.binaryPlusbc))sx|Plus,Binary{f=Minus;x=a;y=Cstb;_},Cstc->binaryMinusa(constant(Bv.binaryMinusbc))sx|Minus,Binary{f=Plus;x=a;y=Cstb;_},Cstc->binaryPlusa(constant(Bv.binaryMinusbc))sx|Minus,Binary{f=Minus;x=a;y=Cstb;_},Cstc->binaryMinusa(constant(Bv.binaryPlusbc))sx|((Plus|Minus)asf),Binary{f=Minus;x=Csta;y=b;_},Cstc->binaryMinus(constant(Bv.binaryfac))bsx|Plus,a,CstbvwhenBv.is_negbv&¬(Bv.is_min_sbvbv)->binaryMinusa(constant(Bv.negbv))sx|Minus,a,CstbvwhenBv.is_negbv->binaryPlusa(constant(Bv.negbv))sx|Mul,Binary{f=Mul;x=a;y=Cstb;_},Cstc->binaryMula(constant(Bv.binaryMulbc))sx|Or,Binary{f=Or;x=a;y=Cstb;_},Cstc->binaryOra(constant(Bv.binaryOrbc))sx|And,Binary{f=And;x=a;y=Cstb;_},Cstc->binaryAnda(constant(Bv.binaryAndbc))sx|Xor,Binary{f=Xor;x=a;y=Cstb;_},Cstc->binaryXora(constant(Bv.binaryXorbc))sx|Lsl,Binary{f=Lsl;x=a;y=Cstb;_},Cstc->binaryLsla(constant(Bv.binaryPlusbc))sx|Lsr,Binary{f=Lsr;x=a;y=Cstb;_},Cstc->binaryLsra(constant(Bv.binaryPlusbc))sx|Asr,Binary{f=Asr;x=a;y=Cstb;_},Cstc->binaryAsra(constant(Bv.binaryPlusbc))sx|Rol,Binary{f=Rol;x=a;y=Cstb;_},Cstc->binaryRola(constant(Bv.binaryPlusbc))sx|Ror,Binary{f=Ror;x=a;y=Cstb;_},Cstc->binaryRora(constant(Bv.binaryPlusbc))sx|Concat,Cstbv,Binary{f=Concat;x=Cstbv';y;_}->letsz=Bv.size_ofbv'inbinaryConcat(constant(Bv.appendbvbv'))y(sx+sz)|Concat,Binary{f=Concat;x;y=Cstbv;_},Cstbv'->letsz=Bv.size_ofbvinbinaryConcatx(constant(Bv.appendbvbv'))(sx-sz)(* identity *)|Plus,x,Cstbv|Minus,x,Cstbv|Lsl,x,Cstbv|Lsr,x,Cstbv|Asr,x,Cstbv|Rol,x,Cstbv|Ror,x,Cstbv|Xor,x,Cstbv|Or,x,CstbvwhenBv.is_zerosbv->x|(Mul,x,Cstbv|Udiv,x,Cstbv|Sdiv,x,Cstbv)whenBv.is_onesbv->x|And,x,CstbvwhenBv.is_fillbv->x|(Rol,x,Cstbv|Ror,x,Cstbv)whensizeofx=Bv.to_uintbv->x(* absorbing element *)|(Mul,_,Cstbv|And,_,Cstbv)whenBv.is_zerosbv->y|Or,_,CstbvwhenBv.is_fillbv->y|(Lsr|Lsl|Asr|Rol|Ror|Srem|Sdiv|Udiv|Urem),Cstbv,_whenBv.is_zerosbv->x|(Lsl,x,Cstbv|Lsr,x,Cstbv)whensizeofx<=Bv.to_uintbv->zeros(Bv.size_ofbv)(* elimination *)|(And,a,b|Or,a,b)whencompareab=0->a|And,a,bwhenis_trivial_lognotab->zerossx|Or,a,bwhenis_trivial_lognotab->constant(Bitvector.fillsx)|(And,Binary{f=And;y=a;_},b|Or,Binary{f=Or;y=a;_},b)whencompareab=0->x|(Minus,a,b|Xor,a,b)whencompareab=0->zeros(sizeofa)|Minus,Binary{f=Plus;x=a;y=b;_},c|Xor,Binary{f=Xor;x=a;y=b;_},cwhencomparebc=0->a|(Srem|Urem),a,CstbvwhenBv.is_onesbv->zeros(sizeofa)|(Sdiv|Udiv),x,ywhencomparexy=0->ones(sizeofx)|(Srem|Urem),x,ywhencomparexy=0->zeros(sizeofx)|(Lsl,x,Cstbv|Lsr,x,Cstbv)whenBv.to_uintbv>=sizeofx->zeros(sizeofx)|Asr,x,CstbvwhenBv.to_uintbv>=sizeofx-1->lethi=sizeofx-1inunary(Sexthi)(unary(Restrict{hi;lo=hi})x)(* factorisation *)|Plus,a,bwhencompareab=0->binaryLsla(constant(Bv.onessx))sx(* commutativity -- keep sorted *)(* special cases for + - *)|Plus,a,Binary{f=Minus;x=b;y=c;_}whencompareab<=0->binaryMinus(binaryPlusbasx)csx|Plus,Binary{f=Minus;x=a;y=b;_},cwhencomparebc<=0->binaryMinus(binaryPlusacsx)bsx|Plus,Binary{f=Minus;_},c->mk_binaryPlusxc|Minus,Binary{f=Plus;x=a;y=b;_},cwhencomparebc<0->binaryPlus(binaryMinusacsx)bsx|Minus,Binary{f=Minus;x=a;y=b;_},cwhencomparebc<0->binaryMinus(binaryMinusacsx)bsx|Plus,Unary{f=Minus;x=a;_},b->binaryMinusbasx(* generic chained *)|Plus,Binary{f=Plus;x=a;y=b;_},c|Mul,Binary{f=Mul;x=a;y=b;_},c|And,Binary{f=And;x=a;y=b;_},c|Or,Binary{f=Or;x=a;y=b;_},c|Xor,Binary{f=Xor;x=a;y=b;_},cwhencomparebc<0->binaryf(binaryfacsx)bsx|Plus,Binary{f=Plus;_},c|Mul,Binary{f=Mul;_},c|And,Binary{f=And;_},c|Or,Binary{f=Or;_},c|Xor,Binary{f=Xor;_},c->mk_binaryfxc(* generic dual *)|Plus,_,_|Mul,_,_|And,_,_|Or,_,_|Xor,_,_|Eq,_,_|Diff,_,_whencomparexy<0->binaryfyxsx(* associativity *)|Plus,a,Binary{f=Plus;x=b;y=c;_}|Mul,a,Binary{f=Mul;x=b;y=c;_}|And,a,Binary{f=And;x=b;y=c;_}|Or,a,Binary{f=Or;x=b;y=c;_}|Xor,a,Binary{f=Xor;x=b;y=c;_}->binaryf(binaryfabsx)csx|Concat,a,Binary{f=Concat;x=b;y=c;_}->binaryf(binaryfabsx)c(sx+sizeofb)(* trivial condition *)|(Eq,a,b|Ule,a,b|Uge,a,b|Sle,a,b|Sge,a,b)whencompareab=0->one|(Diff,a,b|Ult,a,b|Ugt,a,b|Slt,a,b|Sgt,a,b)whencompareab=0->zero(* condition reduction *)|Eq,x,CstbvwhenBv.is_onebv->x|Eq,x,CstbvwhenBv.is_zerobv->unaryNotx|Eq,Unary{f=Uextn;x=a;size;_},Cstbv(* see check above *)|Diff,Unary{f=Uextn;x=a;size;_},Cstbv->letsa=size-ninletbv'=Bv.extract~hi:(sa-1)~lo:0bvinifBv.is_zeros(Bv.extract~hi:(size-1)~lo:sabv)thenbinaryfa(constantbv')saelseiff=Eqthenzeroelseone|Eq,Unary{f=Sextn;x=a;size;_},Cstbv|Diff,Unary{f=Sextn;x=a;size;_},Cstbv->letsa=size-ninletbv'=Bv.extract~hi:(sa-1)~lo:0bvinifBv.equalbv(Bv.extend_signedbv'size)thenbinaryfa(constantbv')saelseiff=Eqthenzeroelseone|Eq,Unary{f=Not;x=a;_},Unary{f=Not;x=b;_}|Eq,Unary{f=Minus;x=a;_},Unary{f=Minus;x=b;_}|Diff,Unary{f=Not;x=a;_},Unary{f=Not;x=b;_}|Diff,Unary{f=Minus;x=a;_},Unary{f=Minus;x=b;_}->binaryfabsx|Eq,Unary{f=Uext_;x=a;_},Unary{f=Uext_;x=b;_}|Eq,Unary{f=Sext_;x=a;_},Unary{f=Sext_;x=b;_}|Diff,Unary{f=Uext_;x=a;_},Unary{f=Uext_;x=b;_}|Diff,Unary{f=Sext_;x=a;_},Unary{f=Sext_;x=b;_}whensizeofa=sizeofb->binaryfab(sizeofa)|(Or,Binary{f=(Ugt|Ult|Sgt|Slt)ascmp;x;y;_},Binary{f=Eq;x=x';y=y';_})|(Or,Binary{f=Eq;x=x';y=y';_},Binary{f=(Ugt|Ult|Sgt|Slt)ascmp;x;y;_})when(is_equalxx'&&is_equalyy')||(is_equalxy'&&is_equalyx')->binary(matchcmpwith|Ugt->Uge|Ult->Ule|Sgt->Sge(* Slt *)|_->Sle)xy1(* split condition *)|Eq,Binary{f=Concat;x=a;y=b;_},Cstbv->letsb=sizeofbinbinaryAnd(binaryEqa(constant(Bv.extract~lo:sb~hi:(Bv.size_ofbv-1)bv))(sx-sb))(binaryEqb(constant(Bv.extract~lo:0~hi:(sb-1)bv))sb)1|Diff,Binary{f=Concat;x=a;y=b;_},Cstbv->letsb=sizeofbinbinaryOr(binaryDiffa(constant(Bv.extract~lo:sb~hi:(Bv.size_ofbv-1)bv))(sx-sb))(binaryDiffb(constant(Bv.extract~lo:0~hi:(sb-1)bv))sb)1|Eq,Binary{f=Concat;x=a;y=b;_},Unary{f=Uext_;x=c;_}whensizeofb=sizeofc->letsa=sizeofainbinaryAnd(binaryEqa(zerossa)sa)(binaryEqbc(sx-sa))1|(Diff,Binary{f=Concat;x=a;y=b;_},Unary{f=Uext_;x=c;_})whensizeofb=sizeofc->letsa=sizeofainbinaryOr(binaryDiffa(zerossa)sa)(binaryDiffbc(sx-sa))1|(Eq,Binary{f=Concat;x=a;y=b;_},Binary{f=Concat;x=c;y=d;_})whensizeofb=sizeofd->binaryAnd(binaryEqac(sizeofa))(binaryEqbd(sizeofb))1|(Diff,Binary{f=Concat;x=a;y=b;_},Binary{f=Concat;x=c;y=d;_})whensizeofb=sizeofd->binaryOr(binaryDiffac(sizeofa))(binaryDiffbd(sizeofb))1(* TODO: possibly more to come *)(* inversion *)|Minus,a,CstbvwhenBv.is_onebv->unaryNota|Xor,a,CstbvwhenBv.is_fillbv->unaryNota|Minus,a,Unary{f=Minus;x=b;_}->binaryPlusabsx|Minus,a,Binary{f=Plus;x=b;y=c;_}->binaryMinus(binaryMinusabsx)csx|Minus,a,Binary{f=Minus;x=b;y=c;_}->binaryPlus(binaryMinusabsx)csx(* bit masking *)|Minus,Unary{f=Uextn;x;_},Cstbwhensizeofx=1&&Bv.is_onesb->unary(Sextn)(unaryNotx)|And,x,CstbvwhenBv.is_onesbv->unary(Uext(sx-1))(unary(Restrict{hi=0;lo=0})x)(* concatenation normalization -- extension on top *)|Concat,Cstbv,awhenBv.is_zerosbv->unary(Uext(Bv.size_ofbv))a|Concat,Unary{f=Uextn;x=a;_},b->unary(Uextn)(binaryConcatab(sizeofa))|Concat,Unary{f=Sextn;x=a;_},b->unary(Sextn)(binaryConcatab(sizeofa))|((Or|Xor),Binary{f=Lsl;x=a;y=Cstbv;_},Unary{f=Uextn;x=b;_})whensizeofb=Bv.to_uintbv->binaryConcat(unary(Restrict{lo=0;hi=n-1})a)bn|(Or|Xor),Binary{f=Lsl;x=a;y=Cstbv;size;_},Cstbv'->letshift=Bv.to_uintbvinletsz=size-shiftinbinaryConcat(binaryOr(unary(Restrict{hi=sz-1;lo=0})a)(constant(Bv.extract~hi:(size-1)~lo:shiftbv'))sz)(constant(Bv.extract~hi:(shift-1)~lo:0bv'))sz(* TODO!!: chain!! *)(* revert -- stitch adjacent part *)|(Concat,Unary{f=Restrict{lo;hi};x=a;_},Unary{f=Restrict{lo=lo';hi=hi'};x=b;_})whenhi'+1=lo&&compareab=0->unary(Restrict{lo=lo';hi})a(* TODO: more to come like loads.. *)(* misc *)|Asr,Unary{f=Uext_;x;_},CstbvwhenBv.to_uintbv>=sizeofx->zeros(Bv.size_ofbv)|Asr,Unary{f=Uextn;x;_},Cstbv->letshift=Bv.to_uintbvinunary(Uext(n+shift))(unary(Restrict{hi=sizeofx-1;lo=shift})x)|And,(Unary{f=Uext_;x;_}asu),Cstbvwhenletv=Bv.value_ofbvinlets=Z.numbitsvinsizeofx<=s&&s=Z.popcountv->u|And,Unary{f=Uextnasf;x;_},Cstbv->unaryf(binaryAndx(constant(Bv.extract~hi:(sizeofx-1)~lo:0bv))(sx-n))|And,Unary{f=Uextnasf;x;_},Unary{f=Uextn';x=x';_}whenn=n'->unaryf(binaryAndxx'(sx-n))|And,Unary{f=Sextn;x;_},CstbvwhenZ.numbits(Bv.value_ofbv)<=sx-n->unary(Uextn)(binaryAndx(constant(Bv.extract~hi:(sx-n-1)~lo:0bv))(sx-n))|And,Binary{f=Concat;y;_},CstbvwhenZ.numbits(Bv.value_ofbv)<=sizeofy->letsz=sizeofyinunary(Uext(sx-sz))(binaryAndy(constant(Bv.extract~hi:(sz-1)~lo:0bv))sz)|((And|Or|Xor)asf),Binary{f=Concat;x;y;size;_},Cstbv->letsy=sizeofyinbinaryConcat(binaryfx(constant(Bv.extract~hi:(size-1)~lo:sybv))(size-sy))(binaryfy(constant(Bv.extract~hi:(sy-1)~lo:0bv))sy)size|Lsr,Binary{f=Lsl;x;y=Cstbv;size;_},Cstbv'whenBv.ugebvbv'->leti=Bv.to_uintbvinbinaryLsl(unary(Uexti)(unary(Restrict{hi=size-1-i;lo=0})x))(constant(Bv.subbvbv'))size|(Or,Binary{f=Lsl;x;y=Cstbv;size;_},Binary{f=Lsr;x=x';y=Cstbv';_})|(Or,Binary{f=Lsr;x=x';y=Cstbv';_},Binary{f=Lsl;x;y=Cstbv;size;_})whenis_equalxx'&&Bv.to_intbv+Bv.to_intbv'=size->binaryConcat(unary(Restrict{hi=size-1-Bv.to_intbv;lo=0})x)(unary(Restrict{hi=size-1;lo=size-Bv.to_intbv})x)size(* bitwize *)|((And|Or|Xor),Binary{f=Concat;x;y;size;_},Binary{f=Concat;x=x';y=y';_})whensizeofy=sizeofy'->letsy=sizeofyinbinaryConcat(binaryfxx'(size-sy))(binaryfyy'sy)size(* forward ite *)|f,Ite{c;t=Cstbv;e;_},(Cstbv'asy)->itec(constant(Bv.binaryfbvbv'))(binaryfeysx)|f,Ite{c;t;e=Cstbv;_},(Cstbv'asy)->itec(binaryftysx)(constant(Bv.binaryfbvbv'))|f,(Cstbvasx),Ite{c;t=Cstbv'asz;e=Cstbv''asz';_}->itec(tryconstant(Bv.binaryfbvbv')withDivision_by_zero->mk_binaryfxz)(tryconstant(Bv.binaryfbvbv'')withDivision_by_zero->mk_binaryfxz')|f,(Cstbvasx),Ite{c;t=Cstbv'asz;e;_}->itec(tryconstant(Bv.binaryfbvbv')withDivision_by_zero->mk_binaryfxz)(binaryfxesx)|f,(Cstbvasx),Ite{c;t;e=Cstbv'asz;_}->itec(binaryfxtsx)(tryconstant(Bv.binaryfbvbv')withDivision_by_zero->mk_binaryfxz)(* basic equation *)|(Eq|Diff),Binary{f=Plus;x;y=Cstbv;_},Cstbv'->binaryfx(constant(Bv.subbv'bv))sx|(Eq|Diff),Binary{f=Minus;x;y=Cstbv;_},Cstbv'->binaryfx(constant(Bv.addbv'bv))sx|(Eq|Diff),Binary{f=Minus;x=Cstbv;y;_},Cstbv'->binaryfy(constant(Bv.subbvbv'))sx|(Eq|Diff),Binary{f=Xor;x;y=Cstbv;_},Cstbv'->binaryfx(constant(Bv.logxorbvbv'))sx|(Eq|Diff),Binary{f=And;x;y=Cstbv;_},Cstbv'whenBv.equalbvbv'&&Z.popcount(Bv.value_ofbv)=1->lethi=Z.trailing_zeros(Bv.value_ofbv)inletb=unary(Restrict{hi;lo=hi})xiniff=DiffthenunaryNotbelseb|(Eq|Diff),Binary{f=And;x;y=Cstbv;_},Cstbv'whenZ.popcount(Bv.value_ofbv)=1&&Bv.is_zerosbv'->lethi=Z.trailing_zeros(Bv.value_ofbv)inletb=unary(Restrict{hi;lo=hi})xiniff=EqthenunaryNotbelseb|(Eq|Diff),Binary{f=Lsl;x;y=Cstbv;_},Cstbv'->letshift=Bv.to_uintbvinlety=Bv.value_ofbv'inifZ.trailing_zerosy>=shiftthenbinaryf(unary(Restrict{hi=sx-shift-1;lo=0})x)(constant(Bv.create(Z.shift_rightyshift)(sx-shift)))1elseiff=Eqthenzeroelseone|(Eq|Diff),Binary{f=Or;x;y;size;_},(Cstbvasz)whenBv.is_zerosbv->binary(iff=EqthenAndelseOr)(binaryfxzsize)(binaryfyzsize)1|(And,Binary{f=Diff;x=a;y=Cstbv;_},Binary{f=Eq;x=a';y=Cstbv';_})whenis_equalaa'->ifBv.equalbvbv'thenzeroelsey|(Or,Binary{f=Diff;x=a;y=Cstbv;_},Binary{f=Eq;x=a';y=Cstbv';_})whenis_equalaa'->ifBv.equalbvbv'thenoneelsex(* basic arithmetic *)|Minus,Binary{f=Lsl;x;y=Cstbv;size;_},ywhenis_equalxy->letone=Bv.onessizeinbinaryMulx(constant(Bv.sub(Bv.binaryLslonebv)one))size|Mul,x,Cstbv->letz=Bv.value_ofbvinifZ.popcountz=1thenbinaryLslx(constant(Bv.of_int~size:sx(Z.trailing_zerosz)))sxelsemk_binaryMulxy(* default case *)|_,_,_->mk_binaryfxyanditecte=match(c,t,e)with|_,_,_whensizeofc<>1||sizeoft<>sizeofe->abort@@mk_itecte|Cstbv,t,_whenBv.is_onebv->t|Cstbv,_,ewhenBv.is_zerobv->e|c,Cstbv,ewhenBv.is_onebv->binaryOrce1|c,Cstbv,ewhenBv.is_zerobv->binaryAnd(unaryNotc)e1|c,t,CstbvwhenBv.is_onebv->binaryOr(unaryNotc)t1|c,t,CstbvwhenBv.is_zerobv->binaryAndct1|_,t,ewhencomparete=0->t|c,Cstbv,Cstbv'whenBv.is_fillbv&&Bv.is_zerosbv'->unary(Sext(Bv.size_ofbv-1))c|c,Cstbv,Cstbv'whenBv.is_zerosbv&&Bv.is_fillbv'->unary(Sext(Bv.size_ofbv-1))(unaryNotc)|Unary{f=Not;x=c;_},t,e->itecet|c,Ite{c=c';t=t';e=e';_},ewhenis_equalee'->ite(binaryAndcc'1)t'e|c,Ite{c=c';t=t';e=e';_},ewhenis_equalet'->ite(binaryAndc(unaryNotc')1)e'e|c,t,Ite{c=c';t=t';e=e';_}whenis_equaltt'->ite(binaryOrcc'1)te'|c,t,Ite{c=c';t=t';e=e';_}whenis_equalte'->ite(binaryOrc(unaryNotc')1)tt'|_,_,_->mk_itecteletbinaryfxy=letsx=sizeofxandsy=sizeofyiniff<>Concat&&sx<>sythenabort@@mk_binaryfxy;binaryfxysxletlognott=unaryNottletuminust=unaryMinustletsextnt=unary(Sext(n-sizeoft))tletuextnt=unary(Uext(n-sizeoft))tletrestrict~lo~hit=unary(Restrict{lo;hi})tletbit_restrictit=restrict~lo:i~hi:itletaddtt'=binaryPlustt'letsubtt'=binaryMinustt'letmultt'=binaryMultt'letsremtt'=binarySremtt'leturemtt'=binaryUremtt'letudivtt'=binaryUdivtt'letsdivtt'=binarySdivtt'letlogortt'=binaryOrtt'letlogxortt'=binaryXortt'letlogandtt'=binaryAndtt'letequaltt'=binaryEqtt'letdifftt'=binaryDifftt'letulett'=binaryUlett'letslett'=binarySlett'letulttt'=binaryUlttt'letslttt'=binarySlttt'letugett'=binaryUgett'letsgett'=binarySgett'letugttt'=binaryUgttt'letsgttt'=binarySgttt'letappendtt'=binaryConcattt'letshift_lefttt'=binaryLsltt'letshift_righttt'=binaryLsrtt'letshift_right_signedtt'=binaryAsrtt'letrotate_lefttt'=binaryRoltt'letrotate_righttt'=binaryRortt'letaddixy=binaryPlusx(constant(Bv.of_int~size:(sizeofx)y))letaddzxy=binaryPlusx(constant(Bv.createy(sizeofx)))letbyte_swap=letrecitereir=ifi=0thenrelseitere(i-8)(append(restrict~hi:(i-1)~lo:(i-8)e)r)infune->letsize=sizeofeinifsizeland0x7<>0thenraise(Invalid_argument"byte_swap");itere(size-8)(restrict~hi:(size-1)~lo:(size-8)e)letrecmap:typekab.(string->int->a->t)->(int->Machine.endianness->t->b->t)->(k,a,b)term->t=funabt->matchTermtwith|Term(Var{name;size;label;_})->anamesizelabel|Term(Load{len;dir;addr;label;_})->blendir(mapabaddr)label|Term(Cst_asc)->c|Term(Unary{f;x;_})->unaryf(mapabx)|Term(Binary{f;x;y;_})->binaryf(mapabx)(mapaby)|Term(Ite{c;t;e;_})->ite(mapabc)(mapabt)(mapabe)let_unary=mk_unarylet_binary=mk_binarylet_ite=mk_iteend