Early engine prototypes resolved Extern(Library:…) via dlopen/dlsym. That complicates reproducible AOT artifacts and blurs security review of loaded code.
Flow and algorithm
Platform spec article
Flow and algorithm
Spec standingStandard
-
User foreign libraries resolve at link time; dlopen remains legacy.
Context
Decision
Track Status Link-time Standard for v0.3 — addresses fixed before execution via C ABI profile Dynamic extern_dlopenProposed / legacy — engine feature only; not required for reference CLI Validation High-level Beskid types in extern signatures must be rejected before codegen Syscalls User externs must not embed OS syscall sequences — see Panic, IO, and syscalls Consequences
New platform work documents link-time flows first. Dynamic resolution stays gated behind
extern_dlopeninbeskid_engine.Verification anchors
compiler/crates/beskid_analysisextern validation;beskid_enginelink paths. -
Compiler thunks call stable dispatch entrypoints for language/runtime interop layouts.
Context
Tagged interop values need runtime-known layout offsets. Per-site custom trampolines would fork ABI stability.
Decision
Builtin family Role interop_dispatch_unitUnit-tagged dispatch interop_dispatch_ptrPointer payloads interop_dispatch_usizeScalar bridge Layout stability Offsets are versioned with ABI versioning Implementation beskid_runtime::interopexports registered inBUILTIN_SPECSLowering must route approved tagged calls through these builtins rather than ad-hoc host calls.
Consequences
Interop layout changes require ABI bump or additive symbol policy per D-EXEC-ABI-0002.
Verification anchors
compiler/crates/beskid_runtime/src/interop/; interop lowering tests.
- Contracts and edge cases MUST rules for extern validation, dynamic linking policy, and interop dispatch layout.
- Design model Extern resolution layers, runtime dispatch builtins, and host policy boundaries.
- Examples Declaring Extern contracts, dynamic getpid smoke, and interop dispatch usage patterns.
- FAQ and troubleshooting Extern linking failures, dlopen policy, and interop dispatch debugging.
- Flow and algorithm Extern validation, link registration, optional dlopen resolution, and interop dispatch calls.
- Verification and traceability Engine extern tests, analysis diagnostics, and interop layout traceability.
0 revisions (git unavailable at build; counts may be empty)
No commits recorded for this path.
| Section id | Required | Found |
|---|---|---|
what-this-feature-specifies | yes | yes |
implementation-anchors | yes | yes |
Full tree: run pnpm verify:platform-spec-layout (writes src/generated/platform-spec-layout-report.json).
Purpose
Section titled “Purpose”Step-by-step flow from source Extern to executable call target. Actor diagram: design model.
Compile-time validation
Section titled “Compile-time validation”- Parser records
ExternABI string (typically"C") and optionalLibraryfor dynamic profiles. - Semantic analysis rejects Beskid-only types in extern parameter/return positions.
declare_validated_extern_imports(beskid_codegen) maps each extern to a Cranelift signature; invalid shapes becomeExternDeclarationError::InvalidSignature.
JIT link without dynamic externs
Section titled “JIT link without dynamic externs”BeskidJitModule::new()registers runtime builtins only.declare_validated_extern_importsdeclares extern imports; addresses must be supplied by the linker or pre-resolvedextrastable before execution.remap_testcase_externalsrewrites CLIF external names to registeredFuncIds during define.
Optional dynamic resolution (extern_dlopen)
Section titled “Optional dynamic resolution (extern_dlopen)”When the engine feature is enabled on Linux x86_64:
- For each distinct
(library, symbol)in the artifact,dlopen(RTLD_LOCAL | RTLD_NOW)once per process. dlsymresolves the symbol; failures includedlerror()text in diagnostics.- Process-lifetime caches deduplicate libraries and symbols across compilation units.
BeskidJitModule::new_with_symbolspasses(name, *const u8)pairs into the JIT builder so Cranelift imports bind to resolved addresses.
When the feature is disabled, artifacts containing externs must fail compilation with an explicit list of unresolved symbols (EXT-001).
Runtime interop dispatch path
Section titled “Runtime interop dispatch path”- Lowering passes a tagged interop handle (header + discriminant + payload per
interop_layout.rs). - Generated code calls
interop_dispatch_unit,interop_dispatch_ptr, orinterop_dispatch_usizedepending on return shape. - Runtime reads tag at offset +8 and payload at +16 from the object header (v0.2 baseline; ABI-bumped if layout changes).
Related topics
Section titled “Related topics”- Contracts and edge cases
- Examples —
getpidsmoke pattern