Context.Cc_backendThe cc backend's own module, re-exported because the library's interface module is this one and a test outside arrayjit can otherwise not name it. What needs naming is Cc_backend.compiler_command: the generated-kernel census (test/operations/cc_march_census.ml, gh-ocannl-650) compiles emitted sources under foreign -march flags, and it must do so with the SAME toolchain that builds them for real -- a census against a different compiler would describe guarded arms nothing here selects. The interface is cc_backend.mli's, so this exposes no more than that file already publishes.
include Ir.Backend_impl.Lowered_no_device_backendinclude Ir.Backend_impl.Bufferval codegen_capabilities : Base.unit -> Ir.Backend_intf.codegen_capabilitiesval sexp_of_procedure : procedure -> Sexplib0.Sexp.tval compile :
name:Base.string ->
Ir.Indexing.unit_bindings ->
Ir.Low_level.optimized ->
procedureval compile_batch :
names:Base.string Base.array ->
Ir.Indexing.unit_bindings ->
Ir.Low_level.optimized Base.array ->
procedure Base.arrayCompiles the given procedures -- the segment kernels of one fissioned routine -- as a single compilation unit: one generated source and one C-compiler invocation, with the resulting (dyn-loaded) library shared by every returned procedure.
val link_compiled :
?lowered_bindings:Ir.Indexing.lowered_bindings ->
merge_buffer:Ir.Backend_intf.buffer_loc Base.option Base.ref ->
resolve:(Ir.Backend_intf.buffer_loc -> buffer_ptr) ->
runner_label:Base.string ->
Ir.Backend_intf.ctx_buffers ->
procedure ->
Ir.Indexing.lowered_bindings * Ir.Task.tresolve is the device's backend-private buffer_loc -> base lookup, supplied at the backend boundary so that the shared layer never handles a raw pointer: this function resolves both the context's ctx_buffers (eagerly, at link time) and the lazily-set merge_buffer (at execution time). runner_label is get_name device of the device holding the buffers. lowered_bindings, when given, supplies the static-index refs to bind (looked up by symbol) instead of freshly minted ones, and is returned as-is: procedures linked as a batch — in particular the segment kernels of one fissioned routine — must share their binding refs, so setting a static index through the routine's bindings reaches every kernel.
include Ir.Backend_impl.No_device_buffer_and_copying
with type buffer_ptr := buffer_ptrinclude Ir.Backend_impl.Buffer with type buffer_ptr := buffer_ptrval sexp_of_buffer_ptr : buffer_ptr -> Sexplib0.Sexp.tReturns (an upper bound of) the memory used for arrays, in bytes.
Raw slab primitives used by Make_slab to back the device-level Backend_intf.Slab_alloc. They allocate / free / zero contiguous backend buffers by byte size; pool-id bookkeeping lives in the shared slab wrapper.
val alloc_pool_raw : size_in_bytes:Base.int -> buffer_ptrval free_pool_raw : (buffer_ptr -> Base.unit) Base.optionval memset_zero_raw :
buffer_ptr ->
offset:Base.int ->
size_in_bytes:Base.int ->
Base.unitval offset_buffer : buffer_ptr -> bytes:Base.int -> buffer_ptrReturns a handle for the slab pointer advanced by bytes. Used by Make_slab.resolve_pool to turn a { pool_id; offset } into the concrete pointer for a sub-region of a multi-tenant pool. For bytes = 0 this must return the base unchanged.
val buffer_to_buffer :
dst:buffer_ptr ->
src:buffer_ptr ->
size_in_bytes:Base.int ->
Base.unitval host_to_buffer : Ir.Ndarray.t -> dst:buffer_ptr -> Base.unitval buffer_to_host : Ir.Ndarray.t -> src:buffer_ptr -> Base.unitThe C compiler command this backend builds kernels with: cc_backend_compiler_command when set, else the toolchain's own C compiler as reported by ocamlc -config. Exposed for the generated-kernel census (gh-ocannl-650), which must compile the emitted sources with the SAME toolchain that will build them for real -- a census run against a different compiler would describe guarded arms nothing here selects.
The flags a kernel compile passes after compiler_command: optimization level, arch and SIMD flags, fast math, contraction and the parallel-grid runtime, all resolved. Exposed for test/operations/bridge_arm_coverage (gh-ocannl-1145), which preprocesses retained kernel sources under exactly these flags to read which storage-bridge arm each one compiled into.
Whether the kernel compile pins contraction off (cc_backend_fp_contract=off, placed after any -ffast-math; Compiler_options.clang_contraction_off over the flags in compile order): the cc C_syntax_config.compiler_contraction_off (gh-ocannl-1457).
Resolves every executable token in a compiler command and fingerprints its path, size and modification time. Exposed for the generated-kernel census's persistent listing identity: an in-place toolchain replacement must not replay assembly from the previous executable.
Whether this backend renders the outermost Grid loops it proves safe as concurrent chunks of the native pool — the gate of C_syntax.collect_parallel_grid: a pool syntax was probed, more than one chunk is configured, and no kernel logging is on. Exposed so a test can say what a bound grid axis means on cc (gh-ocannl-959): a binding the legality check judges where this holds, a serial loop where it does not.
The vector register width in bytes for the explicit SIMD renderings (config cc_vector_bytes; auto-probed when unset). Read by vector_file_setting, and alone wherever only the width matters.
What vector_bytes_setting answers when cc_vector_bytes is unset: the widest vector the configured target holds (64 with AVX-512 F/BW/VL, 32 with AVX2, else 16). Exposed for test/operations/bridge_arm_coverage, which forces every width up to this one.
val vector_file_setting : unit -> Ir.Vector_file.tThe vector register file of the explicit SIMD renderings, width and count as one value (gh-ocannl-1399): the vector_bytes_setting width, and how many registers of that width the kernels' target has (config cc_vector_registers; auto-probed when unset) -- the native file's count, 32 on AArch64 and AVX-512, 16 on other x86 targets, probed under the kernel flags -- divided where the width is wider than a native register; 0 registers when explicit SIMD is off. Exposed for Schedulers.cpu_mma_limits's simd_vector, which the register tile's Register_tile.rn_cap reads in the seeding, as the renderer does here (gh-ocannl-1285).
The worker-pool width after the pool policy: the restricted class's logical CPU count when the restriction fired, the process's affinity-respecting CPU count otherwise. Sizes the auto cc_parallel_chunks.
Compact pool signature (w8P, w24, ...) identifying the pool the process executes on. Exposed for Schedulers.cpu_mma_limits's worker_pool_tag: schedules crowned on one pool do not transfer to another (gh-ocannl-530), so the tag enters the autotune disk-cache key.
val timing_identity : unit -> Ir.Backend_intf.timing_identity optionCPU model and host partition, plus observed compiler target/executable metadata and macOS hardware UUID/OS build when available. OpenMP and non-macOS persistence remain supported. Executable provenance retains the probe cache's path/size/mtime contract; opaque wrappers and separately updated runtime libraries are not completely fingerprinted.
A short digest of this backend's resolved codegen configuration: the compiler command and its flags, the vector width, the fp16-arithmetic support, the parallel-grid syntax and chunking, and the per-chunk privatization cap. Exposed for Schedulers.cpu_mma_limits's Ir.Backend_intf.hardware_limits.codegen_tag: these settings are consulted at codegen, after the lowered code the canonical digest names, so they enter the autotune disk-cache key (gh-ocannl-572) and a knob flip re-tunes rather than replaying a winner from another codegen regime.
Which kind of host this process runs on, as the kernels see it (gh-ocannl-1371): the CPU model, the logical CPU count and pool tag, the ISA the SIMD probes found under the kernel flags (avx2+fma, avx512f+bw+vl, neon), the resolved vector_bytes_setting beside auto_vector_bytes, the register count of vector_file_setting and the native register file, the fp16 arithmetic support, and the compiler with the arch and SIMD flags those were resolved under. Read from the same probes and settings the renderer reads, so it cannot disagree with them. tools/host_caps.exe prints it as the header line of every CI build job: GitHub's x86 runners come with or without AVX-512, and the auto-probed width changes what the autotune pre-filter keeps.
Whether the configured C compiler and target execute _Float16 arithmetic natively, at twice f32's lane count (ARMv8.2-FP16, AVX512-FP16) -- as opposed to lacking the type, or having it with every operation promoted to float (correct, but no throughput win). Probed once per process by test-compiling; overridable with cc_fp16_arithmetic. Exposed for Schedulers.cpu_mma_limits's native_fp16_arithmetic and for the compute-precision decision in CC_syntax_config.
Platform-specific kernel shared-library flags. In particular, ELF kernels bind their own builtin calls locally even when the host stubs use a different native-half ABI. Runtime compiler probes use this same policy rather than restating the linker flags.
val compile_failure_detail :
exit_code:int ->
source_note:string ->
command:string ->
compiler_output:string ->
stringThe detail of the Backend_rejected a failed C compile raises: the exit code, the Ir.C_syntax.codegen_bug_claim asking for source_note's file, the command and the compiler's output. Exposed so a test can hand Ir.C_syntax.attribute_routine_name_failure the report this backend actually raises: attributed to a routine's name, it is quoted without that claim; not attributed, it propagates with the claim intact.
gh-ocannl-1603: how a cc compile is split. part_weight: a kernel weighing more than sixteen parts of this weight is rendered outlined, into noinline parts it calls in order (0: never; config cc_kernel_part_weight). jobs: a batch is compiled as up to this many translation units, by concurrent compiler processes, linked into one library (cc_compile_jobs; always 1 off Unix). unit_min_bytes: the least source a unit holds (cc_compile_unit_min_bytes).
val split_settings : unit -> split_settingsThe settings in force: the configuration, or with_split_settings's.
val with_split_settings : split_settings -> (unit -> 'a) -> 'aRuns f with these settings instead of the configured ones, then restores the previous ones: for a test comparing a split compile with a whole one in one process. Not domain-local.
How many translation units this process has compiled as parts of a split batch (each unit of a batch split into several counts; an unsplit compile counts none).
type load_refusal = | Load_defectAnything else, an undefined symbol or a missing dependency in particular: the kernel's link line is OCANNL's bug (gh-ocannl-1077).
*)| Code_signing_refusalThe loader's code-signing or system policy refused the library (macOS dyld).
*)| Library_missingThe library the compiler built is not there to load.
*)val sexp_of_load_refusal : load_refusal -> Sexplib0.Sexp.tval equal_load_refusal : load_refusal -> load_refusal -> boolval classify_load_refusal : library_present:bool -> string -> load_refusalclassify_load_refusal ~library_present dlerror says why dlopen refused a library the compile produced (gh-ocannl-1717): the two environment classes are reported as Schedule_outcome.Environment rejections, Load_defect as a Compiler_bug. The signing class is read off the text; the missing class off library_present alone (whether the library's path exists after the refusal), since a missing dependency and a signing refusal's list of tried paths both read like a missing file. Exposed for test/operations/cc_load_refusal_classes.
val load_refusal_severity : load_refusal -> Ir.Schedule_outcome.severityThe severity of the dlopen-stage rejection each class raises: Compiler_bug for Load_defect, Environment for the other two.
Seconds load_retrying_signing_refusal's caller in the backend pauses before its one retry.
type 'lib load_outcome = | Loaded of 'lib| Loaded_on_retry of {}| Refused of {refusal : load_refusal;dlerror : string;first_dlerror : string option;}refusal classifies the last attempt's dlerror; first_dlerror is set when that attempt was the retry.
val load_retrying_signing_refusal :
load:(unit -> ('lib, string) Stdlib.Result.t) ->
pause:(unit -> unit) ->
library_present:(unit -> bool) ->
'lib load_outcomeload_retrying_signing_refusal ~load ~pause ~library_present runs load (a dlopen, its Error the dlerror()) and, when classify_load_refusal reads the refusal as a Code_signing_refusal, calls pause and load exactly once more (gh-ocannl-1728). Measured on arm64 macOS before adding it: dyld keeps no verdict on a refused path, so a reload after the cause clears succeeds, while a library the policy keeps refusing is refused again. The other classes are not retried. Exposed for test/operations/cc_load_refusal_classes.