Skip to content

Commit

Permalink
Determine RuntimeID values in configure
Browse files Browse the repository at this point in the history
  • Loading branch information
dra27 committed Oct 4, 2024
1 parent 095026f commit 655372b
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ ___________
runtime assertions.
(Antonin Décimo, review by Miod Vallat, Gabriel Scherer, and David Allsopp)

- #13???: Introduce a RuntimeID for use in filename mangling to allow different
configurations and different versions of the runtime system to coexist
harmoniously on a single system.
(David Allsopp, review by ???)

### Code generation and optimizations:

- #13014: Enable compile-time option -function-sections on all previously
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,7 @@ runtime/build_config.h: $(ROOTDIR)/Makefile.config $(SAK)
$(V_GEN)echo '/* This file is generated from $(ROOTDIR)/Makefile.config */' > $@ && \
echo '#define OCAML_STDLIB_DIR $(call C_LITERAL,$(LIBDIR))' >> $@ && \
echo '#define HOST "$(HOST)"' >> $@
echo '#define BYTECODE_RUNTIME_ID "$(BYTECODE_RUNTIME_ID)"' >> $@

## Runtime libraries and programs

Expand Down
3 changes: 3 additions & 0 deletions Makefile.build_config.in
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,6 @@ TSAN=@tsan@
# Contains TSan-specific runtime files, or nothing if TSan support is
# disabled
TSAN_NATIVE_RUNTIME_C_SOURCES = @tsan_native_runtime_c_sources@

# OCaml release number, relative to 3.12 (used for RuntimeID)
OCAML_RELEASE_NUMBER = @OCAML_RELEASE_NUMBER@
4 changes: 4 additions & 0 deletions Makefile.config.in
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ FUNCTION_SECTIONS=@function_sections@
AWK=@AWK@
NAKED_POINTERS=false

# RuntimeID values
BYTECODE_RUNTIME_ID=@bytecode_runtime_id@
NATIVE_RUNTIME_ID=@native_runtime_id@

# Deprecated variables

## Variables deprecated since OCaml 5.2
Expand Down
4 changes: 4 additions & 0 deletions build-aux/ocaml_version.m4
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ m4_define([OCAML__DEVELOPMENT_VERSION], [true])
m4_define([OCAML__VERSION_MAJOR], [5])
m4_define([OCAML__VERSION_MINOR], [4])
m4_define([OCAML__VERSION_PATCHLEVEL], [0])

# OCAML__RELEASE_NUMBER must be incremented with each minor release.
m4_define([OCAML__RELEASE_NUMBER], [17])

# Note that the OCAML__VERSION_EXTRA string defined below is always empty
# for officially-released versions of OCaml.
m4_define([OCAML__VERSION_EXTRA], [dev0-2024-08-25])
Expand Down
65 changes: 65 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ AC_SUBST([OCAML_VERSION_MINOR], [OCAML__VERSION_MINOR])
AC_SUBST([OCAML_VERSION_PATCHLEVEL], [OCAML__VERSION_PATCHLEVEL])
AC_SUBST([OCAML_VERSION_EXTRA], [OCAML__VERSION_EXTRA])
AC_SUBST([OCAML_VERSION_SHORT], [OCAML__VERSION_SHORT])
AC_SUBST([OCAML_RELEASE_NUMBER], [OCAML__RELEASE_NUMBER])
AC_DEFINE([MAGIC_NUMBER_PREFIX], ["][MAGIC_NUMBER__PREFIX]["])
AC_DEFINE([MAGIC_NUMBER_VERSION], ["][MAGIC_NUMBER__VERSION]["])
AC_DEFINE([EXEC_MAGIC_LENGTH], [MAGIC_NUMBER__LENGTH])
Expand Down Expand Up @@ -257,6 +258,8 @@ AC_SUBST([ocaml_bindir])
AC_SUBST([ocaml_libdir])
AC_SUBST([QS])
AC_SUBST([ar_supports_response_files])
AC_SUBST([bytecode_runtime_id])
AC_SUBST([native_runtime_id])

## Generated files

Expand Down Expand Up @@ -287,6 +290,7 @@ m4_if([OCAML__VERSION_EXTRA],[], [],
AC_DEFINE([OCAML_VERSION_EXTRA], ["][OCAML__VERSION_EXTRA]["])])
AC_DEFINE([OCAML_VERSION], [OCAML__VERSION_NUMBER])
AC_DEFINE([OCAML_VERSION_STRING], ["][OCAML__VERSION]["])
AC_DEFINE([OCAML_RELEASE_NUMBER], [OCAML__RELEASE_NUMBER])

# Works out how many "o"s are needed in quoted strings
AC_CONFIG_COMMANDS_PRE(OCAML_QUOTED_STRING_ID)
Expand Down Expand Up @@ -2674,6 +2678,47 @@ AS_CASE([$host],
# as "Infinity" and "Inf" instead of the expected "inf"
[AC_DEFINE([HAS_BROKEN_PRINTF], [1])])

# Determine the RuntimeID (see runtime/Mangling.md)
m4_define([ALPHABET],
[0123456789abcdefghijklmnopqrstuv])
alphabet='ALPHABET'

m4_cond(OCAML__DEVELOPMENT_VERSION, [true],
[m4_define([ID_VERSION], m4_eval(OCAML__RELEASE_NUMBER << 1))],
[m4_define([ID_VERSION], m4_eval(1 + (OCAML__RELEASE_NUMBER << 1)))])

# Bits 0-4 (release bit + low 4 bits of release number)
m4_define([QUINTET0], [m4_substr(ALPHABET, m4_eval(ID_VERSION & 31), [1])])

# Bits 5-6 (high 2 bits of release number)
quintet1=m4_eval(ID_VERSION >> 5)
# Bit 7 (int31)
AS_IF([! $arch64], [quintet1="4 + ${quintet1}"])
# Bit 8 (no shared libraries)
AS_IF([! $supports_shared_libraries], [quintet1="8 + ${quintet1}"])
# Bit 9 (--enable-naked-pointers) cannot be set since OCaml 5.0
quintet1="$(echo "${alphabet}" | cut -c $(expr ${quintet1} + 1))"

# Bits 10-14 (number of reserved header bits)
quintet2="$(echo "${alphabet}" | cut -c $(expr ${reserved_header_bits} + 1))"

quintet3_byte='0'
# Bit 15 (--enable-frame-pointers)
AS_IF([$frame_pointers], [quintet3_native='1'], [quintet3_native='0'])
# Bit 16 (--enable-spacetime) cannot be set since OCaml 4.12+
# Bit 17 (--disable-force-safe-string) cannot be set since OCaml 5.0
# Bit 18 (--disable-flat-float-array)
AS_IF([! $flat_float_array], [quintet3_byte="8 + ${quintet3_byte}"])
# Bit 19 (WINDOWS_UNICODE=ansi)
AS_CASE([$host,$windows_unicode],
[*-*-mingw32,0|*-pc-windows,0], [quintet3_byte="16 + ${quintet3_byte}"])
quintet3_native="${quintet3_byte} + ${quintet3_native}"
quintet3_byte="$(echo "${alphabet}" | cut -c $(expr ${quintet3_byte} + 1))"
quintet3_native="$(echo "${alphabet}" | cut -c $(expr ${quintet3_native} + 1))"

bytecode_runtime_id="${quintet3_byte}${quintet2}${quintet1}QUINTET0"
native_runtime_id="${quintet3_native}${quintet2}${quintet1}QUINTET0"

# Do not permanently cache the result of flexdll.h
unset ac_cv_header_flexdll_h

Expand Down
82 changes: 82 additions & 0 deletions runtime/Mangling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# File Name Mangling

## Background

OCaml compiler installations exist in isolation. When running the compiler, it
is assumed that the caller will have configured the environment of the compiler
such that files and settings related to other compiler installations will not
interfere.

This is not true of the runtime. For bytecode, multiple different OCaml runtimes
may be "in scope" at the same time. To facilate this, a name mangling scheme is
used for the runtime's files.

## RuntimeID

A RuntimeID is a bitmask describing a given OCaml runtime. Currently, 20 bits
are used; the mangling format is designed to be trivially extensible.

- **Bit 0**: Release bit. This is always set for official released versions of
OCaml and is never set for development/trunk builds or for customised
compilers.
- **Bits 1-6**: OCaml release number; little-endian. This is incremented for
each minor release of the compiler, with OCaml 3.12.0[^1] being release 0. At
present, the ordering of release numbers matches the semantic ordering of the
version numbers, but this is not guaranteed and should not be assumed[^2].
- **Bit 7**: Set if the runtime uses 31-bit `int` values.
- **Bit 8**: Set if the runtime does not support shared libraries.
- **Bit 9**: Set if the runtime is configured with `--enable-naked-pointers`.
- **Bits 10-14**: Number of reserved header bits; little-endian. This is the
value passed to `--enable-reserved-header-bits` when the compiler was
configured.
- **Bit 15**: Set if the runtime is configured with `--enable-frame-pointers`.
- **Bit 16**: Set if the runtime is configured with `--enable-spacetime`.
- **Bit 17**: Set if the runtime is configured with
`--disable-force-safe-string`.
- **Bit 18**: Set if the runtime is configured with
`--disable-flat-float-array`.
- **Bit 19**: Set if the runtime is configured with `WINDOWS_UNICODE=ansi`

The bit description are designed such that the default configuration of the
latest version of the compiler has unset bits.

[^1]: OCaml 3.12.0 was the first version where `ocamlrun` supported the `-vnum`
argument.
[^2]: In particular, should there be any additional releases in the OCaml 4.x
series, these will have higher release numbers than releases already made in the
OCaml 5.x series.

## Masks

A particular configuration of the compiler has one RuntimeID, but this is used
in two different contexts where certain bits are masked out:

1. Bytecode Mask (0xe7fff) is used by `libcamlrun` and masks out the frame
pointers and spacetime bits since these affect neither the runtime nor code
generation in bytecode.
2. Native Mask (0xfffff) is used by `libasmrun`. Note that in native code, the
only place where name mangling is used is natdynlink, and bit 8 is therefore
_never_ set.

## File Name Mangling

Filenames are mangled in two ways.

"triplet-prefixed" files have the _target_ triplet that the compliler was
prefixed with (e.g. `x86_64-pc-linux-gnu`) prepended with an additional hyphen
(e.g. `x86_64-pc-linux-gnu-ocamlrun`).

"Mask-suffixed" files have (RuntimeID & Mask) encoded in base32 using characters
`[0-9a-v]` appended with a prefixing hyphen (e.g. `ocamlrun-0013`)

Mangling is applied to the name of any file which will be loaded at runtime:

- `ocamlrun` (and variants) are triplet-prefixed and Bytecode-suffixed. A
symbolic is created both for `ocamlrun` and for `ocamlrun` Byte-suffixed but
not triplet-prefixed.
- C stub libraries loaded by both the bytecode runtime and bytecode `Dynlink`.
These are triplet-prefixed and Bytecode-suffixed. The effect is that any
runtime attempts to load stub libraries compiled for exactly the same runtime.
- Shared versions of the bytecode and native runtimes (`libcamlrun_shared.so`
and `libasmrun_shared.so`). These are triplet-prefixed and
Bytecode/Native-suffixed respectively.
1 change: 1 addition & 0 deletions runtime/caml/version.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
#undef OCAML_VERSION_EXTRA
#undef OCAML_VERSION
#undef OCAML_VERSION_STRING
#undef OCAML_RELEASE_NUMBER
2 changes: 2 additions & 0 deletions utils/config.common.ml.in
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ let configuration_variables () =
p_bool "systhread_supported" systhread_supported;
p "host" host;
p "target" target;
p "bytecode_runtime_id" bytecode_runtime_id;
p "native_runtime_id" native_runtime_id;
p_bool "flambda" flambda;
p_bool "safe_string" safe_string;
p_bool "default_safe_string" default_safe_string;
Expand Down
2 changes: 2 additions & 0 deletions utils/config.fixed.ml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ let align_double = true
let align_int64 = true
let function_sections = false
let afl_instrument = false
let bytecode_runtime_id = ""
let native_runtime_id = ""
let native_compiler = false
let tsan = false
let architecture = "none"
Expand Down
3 changes: 3 additions & 0 deletions utils/config.generated.ml.in
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ let align_int64 = @align_int64@
let function_sections = @function_sections@
let afl_instrument = @afl@

let bytecode_runtime_id = {@QS@|@bytecode_runtime_id@|@QS@}
let native_runtime_id = {@QS@|@native_runtime_id@|@QS@}

let native_compiler = @native_compiler@

let architecture = {@QS@|@arch@|@QS@}
Expand Down
10 changes: 10 additions & 0 deletions utils/config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,16 @@ val ar_supports_response_files: bool
val tsan : bool
(** Whether ThreadSanitizer instrumentation is enabled *)

val bytecode_runtime_id : string
(** The RuntimeID for ocamlrun and libcamlrun_shared
@since 5.3 *)

val native_runtime_id : string
(** The RuntimeID for libasmrun_shared
@since 5.3 *)

(** Access to configuration values *)
val print_config : out_channel -> unit

Expand Down

0 comments on commit 655372b

Please sign in to comment.