aboutsummaryrefslogtreecommitdiffstats
path: root/exportclight/ExportClight.ml
diff options
context:
space:
mode:
authorXavier Leroy <xavierleroy@users.noreply.github.com>2020-05-19 10:25:45 +0200
committerGitHub <noreply@github.com>2020-05-19 10:25:45 +0200
commit0eba6f63b6bc458d856e477f6f8ec6b78ef78c58 (patch)
tree6ab59e34aea0369013ed7e7461f3bf2f732d97bd /exportclight/ExportClight.ml
parent4a676623badb718da4055b7f26ee05f5097f4e7b (diff)
downloadcompcert-kvx-0eba6f63b6bc458d856e477f6f8ec6b78ef78c58.tar.gz
compcert-kvx-0eba6f63b6bc458d856e477f6f8ec6b78ef78c58.zip
Add a canonical encoding of identifiers as numbers and use it in clightgen (#353)
Within CompCert, identifiers (names of C functions, variables, types, etc) are represented by unique positive numbers, sometimes called "atoms". In the original implementation, atoms 1, 2, ..., N are assigned to identifiers as they are encountered. The resulting number are small and are efficient when used as keys in data structures such as PTrees. However, the mapping from C source-level identifiers to atoms differs between compilation units. This is not a problem for CompCert but complicates CompCert-based verification tools that need to combine several compilation units. This commit introduces an alternate implementation of atoms, suggested by Andrew Appel. The choice between implementations is governed by the Boolean reference `Camlcoq.use_canonical_atoms`. In the alternate implementation, identifiers are converted to bit sequences via a Huffman encoding, then the bits are represented as positive numbers. The same identifier is always represented by the same number. However, the numbers are usually bigger than in the original implementation, making PTree operations slower: lookups and updates take time linear in the length of the identifier, instead of logarithmic time in the number of identifiers encountered. The CompCert compiler (the `ccomp` executable) still uses the original implementation, but the `clightgen` tool used in conjunction with the VST program logic can use either implementations: - The alternate "canonical atoms" implementation is used by default, and also if the `-canonical-idents` option is given. - The original implementation is used if the `-short-idents` option is given. Closes: #222 Closes: #311
Diffstat (limited to 'exportclight/ExportClight.ml')
-rw-r--r--exportclight/ExportClight.ml35
1 files changed, 21 insertions, 14 deletions
diff --git a/exportclight/ExportClight.ml b/exportclight/ExportClight.ml
index c9d6fced..87956b58 100644
--- a/exportclight/ExportClight.ml
+++ b/exportclight/ExportClight.ml
@@ -81,8 +81,12 @@ let define_idents p =
string_of_atom
(fun (id, name) ->
try
- fprintf p "Definition _%s : ident := %ld%%positive.@ "
- (sanitize name) (P.to_int32 id)
+ if id = pos_of_string name then
+ fprintf p "Definition _%s : ident := $\"%s\".@ "
+ (sanitize name) name
+ else
+ fprintf p "Definition _%s : ident := %ld%%positive.@ "
+ (sanitize name) (P.to_int32 id)
with Not_an_identifier ->
());
iter_hashtbl_sorted
@@ -93,9 +97,11 @@ let define_idents p =
fprintf p "@ "
let name_temporary t =
- let t1 = P.to_int t and t0 = P.to_int (first_unused_ident ()) in
- if t1 >= t0 && not (Hashtbl.mem temp_names t)
- then Hashtbl.add temp_names t (sprintf "_t'%d" (t1 - t0 + 1))
+ if not (Hashtbl.mem string_of_atom t) && not (Hashtbl.mem temp_names t)
+ then begin
+ let t1 = P.to_int t and t0 = P.to_int (first_unused_ident ()) in
+ Hashtbl.add temp_names t (sprintf "_t'%d" (t1 - t0 + 1))
+ end
let name_opt_temporary = function
| None -> ()
@@ -468,7 +474,7 @@ let print_assertion p (txt, targs) =
| Text _ -> ()
| Param n -> max_param := max n !max_param)
frags;
- fprintf p " | \"%s\"%%string, " txt;
+ fprintf p " | \"%s\", " txt;
list_iteri
(fun i targ -> fprintf p "_x%d :: " (i + 1))
targs;
@@ -495,7 +501,8 @@ let print_assertions p =
let prologue = "\
From Coq Require Import String List ZArith.\n\
From compcert Require Import Coqlib Integers Floats AST Ctypes Cop Clight Clightdefs.\n\
-Local Open Scope Z_scope.\n"
+Local Open Scope Z_scope.\n\
+Local Open Scope string_scope.\n"
(* Naming the compiler-generated temporaries occurring in the program *)
@@ -554,15 +561,15 @@ let name_program p =
let print_clightgen_info p sourcefile normalized =
fprintf p "@[<v 2>Module Info.";
- fprintf p "@ Definition version := %S%%string." Version.version;
- fprintf p "@ Definition build_number := %S%%string." Version.buildnr;
- fprintf p "@ Definition build_tag := %S%%string." Version.tag;
- fprintf p "@ Definition arch := %S%%string." Configuration.arch;
- fprintf p "@ Definition model := %S%%string." Configuration.model;
- fprintf p "@ Definition abi := %S%%string." Configuration.abi;
+ fprintf p "@ Definition version := %S." Version.version;
+ fprintf p "@ Definition build_number := %S." Version.buildnr;
+ fprintf p "@ Definition build_tag := %S." Version.tag;
+ fprintf p "@ Definition arch := %S." Configuration.arch;
+ fprintf p "@ Definition model := %S." Configuration.model;
+ fprintf p "@ Definition abi := %S." Configuration.abi;
fprintf p "@ Definition bitsize := %d." (if Archi.ptr64 then 64 else 32);
fprintf p "@ Definition big_endian := %B." Archi.big_endian;
- fprintf p "@ Definition source_file := %S%%string." sourcefile;
+ fprintf p "@ Definition source_file := %S." sourcefile;
fprintf p "@ Definition normalized := %B." normalized;
fprintf p "@]@ End Info.@ @ "