1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588(**************************************************************************)(* 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(** {4 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