1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
let dkey = Wp_parameters.register_category "rte"
module type Option = sig
val get : unit -> bool
val is_default : unit -> bool
val name : string
end
type t = {
name : string ;
cint : bool ;
option : (module Option) ;
status : (module RteGen.Generator.S) ;
}
let configure ~update ~generate kf cint rte =
let module Option = (val rte.option) in
let module Generator = (val rte.status) in
if rte.cint && not @@ Option.get () && generate then
match cint with
| Cint.Natural ->
Wp_parameters.warning ~once:true ~current:false
"-wp-rte and model nat require kernel to warn against %s" rte.name
| Cint.Machine -> ()
else
if not @@ Generator.is_computed kf then
if Option.get () then begin
let msg = if generate then "generate" else "missing" in
Wp_parameters.debug ~dkey "function %a: %s rte for %s"
Kernel_function.pretty kf msg rte.name ;
update := true
end else if not @@ Option.is_default () then begin
Wp_parameters.warning ~once:true ~current:false
"-wp-rte can annotate %s because %s is not set"
rte.name Option.name ;
update := !update || not generate
end
module WrapFiniteFloat = struct
include Kernel.SpecialFloat
let get () = get () <> "none"
end
let generator =
[
{ name = "memory access" ; cint = false ;
option = (module RteGen.Options.DoMemAccess) ;
status = (module RteGen.Generator.Mem_access) } ;
{ name = "division by zero" ; cint = false ;
option = (module RteGen.Options.DoDivMod) ;
status = (module RteGen.Generator.Div_mod) } ;
{ name = "signed overflow" ; cint = true ;
option = (module Kernel.SignedOverflow) ;
status = (module RteGen.Generator.Signed_overflow) } ;
{ name = "unsigned overflow" ; cint = true ;
option = (module Kernel.UnsignedOverflow) ;
status = (module RteGen.Generator.Unsigned_overflow) } ;
{ name = "signed downcast" ; cint = true ;
option = (module Kernel.SignedDowncast) ;
status = (module RteGen.Generator.Signed_downcast) } ;
{ name = "unsigned downcast" ; cint = true ;
option = (module Kernel.UnsignedDowncast) ;
status = (module RteGen.Generator.Unsigned_downcast) } ;
{ name = "shift" ; cint = true ;
option = (module RteGen.Options.DoShift) ;
status = (module RteGen.Generator.Shift) } ;
{ name = "left shift on negative" ; cint = true ;
option = (module Kernel.LeftShiftNegative) ;
status = (module RteGen.Generator.Left_shift_negative) } ;
{ name = "right shift on negative" ; cint = false ;
option = (module Kernel.RightShiftNegative) ;
status = (module RteGen.Generator.Right_shift_negative) } ;
{ name = "invalid bool value" ; cint = false ;
option = (module Kernel.InvalidBool) ;
status = (module RteGen.Generator.Bool_value) } ;
{ name = "pointer downcast" ; cint = false ;
option = (module Kernel.PointerDowncast) ;
status = (module RteGen.Generator.Pointer_downcast) } ;
{ name = "invalid pointer" ; cint = false ;
option = (module Kernel.InvalidPointer) ;
status = (module RteGen.Generator.Pointer_value) } ;
{ name = "float to int" ; cint = false ;
option = (module RteGen.Options.DoFloatToInt) ;
status = (module RteGen.Generator.Float_to_int) } ;
{ name = "special float" ; cint = false ;
option = (module WrapFiniteFloat) ;
status = (module RteGen.Generator.Float_to_int) } ;
]
let configure_initialized ~update ~generate kf =
let module Option = RteGen.Options.DoInitialized in
if Option.mem kf then begin
let generated = RteGen.Generator.Initialized.is_computed kf in
if not generated then begin
let msg = if generate then "generate" else "missing" in
Wp_parameters.debug ~dkey "function %a: %s rte for initialization"
Kernel_function.pretty kf msg ;
end ;
update := !update || not generated
end
let print_unsupported ~asked message =
if asked then
Wp_parameters.warning ~once:true ~current:false
"Skipped RTE guards: %s" message
let generate model kf =
let update = ref false in
let cint = WpContext.on_context (model,WpContext.Kf kf) Cint.current () in
List.iter (configure ~update ~generate:true kf cint) generator ;
configure_initialized ~update ~generate:true kf ;
if !update then begin
print_unsupported ~asked:(Kernel.UnalignedPointer.get ())
"unaligned pointers (\\aligned not supported)" ;
print_unsupported ~asked:(RteGen.Options.DoPointerCall.get ())
"invalid function pointer calls (\\valid_function not supported)" ;
let flags =
{ (RteGen.Flags.default ()) with
pointer_alignment = false ;
pointer_call = false ;
}
in
RteGen.Visit.annotate ~flags kf
end
let generate_all model =
Wp_parameters.iter_kf (generate model)
let missing_guards model kf =
let update = ref false in
let cint = WpContext.on_context (model,WpContext.Kf kf) Cint.current () in
List.iter (configure ~update ~generate:false kf cint) generator ;
configure_initialized ~update ~generate:false kf ;
!update