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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
(* *********************************************************************)
(* *)
(* The Compcert verified compiler *)
(* *)
(* Xavier Leroy, INRIA Paris-Rocquencourt *)
(* *)
(* Copyright Institut National de Recherche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU General Public License as published by *)
(* the Free Software Foundation, either version 2 of the License, or *)
(* (at your option) any later version. This file is also distributed *)
(* under the terms of the INRIA Non-Commercial License Agreement. *)
(* *)
(* *********************************************************************)
(* Platform-dependent handling of pragmas *)
open Printf
open Camlcoq
open Cparser
type section_info = {
sec_name_init: string;
sec_name_uninit: string;
sec_acc_mode: string;
sec_near_access: bool
}
let default_section_info = {
sec_name_init = ".data";
sec_name_uninit = ".data"; (* COMM? *)
sec_acc_mode = "RW";
sec_near_access = false
}
let section_table : (string, section_info) Hashtbl.t =
Hashtbl.create 17
(* Built-in sections *)
let _ =
let rodata =
if Configuration.system = "linux" then ".rodata" else ".text" in
List.iter (fun (n, si) -> Hashtbl.add section_table n si) [
"CODE", {sec_name_init = ".text";
sec_name_uninit = ".text";
sec_acc_mode = "RX";
sec_near_access = false};
"DATA", {sec_name_init = ".data";
sec_name_uninit = ".data"; (* COMM? *)
sec_acc_mode = "RW";
sec_near_access = false};
"SDATA", {sec_name_init = ".sdata";
sec_name_uninit = ".sbss";
sec_acc_mode = "RW";
sec_near_access = true};
"CONST", {sec_name_init = rodata;
sec_name_uninit = rodata;
sec_acc_mode = "R";
sec_near_access = false};
"SCONST",{sec_name_init = ".sdata2";
sec_name_uninit = ".sdata2";
sec_acc_mode = "R";
sec_near_access = true};
"STRING",{sec_name_init = rodata;
sec_name_uninit = rodata;
sec_acc_mode = "R";
sec_near_access = false}
]
(* #pragma section *)
let process_section_pragma classname istring ustring addrmode accmode =
let old_si =
try Hashtbl.find section_table classname
with Not_found -> default_section_info in
let si =
{ sec_name_init =
if istring = "" then old_si.sec_name_init else istring;
sec_name_uninit =
if ustring = "" then old_si.sec_name_uninit else ustring;
sec_acc_mode =
if accmode = "" then old_si.sec_acc_mode else accmode;
sec_near_access =
if addrmode = ""
then old_si.sec_near_access
else (addrmode = "near-code") || (addrmode = "near-data") } in
Hashtbl.add section_table classname si
(* #pragma use_section *)
let use_section_table : (AST.ident, section_info) Hashtbl.t =
Hashtbl.create 51
let process_use_section_pragma classname id =
try
let info = Hashtbl.find section_table classname in
Hashtbl.add use_section_table (intern_string id) info
with Not_found ->
C2Clight.error (sprintf "unknown section name `%s'" classname)
let default_use_section id classname =
if not (Hashtbl.mem use_section_table id) then begin
let info =
try Hashtbl.find section_table classname
with Not_found -> assert false in
Hashtbl.add use_section_table id info
end
let define_function id d =
default_use_section id "CODE"
let define_stringlit id =
default_use_section id "STRING"
let define_variable id d =
let is_small limit =
match C2Clight.atom_sizeof id with
| None -> false
| Some sz -> sz <= limit in
let sect =
if C2Clight.atom_is_readonly id then
if is_small !Clflags.option_small_const then "SCONST" else "CONST"
else
if is_small !Clflags.option_small_data then "SDATA" else "DATA" in
default_use_section id sect
(* #pragma reserve_register *)
let process_reserve_register_pragma name =
match Machregsaux.register_by_name name with
| None ->
C2Clight.error "unknown register in `reserve_register' pragma"
| Some r ->
if Machregsaux.can_reserve_register r then
Coloringaux.reserved_registers :=
r :: !Coloringaux.reserved_registers
else
C2Clight.error "cannot reserve this register (not a callee-save)"
(* Parsing of pragmas using regexps *)
let re_start_pragma_section = Str.regexp "section\\b"
let re_pragma_section = Str.regexp(
"section[ \t]+"
^ "\\([A-Za-z_][A-Za-z_0-9]*\\)[ \t]+" (* class_name *)
^ "\\(\"[^\"]*\"\\)?[ \t]*" (* istring *)
^ "\\(\"[^\"]*\"\\)?[ \t]*" (* ustring *)
^ "\\(standard\\|near-absolute\\|far-absolute\\|near-data\\|far-data\\|near-code\\|far-code\\)?[ \t]*" (* addressing mode *)
^ "\\([RWXON]*\\)" (* access mode *)
)
let re_start_pragma_use_section = Str.regexp "use_section\\b"
let re_pragma_use_section = Str.regexp
"use_section[ \t]+\
\\([A-Za-z_][A-Za-z_0-9]*\\)[ \t]+\
\\(.*\\)$"
let re_split_idents = Str.regexp "[ \t,]+"
let re_start_pragma_reserve_register = Str.regexp "reserve_register\\b"
let re_pragma_reserve_register = Str.regexp
"reserve_register[ \t]+\\([A-Za-z0-9]+\\)"
let process_pragma name =
if Str.string_match re_pragma_section name 0 then begin
process_section_pragma
(Str.matched_group 1 name) (* classname *)
(Str.matched_group 2 name) (* istring *)
(Str.matched_group 3 name) (* ustring *)
(Str.matched_group 4 name) (* addrmode *)
(Str.matched_group 5 name); (* accmode *)
true
end else if Str.string_match re_start_pragma_section name 0 then
(C2Clight.error "ill-formed `section' pragma"; true)
else if Str.string_match re_pragma_use_section name 0 then begin
let classname = Str.matched_group 1 name
and idents = Str.matched_group 2 name in
let identlist = Str.split re_split_idents idents in
if identlist = [] then C2Clight.warning "vacuous `use_section' pragma";
List.iter (process_use_section_pragma classname) identlist;
true
end else if Str.string_match re_start_pragma_use_section name 0 then begin
C2Clight.error "ill-formed `use_section' pragma"; true
end else if Str.string_match re_pragma_reserve_register name 0 then begin
process_reserve_register_pragma (Str.matched_group 1 name); true
end else if Str.string_match re_start_pragma_reserve_register name 0 then begin
C2Clight.error "ill-formed `reserve_register' pragma"; true
end else
false
let initialize () =
C2Clight.process_pragma_hook := process_pragma;
C2Clight.define_variable_hook := define_variable;
C2Clight.define_function_hook := define_function;
C2Clight.define_stringlit_hook := define_stringlit
(* PowerPC-specific: say if an atom is in a small data area *)
let atom_is_small_data a ofs =
match C2Clight.atom_sizeof a with
| None -> false
| Some sz ->
let ofs = camlint_of_coqint ofs in
if ofs >= 0l && ofs < Int32.of_int sz then begin
try
(Hashtbl.find use_section_table a).sec_near_access
with Not_found ->
if C2Clight.atom_is_readonly a
then sz <= !Clflags.option_small_const
else sz <= !Clflags.option_small_data
end else
false
(* PowerPC-specific: determine section to use for a particular symbol *)
let section_for_atom a init =
try
let sinfo = Hashtbl.find use_section_table a in
let sname =
if init then sinfo.sec_name_init else sinfo.sec_name_uninit in
if not (String.contains sname '\"') then
Some sname
else begin
(* The following is Diab-specific... *)
let accmode = sinfo.sec_acc_mode in
let is_writable = String.contains accmode 'W'
and is_executable = String.contains accmode 'X' in
let stype =
match is_writable, is_executable with
| true, true -> 'm' (* text+data *)
| true, false -> 'd' (* data *)
| false, true -> 'c' (* text *)
| false, false -> 'r' (* const *)
in Some(sprintf ".section\t%s,,%c" sname stype)
end
with Not_found -> None
|