Skip to content

Commit e824e8c

Browse files
committed
Port native_compute to OCaml 5.
1 parent 2f62807 commit e824e8c

3 files changed

Lines changed: 60 additions & 29 deletions

File tree

kernel/byterun/rocq_values.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,40 @@ value rocq_tcode_array(value tcodes) {
107107
CAMLreturn(res);
108108
}
109109

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

kernel/nativevalues.ml

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -109,23 +109,30 @@ let ret_accu = Obj.repr (ref ())
109109

110110
type accu_val = { acc_atm : atom; acc_arg : t list }
111111

112-
external set_tag : Obj.t -> int -> unit = "rocq_obj_set_tag"
113-
114-
let mk_accu (a : atom) : t =
115-
let rec accumulate data x =
116-
if Obj.repr x == ret_accu then Obj.repr data
117-
else
118-
let data = { data with acc_arg = x :: data.acc_arg } in
119-
let ans = Obj.repr (accumulate data) in
120-
let () = set_tag ans accumulate_tag in
121-
ans
122-
in
123-
let acc = { acc_atm = a; acc_arg = [] } in
124-
let ans = Obj.repr (accumulate acc) in
125-
(** FIXME: use another representation for accumulators, this causes naked
126-
pointers. *)
127-
let () = set_tag ans accumulate_tag in
128-
(Obj.obj ans : t)
112+
113+
(** Returns a pointer to the code of a partial application of [accumulate], yet also recognized as an unscannable block *)
114+
external get_proxy_accu : (accu_val -> t -> t) -> Obj.t option = "rocq_proxy_accu"
115+
116+
[@@@warning "-69"]
117+
type accu_clos = { clos_addr : Obj.t; clos_arity : int; clos_env : Obj.t }
118+
119+
let proxy_accu = ref None
120+
121+
let mk_accu data =
122+
let ans = { clos_addr = Option.get !proxy_accu; clos_arity = 2; clos_env = Obj.repr data } in
123+
(* [ans] is indistinguishable from [accumulate data] *)
124+
(Obj.magic ans : t)
125+
126+
let accumulate data x =
127+
if Obj.repr x == ret_accu then (Obj.magic data : t)
128+
else mk_accu { data with acc_arg = x :: data.acc_arg }
129+
130+
let () =
131+
proxy_accu := get_proxy_accu accumulate
132+
133+
let mk_accu a : t =
134+
let data = { acc_atm = a; acc_arg = [] } in
135+
mk_accu data
129136

130137
let get_accu (k : accumulator) =
131138
(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
@@ -103,10 +103,7 @@ let caml_version_nums { CamlConf.caml_version; _ } =
103103
generic_version_nums ~name:"the OCaml compiler" caml_version
104104

105105
let check_caml_version prefs caml_version caml_version_nums =
106-
if caml_version_nums >= [5;0;0] && prefs.nativecompiler <> NativeNo then
107-
let () = cprintf prefs "Your version of OCaml is %s." caml_version in
108-
die "You have enabled Rocq's native compiler, however it is not compatible with OCaml >= 5.0.0"
109-
else if caml_version_nums >= [4;14;0] then
106+
if caml_version_nums >= [4;14;0] then
110107
cprintf prefs "You have OCaml %s. Good!" caml_version
111108
else
112109
let () = cprintf prefs "Your version of OCaml is %s." caml_version in

0 commit comments

Comments
 (0)