Skip to content

Commit 21acf13

Browse files
committed
Port native_compute to OCaml 5.
1 parent 3d5120e commit 21acf13

File tree

3 files changed

+52
-30
lines changed

3 files changed

+52
-30
lines changed

kernel/byterun/coq_values.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,32 @@ value coq_tcode_array(value tcodes) {
107107
CAMLreturn(res);
108108
}
109109

110-
CAMLprim value coq_obj_set_tag (value arg, value new_tag)
111-
{
112-
#if OCAML_VERSION >= 50000
113-
// Placeholder used by native_compute
114-
abort();
115-
#else
116-
Tag_val (arg) = Int_val (new_tag);
117-
#endif
118-
return Val_unit;
110+
code_t coq_accumulate_addr;
111+
112+
value coq_proxy_accu(value clos) {
113+
value v;
114+
CAMLassert(Tag_val(clos) == Closure_tag && Arity_closinfo(Closinfo_val(clos)) == 2);
115+
/* Field 2 of the closure contains the code pointer for the arity-2 direct call. */
116+
coq_accumulate_addr = ((code_t *)clos)[2];
117+
/* The following assembly block does not perform any meaningful computation;
118+
it just returns a pointer to the inner code (notice the initial "jmp").
119+
The inner code translates the call "foo x" (i.e., "%apply x foo") into
120+
"accumulate foo.2 x". For both calls, the two arguments are stored in %rax
121+
and %rbx, while register %rdi is caller-saved. */
122+
asm("jmp 1f\n\t"
123+
".align 8\n\t"
124+
".quad 3067\n"
125+
"2:\n\t"
126+
"mov %%rax, %%rdi\n\t"
127+
"mov 16(%%rbx), %%rax\n\t"
128+
"mov %%rdi, %%rbx\n\t"
129+
"mov coq_accumulate_addr@GOTPCREL(%%rip), %%rdi\n\t"
130+
"jmp *(%%rdi)\n"
131+
"1:\n\t"
132+
"lea 2b(%%rip), %0\n\t"
133+
: "=r"(v));
134+
/* v is a pointer that can be used as field 0 of an OCaml closure. But it is
135+
also a pointer to a block that is ignored by the garbage collector (notice
136+
the header 3067). So, v can be put inside closures that do not have tag 247. */
137+
return v;
119138
}

kernel/nativevalues.ml

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,23 +121,29 @@ let ret_accu = Obj.repr (ref ())
121121

122122
type accu_val = { mutable acc_atm : atom; acc_arg : t list }
123123

124-
external set_tag : Obj.t -> int -> unit = "coq_obj_set_tag"
125-
126-
let mk_accu (a : atom) : t =
127-
let rec accumulate data x =
128-
if Obj.repr x == ret_accu then Obj.repr data
129-
else
130-
let data = { data with acc_arg = x :: data.acc_arg } in
131-
let ans = Obj.repr (accumulate data) in
132-
let () = set_tag ans accumulate_tag in
133-
ans
134-
in
135-
let acc = { acc_atm = a; acc_arg = [] } in
136-
let ans = Obj.repr (accumulate acc) in
137-
(** FIXME: use another representation for accumulators, this causes naked
138-
pointers. *)
139-
let () = set_tag ans accumulate_tag in
140-
(Obj.obj ans : t)
124+
(** Returns a pointer to the code of a partial application of [accumulate], yet also recognized as an unscannable block *)
125+
external get_proxy_accu : (accu_val -> t -> t) -> Obj.t = "coq_proxy_accu"
126+
127+
[@@@warning "-69"]
128+
type accu_clos = { clos_addr : Obj.t; clos_arity : int; clos_env : Obj.t }
129+
130+
let proxy_accu = ref None
131+
132+
let mk_accu data =
133+
let ans = { clos_addr = Option.get !proxy_accu; clos_arity = 2; clos_env = Obj.repr data } in
134+
(* [ans] is indistinguishable from [accumulate data] *)
135+
(Obj.magic ans : t)
136+
137+
let accumulate data x =
138+
if Obj.repr x == ret_accu then (Obj.magic data : t)
139+
else mk_accu { data with acc_arg = x :: data.acc_arg }
140+
141+
let () =
142+
proxy_accu := Some (get_proxy_accu accumulate)
143+
144+
let mk_accu a : t =
145+
let data = { acc_atm = a; acc_arg = [] } in
146+
mk_accu data
141147

142148
let get_accu (k : accumulator) =
143149
(Obj.magic k : Obj.t -> accu_val) ret_accu

tools/configure/configure.ml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ let caml_version_nums { CamlConf.caml_version; _ } =
101101
generic_version_nums ~name:"the OCaml compiler" caml_version
102102

103103
let check_caml_version prefs caml_version caml_version_nums =
104-
if caml_version_nums >= [5;0;0] && prefs.nativecompiler <> NativeNo then
105-
let () = cprintf prefs "Your version of OCaml is %s." caml_version in
106-
die "You have enabled Coq's native compiler, however it is not compatible with OCaml >= 5.0.0"
107-
else if caml_version_nums >= [4;9;0] then
104+
if caml_version_nums >= [4;9;0] then
108105
cprintf prefs "You have OCaml %s. Good!" caml_version
109106
else
110107
let () = cprintf prefs "Your version of OCaml is %s." caml_version in

0 commit comments

Comments
 (0)