@@ -84,7 +84,17 @@ struct
8484 let overflow_range = R. of_interval range_ikind (- 999L , 999L ) (* Since there is no top ikind we use a range that includes both IInt128 [-127,127] and IUInt128 [0,128]. Only needed for intermediate range computation on longs. Correct range is set by cast. *)
8585 let top_overflow () = `Excluded (S. empty () , overflow_range)
8686 let bot () = `Bot
87- let top_of ik = `Excluded (S. empty () , size ik)
87+ let top_of ?bitfield ik =
88+ match bitfield with
89+ | Some b when b < = Z. numbits (Size. range ik |> snd) ->
90+ let range =
91+ if Cil. isSigned ik then
92+ R. of_interval range_ikind (Int64. of_int @@ - (b - 1 ), Int64. of_int b)
93+ else
94+ R. of_interval range_ikind (Int64. zero, Int64. of_int b)
95+ in
96+ `Excluded (S. empty () , range)
97+ | _ -> `Excluded (S. empty () , size ik)
8898 let bot_of ik = bot ()
8999
90100 let show x =
@@ -447,20 +457,49 @@ struct
447457
448458 let ge ik x y = le ik y x
449459
450- let lognot = lift1 Z. lognot
460+ let lognot ik x = norm ik @@ match x with
461+ | `Excluded (s , r ) ->
462+ let s' = S. map Z. lognot s in
463+ let r' = match R. minimal r, R. maximal r with
464+ | Some min , Some max when Int64. compare (Int64. neg max) Int64. zero < = 0 && Int64. compare (Int64. neg min) Int64. zero > 0 ->
465+ R. of_interval range_ikind (Int64. neg max, Int64. neg min)
466+ | _ , _ -> apply_range Z. lognot r
467+ in
468+ `Excluded (s', r')
469+ | `Definite x -> `Definite (Z. lognot x)
470+ | `Bot -> `Bot
451471
452472 let logand ik x y = norm ik (match x,y with
453- (* We don't bother with exclusion sets : * )
454- | `Excluded _ , `Definite i ->
455- (* Except in two special cases *)
473+ | `Excluded (_, r), `Definite i
474+ | `Definite i , `Excluded (_ , r ) ->
456475 if Z. equal i Z. zero then
457476 `Definite Z. zero
458477 else if Z. equal i Z. one then
459478 of_interval IBool (Z. zero, Z. one)
460- else
461- top_of ik
462- | `Definite _, `Excluded _
463- | `Excluded _ , `Excluded _ -> top_of ik
479+ else (
480+ match R. minimal r, R. maximal r with
481+ | None , _
482+ | _ , None -> top_of ik
483+ | Some r1 , Some r2 ->
484+ match Z. compare i Z. zero > = 0 , Int64. compare r1 Int64. zero > = 0 with
485+ | true , true -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, Int64. min r2 (Int64. of_int @@ Z. numbits i)))
486+ | true , _ -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, Int64. of_int @@ Z. numbits i))
487+ | _ , true -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, r2))
488+ | _ , _ ->
489+ let b = Int64. max (Int64. of_int @@ Z. numbits i) (Int64. max (Int64. abs r1) (Int64. abs r2)) in
490+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. neg b, b))
491+ )
492+ | `Excluded (_ , p ), `Excluded (_ , r ) ->
493+ begin match R. minimal p, R. maximal p, R. minimal r, R. maximal r with
494+ | Some p1 , Some p2 , Some r1 , Some r2 ->
495+ begin match Int64. compare p1 Int64. zero > = 0 , Int64. compare r1 Int64. zero > = 0 with
496+ | true , true -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, Int64. min p2 r2))
497+ | true , _ -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, p2))
498+ | _ , true -> `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, r2))
499+ | _ , _ -> `Excluded (S. empty () , R. join p r)
500+ end
501+ | _ -> top_of ik
502+ end
464503 (* The good case: *)
465504 | `Definite x , `Definite y ->
466505 (try `Definite (Z. logand x y) with | Division_by_zero -> top_of ik)
@@ -469,9 +508,58 @@ struct
469508 (* If only one of them is bottom, we raise an exception that eval_rv will catch *)
470509 raise (ArithmeticOnIntegerBot (Printf. sprintf " %s op %s" (show x) (show y))))
471510
511+ let logor ik x y = norm ik (match x,y with
512+ | `Excluded (_, r), `Definite i
513+ | `Definite i , `Excluded (_ , r ) ->
514+ if Z. compare i Z. zero > = 0 then
515+ `Excluded (S. empty () , R. join r (R. of_interval range_ikind (Int64. zero, Int64. of_int @@ Z. numbits i)))
516+ else (
517+ match R. minimal r, R. maximal r with
518+ | None , _
519+ | _ , None -> top_of ik
520+ | Some r1 , Some r2 ->
521+ let b = Int64. max (Int64. of_int @@ Z. numbits i) (Int64. max (Int64. abs r1) (Int64. abs r2)) in
522+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. neg b, b))
523+ )
524+ | `Excluded (_ , r1 ), `Excluded (_ , r2 ) -> `Excluded (S. empty () , R. join r1 r2)
525+ | `Definite x , `Definite y ->
526+ (try `Definite (Z. logor x y) with | Division_by_zero -> top_of ik)
527+ | `Bot , `Bot -> `Bot
528+ | _ ->
529+ (* If only one of them is bottom, we raise an exception that eval_rv will catch *)
530+ raise (ArithmeticOnIntegerBot (Printf. sprintf " %s op %s" (show x) (show y))))
472531
473- let logor = lift2 Z. logor
474- let logxor = lift2 Z. logxor
532+ let logxor ik x y = norm ik (match x,y with
533+ | `Definite i, `Excluded (_, r)
534+ | `Excluded (_ , r ), `Definite i ->
535+ begin match R. minimal r, R. maximal r with
536+ | None , _
537+ | _ , None -> top_of ik
538+ | Some r1 , Some r2 ->
539+ let b = Int64. max (Int64. of_int @@ Z. numbits i) (Int64. max (Int64. abs r1) (Int64. abs r2)) in
540+ if Int64. compare r1 Int64. zero > = 0 && Z. compare i Z. zero > = 0 then
541+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, b))
542+ else
543+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. neg b, b))
544+ end
545+ | `Excluded (_ , p ), `Excluded (_ , r ) ->
546+ begin match R. minimal p, R. maximal p, R. minimal r, R. maximal r with
547+ | Some p1 , Some p2 , Some r1 , Some r2 ->
548+ if Int64. compare p1 Int64. zero > = 0 && Int64. compare r1 Int64. zero > = 0 then
549+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. zero, Int64. max p2 r2))
550+ else (
551+ let b = List. fold_left Int64. max Int64. zero (List. map Int64. abs [p1; p2; r1; r2]) in
552+ `Excluded (S. empty () , R. of_interval range_ikind (Int64. neg b, b))
553+ )
554+ | _ , _ , _ , _ -> top_of ik
555+ end
556+ (* The good case: *)
557+ | `Definite x , `Definite y ->
558+ (try `Definite (Z. logxor x y) with | Division_by_zero -> top_of ik)
559+ | `Bot , `Bot -> `Bot
560+ | _ ->
561+ (* If only one of them is bottom, we raise an exception that eval_rv will catch *)
562+ raise (ArithmeticOnIntegerBot (Printf. sprintf " %s op %s" (show x) (show y))))
475563
476564 let shift (shift_op : int_t -> int -> int_t ) (ik : Cil.ikind ) (x : t ) (y : t ) =
477565 (* BigInt only accepts int as second argument for shifts; perform conversion here *)
0 commit comments