123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201(* This file is free software, part of dolmen. See file "LICENSE" for more information *)(* Value definition *)(* ************************************************************************* *)(** Bitvectors are represented by an unsigned unbounded integer. *)typet=Z.tletcompare=Z.compareletprint_bitpatternfmtt=letrecauxfmttn=ifn<0then()elsebeginFormat.fprintffmt"%d"(ifZ.testbittnthen1else0);auxfmtt(n-1)endinauxfmtt(Z.numbitst-1)letprintfmtt=Format.fprintffmt"%a / #%a"Z.pp_printtprint_bitpatterntletops=Value.ops~print~compare()(* Value helpers *)(* ************************************************************************* *)letis_unsigned_integersizez=Z.signz>=0&&Z.numbitsz<=sizeletubitvnt=lett=Value.extract_exn~opstin(* the typing of expressions should guarantee that this never happens *)ifnot(is_unsigned_integernt)then(invalid_arg(Format.asprintf"%a is not an unsigned integer of size %i"Z.pp_printtn));tletfrom_bitvnt=(* TODO: proper error *)ifnot(is_unsigned_integernt)then((* Format.eprintf "@[[BV] %s(%a) is not of size %i@]@."
(Z.format (Printf.sprintf "%%0+#%ib" n) t)
Z.pp_print t n; *)assertfalse(* Internal error *));tletextractnt=Z.extractt0nletconcatnmab=Z.logor(Z.shift_left(ubitvna)m)(ubitvmb)letrepeatnka=letrecloopnkaccz=ifk=0thenaccelseletacc=Z.logor(Z.shift_leftaccn)zinloopn(k-1)acczinloopnkZ.zeroaletrotate_leftnia=letk=imodninextractn(Z.logor(Z.shift_leftak)(Z.extracta(n-k)k))letrotate_rightnia=letk=imodninextractn(Z.logor(Z.shift_lefta(n-k))(Z.shift_rightak))(* Builtins *)(* ************************************************************************* *)moduleE=Dolmen.Std.ExprmoduleB=Dolmen.Std.Builtinletmkni=Value.mk~ops(from_bitvni)letcmp~cstp=Some(Fun.mk_clos@@Fun.fun_2~cst(funxy->Bool.mk@@pxy))letop2~cst~sizef=Some(Fun.mk_clos@@Fun.fun_2~cst(funxy->mksize@@fxy))letop1~cst~sizef=Some(Fun.mk_clos@@Fun.fun_1~cst(funx->mksize@@fx))letsbitvnt=Z.signed_extract(ubitvnt)0nletextractnt=Z.extractt0nletbuiltins~eval:__(cst:Dolmen.Std.Expr.Term.Const.t)=matchcst.builtinwith|B.Bitvecs->Some(mk(String.lengths)(Z.of_string_base2s))|B.Bitv_concat{n;m}->op2~cst~size:(n+m)(concatnm)|B.Bitv_extract{n;i;j}->op1~cst~size:(i-j+1)(funa->Z.extract(ubitvna)j(i-j+1))|B.Bitv_repeat{n;k}->op1~cst~size:(n*k)(funa->repeatnk(ubitvna))|B.Bitv_zero_extend{n;k}->op1~cst~size:(n+k)(ubitvn)|B.Bitv_sign_extend{n;k}->op1~cst~size:(n+k)(funa->extract(n+k)(sbitvna))|B.Bitv_rotate_left{n;i}->op1~cst~size:n(funa->rotate_leftni(ubitvna))|B.Bitv_rotate_right{n;i}->op1~cst~size:n(funa->rotate_rightni(ubitvna))|B.Bitv_notn->op1~cst~size:n(funa->extractn(Z.lognot(ubitvna)))|B.Bitv_andn->op2~cst~size:n(funab->Z.logand(ubitvna)(ubitvnb))|B.Bitv_orn->op2~cst~size:n(funab->from_bitvn(Z.logor(ubitvna)(ubitvnb)))|B.Bitv_nandn->op2~cst~size:n(funab->extractn(Z.lognot(Z.logand(ubitvna)(ubitvnb))))|B.Bitv_norn->op2~cst~size:n(funab->extractn(Z.lognot(Z.logor(ubitvna)(ubitvnb))))|B.Bitv_xorn->op2~cst~size:n(funab->extractn(Z.logxor(ubitvna)(ubitvnb)))|B.Bitv_xnorn->op2~cst~size:n(funab->extractn(Z.logxor(ubitvna)(Z.lognot(ubitvnb))))|B.Bitv_compn->op2~cst~size:n(funab->ifZ.equal(ubitvna)(ubitvnb)thenextract1Z.minus_oneelsefrom_bitv1Z.zero)|B.Bitv_negn->op1~cst~size:n(funa->extractn(Z.sub(Z.shift_leftZ.onen)(ubitvna)))|B.Bitv_addn->op2~cst~size:n(funab->extractn(Z.add(ubitvna)(ubitvnb)))|B.Bitv_subn->op2~cst~size:n(funab->extractn(Z.sub(ubitvna)(ubitvnb)))|B.Bitv_muln->op2~cst~size:n(funab->extractn(Z.mul(ubitvna)(ubitvnb)))|B.Bitv_udivn->op2~cst~size:n(funab->letb=ubitvnbinifZ.equalbZ.zerothenextractnZ.minus_oneelseextractn(Z.div(ubitvna)b))|B.Bitv_uremn->op2~cst~size:n(funab->letb=ubitvnbinifZ.equalbZ.zerothenfrom_bitvn(ubitvna)elseextractn(Z.rem(ubitvna)b))|B.Bitv_sdivn->op2~cst~size:n(funab->letb=sbitvnbinleta=sbitvnainifZ.equalbZ.zerothenifZ.signa>=0thenextractnZ.minus_oneelseextractnZ.oneelseextractn(Z.divab))|B.Bitv_sremn->op2~cst~size:n(funab->letb=sbitvnbinifZ.equalbZ.zerothenfrom_bitvn(ubitvna)elseextractn(Z.rem(sbitvna)b))|B.Bitv_smodn->op2~cst~size:n(funab->letb=sbitvnbinifZ.equalbZ.zerothenfrom_bitvn(ubitvna)elsebeginleta=sbitvnainextractn(Z.suba(Z.mul(Z.fdivab)b))end)|B.Bitv_shln->op2~cst~size:n(funab->letb=ubitvnbinifZ.leq(Z.of_intn)bthenfrom_bitvnZ.zeroelseextractn(Z.shift_left(ubitvna)(Z.to_intb)))|B.Bitv_lshrn->op2~cst~size:n(funab->letb=ubitvnbinifZ.leq(Z.of_intn)bthenfrom_bitvnZ.zeroelseextractn(Z.shift_right(ubitvna)(Z.to_intb)))|B.Bitv_ashrn->op2~cst~size:n(funab->letb=ubitvnbinletb=ifZ.leq(Z.of_intn)bthennelseZ.to_intbinextractn(Z.shift_right(sbitvna)b))|B.Bitv_ultn->cmp~cst(funab->Z.lt(ubitvna)(ubitvnb))|B.Bitv_ulen->cmp~cst(funab->Z.leq(ubitvna)(ubitvnb))|B.Bitv_ugtn->cmp~cst(funab->Z.gt(ubitvna)(ubitvnb))|B.Bitv_ugen->cmp~cst(funab->Z.geq(ubitvna)(ubitvnb))|B.Bitv_sltn->cmp~cst(funab->Z.lt(sbitvna)(sbitvnb))|B.Bitv_slen->cmp~cst(funab->Z.leq(sbitvna)(sbitvnb))|B.Bitv_sgtn->cmp~cst(funab->Z.gt(sbitvna)(sbitvnb))|B.Bitv_sgen->cmp~cst(funab->Z.geq(sbitvna)(sbitvnb))|_->None