blob: fc3c030533f75ae1dad3a619097567f2fe401e03 (
plain)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
(* *********************************************************************)
(* *)
(* The Compcert verified compiler *)
(* *)
(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
(* *)
(* Copyright Institut National de Recherche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
(* under the terms of the INRIA Non-Commercial License Agreement. *)
(* *)
(* *********************************************************************)
open AST
open Camlcoq
open Diagnostics
open Memdata
open Printf
type t =
| Label of int
| String of string
| Symbol of ident
let offset ofs =
let ofs = camlint_of_coqint ofs in
if ofs = 0l then "" else sprintf " + %ld" ofs
let size_chunk c =
sprintf "%ld" (camlint_of_coqint (size_chunk c))
let addr_global id ofs =
let addr_o = "("
and addr_e = sprintf "%s)" (offset ofs) in
[String addr_o;Symbol id;String addr_e]
exception Bad_parameter of string
let warn_lval_arg pos arg =
match arg with
| BA_int _
| BA_long _
| BA_addrstack _
| BA_addrglobal _
| BA_splitlong _
| BA_addptr _ ->
let msg = sprintf "expected register or memory cell for parameter '%s', skipping generation of ais annotation" pos in
raise (Bad_parameter msg)
| BA_float _
| BA_single _ -> assert false (* Should never occur and be avoided in C2C *)
| _ -> ()
let ais_expr_arg pos preg_string sp_reg_name arg =
let preg reg = sprintf "reg(\"%s\")" (preg_string reg)
and sp = sprintf "reg(\"%s\")" sp_reg_name
and simple s = [String s]
in
let rec ais_arg = function
| BA x -> simple (preg x)
| BA_int n -> simple (sprintf "%ld" (camlint_of_coqint n))
| BA_long n -> simple (sprintf "%Ld" (camlint64_of_coqint n))
| BA_float _
| BA_single _ -> assert false (* Should never occur and be avoided in C2C *)
| BA_loadstack(chunk, ofs) ->
let loadstack = sprintf "mem(%s%s, %s)" sp
(offset ofs)
(size_chunk chunk) in
simple loadstack
| BA_addrstack ofs ->
let addrstack = sprintf "(%s%s)" sp (offset ofs) in
simple addrstack
| BA_loadglobal(chunk, id, ofs) ->
let mem_o = "mem("
and mem_e = sprintf "%s, %s)"
(offset ofs)
(size_chunk chunk) in
[String mem_o;Symbol id;String mem_e]
| BA_addrglobal(id, ofs) ->
addr_global id ofs
| BA_splitlong(hi, lo) ->
let arg1 = combine " * " (ais_arg hi) (simple "0x100000000") in
combine " + " arg1 (ais_arg lo)
| BA_addptr(a1, a2) ->
let a1 = ais_arg a1
and a2 = ais_arg a2 in
combine " + " a1 a2
and combine mid arg1 arg2 =
let op_br = simple "("
and mid = simple mid
and cl_br = simple ")" in
op_br@arg1@mid@arg2@cl_br in
ais_arg arg
let ais_annot_list: (t list) list ref = ref []
let get_ais_annots () =
let annots = !ais_annot_list in
ais_annot_list := [];
List.rev annots
let re_loc_param = Str.regexp "# file:\\([^ ]+\\) line:\\([^ ]+\\)"
let loc_of_txt txt =
try
let pos = String.index txt '\n' in
let txt = String.sub txt 0 (pos -1) in
if Str.string_partial_match re_loc_param txt 0 then
let file = Str.matched_group 1 txt
and line = int_of_string (Str.matched_group 2 txt) in
file,line
else
no_loc
with _ ->
no_loc
let re_ais_annot_param = Str.regexp "%%\\|%[el][0-9]+\\|%here\\|\007"
let ais_annot_txt warn lbl preg_string sp_reg_name txt args =
let fragment = function
| Str.Delim "%here" ->
[Label lbl]
| Str.Text s ->
[String s]
| Str.Delim "%%" ->
[String "%"]
| Str.Delim "\007" ->
[String "\007\000"]
| Str.Delim s ->
let typ = String.get s 1
and n = int_of_string (String.sub s 2 (String.length s - 2)) in
let arg = List.nth args (n-1) in
begin match typ with
| 'e' -> ais_expr_arg s preg_string sp_reg_name arg
| 'l' -> warn_lval_arg s arg; ais_expr_arg s preg_string sp_reg_name arg
| _ -> assert false
end
in
let annot =
try
List.concat (List.map fragment (Str.full_split re_ais_annot_param txt))
with
| Bad_parameter s ->
if warn then begin
let loc = loc_of_txt txt in
warning loc Wrong_ais_parameter "wrong ais parameter: %s" s
end;
[]
in
let rec merge acc = function
| [] -> List.rev acc
| (Label _ as lbl):: rest -> merge (lbl::acc) rest
| (Symbol _ as sym) :: rest -> merge (sym::acc) rest
| String s1 :: String s2 :: rest ->
merge acc (String (s1 ^ s2) :: rest)
| String s:: rest -> merge ((String s)::acc) rest
in
merge [] annot
let add_ais_annot lbl preg_string sp_reg_name txt args =
let annot = ais_annot_txt true lbl preg_string sp_reg_name txt args in
if annot <> [] then
ais_annot_list := (annot)::!ais_annot_list
let json_ais_annot preg_string sp_reg_name txt args =
let txt = ais_annot_txt false 0 preg_string sp_reg_name txt args in
let t_to_json = function
| Label _ -> String "%here"
| String s -> let buf = Buffer.create (String.length s) in
String.iter (fun c ->
begin match c with
| '\\' | '"' -> Buffer.add_char buf '\\'
| _ -> () end;
Buffer.add_char buf c) s;
String (Buffer.contents buf)
| Symbol s -> Symbol s in
(List.map t_to_json txt)
let validate_ais_annot env loc txt args =
let used_params = Array.make (List.length args) false in
let fragment arg =
match arg with
| Str.Delim "%here"
| Str.Text _
| Str.Delim "%%"
| Str.Delim "\007" -> ()
| Str.Delim s ->
let n = int_of_string (String.sub s 2 (String.length s - 2)) in
try
let arg = List.nth args (n-1) in
Array.set used_params (n-1) true;
if Cutil.is_float_type env arg.C.etyp then
error loc "floating point types for parameter '%s' are not supported in ais annotations" s
else if Cutil.is_volatile_variable env arg then begin
let arg =
match arg.C.edesc with
| C.EVar id -> id.C.name
| _ -> assert false
in
error loc "access to volatile variable '%s' for parameter '%s' is not supported in ais annotations" arg s
end
with _ ->
error loc "unknown parameter '%s'" s
in List.iter fragment (Str.full_split re_ais_annot_param txt);
Array.iteri (fun pos used -> if not used then warning loc Unused_ais_parameter "unused parameter %d of ais annotation" pos) used_params
|