* Bytecode: hint reads of immediate values
Keep in the bytecode hints the information, known in Lambda, that a
value read from a block field or from an array is an immediate:
- Hint_immediate is recorded on GETFIELD (including the fused
GETGLOBALFIELD and PUSHGETGLOBALFIELD) when the field is Immediate,
and on GETVECTITEM for integer arrays;
- the new C call hint Hint_immediate_result is attached to
caml_array_get_addr for integer arrays.
This lets a compiler from bytecode, such as wasm_of_ocaml, know that
these values are integers, and use an unboxed representation for them.
To carry the information, Kgetfield and Kgetvectitem take the
immediate_or_pointer of the value read.
* Testsuite: dumpobj test for the hints on reads of immediate values
* Bytecode: hint the tests of whether a variant value is an immediate
Add to Pisint a [variant_only] flag, true when the argument is known to
be a value of a variant type, as in flambda-backend. The
pattern-matching compiler sets it for the tests it generates on
constructors and polymorphic variants; %obj_is_int and the inlined
forcing of lazy values (whose result can be any immediate) do not.
Keep this information in the bytecode hints: ISINT gets the new
Hint_variant hint when the flag is set.
A compiler from bytecode where some integers are boxed can then test
whether such a value is an immediate with a single check, since constant
constructors are never boxed. This is the case of an experimental
version of wasm_of_ocaml with 63-bit integers, where large integers are
boxed: testing whether any value is an immediate takes two type tests,
and, when the value is a block, both are performed.
* Testsuite: dumpobj test for the hints on tests of variant values
* Changes entry for #15122
* Add primitives converting between floats and boxed integers
* Use the new primitives for Int64.of_float and friends
* Changes entry for #15084
* Bootstrap
* Keep the C call for Int32.of_float
* Add Iatomic_fetch_add machine operation for native atomics
This is the machine-level infrastructure for compiling atomic
fetch-and-add to native instructions instead of C runtime calls.
* Add TSan instrumentation for Iatomic_fetch_add
* amd64: add caml_domain_alone fast path for Iatomic_fetch_add
* arm64: add trailing dmb st release barrier to fetch-and-add
* power, riscv: trailing release fence after atomic fetch-and-add
%standard_library_default allows Config.standard_library_default to be
converted to a compile-time derived value, as with existing compile-time
constants such as %backend_type, etc. This paves the way for allowing
Config.standard_library_default to be changed at link-time, rather than
fixed when the Config module itself is compiled.
This is a copy of Asttypes.constant minus the string case.
It ensures that there is a single way to represent constant strings,
and allows to remove a few pieces of duplicated code.
Lazy blocks are very special, in that a value bound to a lazy block may,
at any moment, completely change its shape (it could become an immediate,
or any other kind of value).
By splitting these blocks from the regular blocks, we allow the middle-end
to assume that any Pmakeblock behaves as a normal block, making all
related optimisations safer.
In passing, this also fixes an issue with Forward blocks in recursive definitions.
The Patomic_load primitive represents atomic loads (Atomic.get), and
it tracks whether the load type only contains immediate values, or
whether it contains both immediates and pointers. This comes at a
small cost in complexity in the compiler source, but is in fact
completely useless for two reasons:
1. We made a mistake in atomic.mli, which results in the information
*never* being upgraded to Immediate: we declare
`val get : 'a t -> 'a` instead of `external get : ...`,
and as a consequence the compiler never specializes this primitive.
(You can test this by compiling
`let f (n : int Atomic.t) = Atomic.get n`
and looking at the lambda or cmm output.)
2. The backend does not in fact depend on whether the value is
immediate or not: even if we did track this information correctly,
there would be no change in the generated code.
(We checked this by reviewing atomic-load code production in all
emit.mlp backends.)
This simplification will help (modestly) simplify the code of an
upcoming PR on atomic record fields.
Co-authored-by: Clément Allain <clef-men@orange.fr>
Reviewed-by: KC Sivaramakrishnan <kc@kcsrk.info>
In trunk, all atomic functions exposed in the runtime are also exposed
as language primitives in our intermediate representations (lambda,
clambda). But except for `Patomic_load`, which benefits from
dedicated code generation, they are all transformed into C calls
on all backends.
The present PR simplifies the code noticeably by removing the
intermediate primitives, by producing C calls directly in
lambda/translprim.ml.
This reduces the amount of boilerplate to modify to implement
atomic record fields (https://github.com/ocaml/RFCs/pull/39).
Co-authored-by: Clément Allain <clef-men@orange.fr>
This commit refactors the types that make up type-checking errors to
maintain more structural information. Most significantly, we split
out the errors we get from unification, moregen, and type equality in
`Ctype` into three distinct exceptions, and retain the sorts of
information we keep during unification in the other two cases as well
(no more `Unify []`). We also maintain more information in
`Includecore` about mismatches of primitives, manifests, and private
objects and variants
This commit doesn't make a lot of changes to the user-visible error
messages yet, only what's necessary to support the type changes, but
it enables a forthcoming patch where we use this improvement to
produce more informative error messages.
This commit includes existing work by Mekhrubon Tuarev, who did all
the early development. I (Antal Spector-Zabusky) came and built the
layer of types on top.