Sarek_opencl.Opencl_fpRaised when a build-option string would relax float semantics below what docs/fp-contraction-policy.md §1 promises.
The vendored dependencies/CL/cl.h is OpenCL 1.0-era and defines neither of the two bits this module needs, so they are spelled out. Values from the OpenCL 1.2+ headers.
conformance_options ~single_fp_config is the option list Sarek chooses on its own behalf, given a device's CL_DEVICE_SINGLE_FP_CONFIG.
The full audit of what an empty option string was silently accepting, and what is now decided explicitly. Every entry is a DEFAULT that was being inherited rather than chosen:
-cl-fp32-correctly-rounded-divide-sqrt — ADDED, gated on CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT. Default off means sqrt up to 3 ulp and divide up to 2.5 ulp; §1 requires both correctly rounded, and Sarek_df64's Newton/Karp step squares its seed's error and has no margin for a 3-ulp seed. Gated because the spec makes it an error to pass it otherwise (see the header).-cl-denorms-are-zero — NEVER PASSED. It is a HINT that the device may flush binary32 subnormals; §1 says subnormals are not flushed. Its default (absent) is the conformant one, so the fix is to keep not passing it — but note this is a request, not a guarantee in either direction: whether subnormals actually survive is CL_FP_DENORM in the device's config, and on BOTH local devices that bit is CLEAR, so f32 subnormals are flushed here regardless of any build option. That is a device property Sarek cannot correct, and it is recorded rather than fixed.-cl-fast-relaxed-math — NEVER PASSED, and REFUSED from callers. It implies -cl-unsafe-math-optimizations and -cl-finite-math-only, and additionally lets the implementation substitute native_* builtins.-cl-unsafe-math-optimizations — NEVER PASSED, REFUSED. Permits reassociation, which destroys an error-free transformation outright (§1 corollary 1); implies -cl-no-signed-zeros and -cl-mad-enable.-cl-finite-math-only — NEVER PASSED, REFUSED. Assumes no NaN/Inf operand; the interpreter oracle assumes no such thing.-cl-no-signed-zeros — NEVER PASSED, REFUSED. Discards the sign of zero, which Sarek_df64's renormalisation steps rely on.-cl-mad-enable — NEVER PASSED, REFUSED. This is the contraction hazard by name: it permits a*b+c to become a mad of reduced accuracy.-cl-single-precision-constant — NEVER PASSED, REFUSED. Silently demotes double literals to single, changing the meaning of a written constant.-cl-opt-disable — not passed, and ALLOWED from a caller: it is conservative, it cannot relax FP semantics, and it is useful for debugging codegen.Deliberately NOT here: anything that would need to be undone later. Unlike HIP — where appending -ffp-contract=off LAST neutralises whatever the caller passed, because clang resolves conflicting FP options by last occurrence — OpenCL has no build option that undoes -cl-fast-relaxed-math. So the relaxing options are REFUSED rather than countered, for the same reason Cuda_nvrtc refuses -use_fast_math (docs/fp-contraction-policy.md §5).
(token, verdict, why).
Every OpenCL FP option is a BARE SWITCH — none takes a value, inline or separated. That is why this screen can match on whole tokens and does not need Cuda_nvrtc's value-resolution machinery, which exists because nvrtc accepts --ftz true as two array elements and a spelling-shaped matcher let the separated form straight through (§5). The hazard has no OpenCL analogue; if a future OpenCL option ever takes a value, this comment is the warning that this matcher is then the wrong shape.
Split an OpenCL build-option string on whitespace. OpenCL takes ONE string, not an array, so this is the only tokenisation there is.
val fp_scan : string -> fp_verdict listRaise Fp_conformance_violation on a caller option string that would relax float semantics; warn on the merely redundant.
Pure: no device, no OpenCL ICD and no libOpenCL are needed to run it, so it is reachable in a test suite on a host with no OpenCL at all — the same property that makes Cuda_nvrtc.check_fp_conformance testable without CUDA.
build_options ~single_fp_config ~caller is the complete option string clBuildProgram receives.
caller is screened first — so an offending option raises BEFORE any OpenCL entry point is touched — and Sarek's own options are appended after it. Ordering carries no meaning here (no OpenCL FP option overrides another, unlike clang's last-occurrence rule that Hip_rtc.base_options depends on); the options are appended last purely so the resulting string reads as "what the caller asked for, then what this backend requires".