C Runtime Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The C Runtime Architecture of the Jazz project serves as the bridge between high-level functional constructs and low-level machine execution. It primarily facilitates the interaction between the Jazz compiler and the LLVM backend through a Foreign Function Interface (FFI). This architecture is critical for implementing the planned LLVM backend and performance targets, moving beyond the initial functional subsets.
The runtime environment encompasses memory management, JIT (Just-In-Time) compilation layers, and primitive semantics contracts. It handles the transition from Jazz's immutable bindings and first-class functions into executable machine code, supporting features like currying and partial application through runtime helpers.
Sources: README.md:12-25, jazz-next/README.md:21-25
Core Runtime Components
The runtime is structured around several key C++ and C components that wrap LLVM functionality to provide a stable execution environment for Jazz code.
JIT Compilation Layers (OrcV2)
The runtime utilizes LLVM's OrcV2 JIT infrastructure to manage dynamic code execution. It defines layers for object linking and IR compilation, allowing the compiler to add modules and look up symbols during execution.
- ExecutionSession: Manages the state of the JIT environment, including symbol resolution and error handling.
- ObjectLinkingLayer: Handles the linking of compiled object files into the current process.
- IRCompileLayer: Responsible for transforming LLVM IR into machine code using a
SimpleCompiler.
The diagram above illustrates the flow of a module through the JIT layers to reach a state where symbols can be resolved for execution.
Sources: jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/OrcJITC.cpp:57-128
Primitive Semantics and Contracts
The runtime defines a strict contract for primitive operations, ensuring consistent behavior across different execution targets. This includes a defined "Runtime Failure Model" for handling illegal operations at the hardware or software level.
| Component | Description |
|---|---|
| Primitive Contract Table | Defines the expected behavior of fundamental types (Int, Bool, etc.). |
| Equality Contract | Specifies how deep or shallow equality is handled at the C level. |
| Runtime Failure Model | Defines behaviors for overflows, division by zero, and invalid memory access. |
Sources: scripts/check-clarification-specs.sh:49-53
Execution and Memory Management
Thread-Safe Contexts
To support concurrent compilation and execution, the runtime implements thread-safe wrappers around LLVM Contexts and Modules. This prevents race conditions when the Jazz compiler is performing multi-threaded analysis or code generation.
- ThreadSafeContext: A wrapper around
llvm::LLVMContext. - ThreadSafeModule: A container that ensures a module and its associated context are moved together safely between threads.
Sources: jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/OrcJITC.cpp:78-106
Target Machine Configuration
The runtime explicitly configures the target machine architecture, which is necessary for generating optimized code specific to the host system. This includes setting relocation models (Static, PIC) and optimization levels (None, Less, Default, Aggressive).
Runtime Interoperability (FFI)
The runtime provides a set of C-compatible functions (extern "C") that allow the Haskell-based compiler to manipulate LLVM structures directly. This layer is essential for the "Bundled-prelude" runtime helpers such as print!, map, and filter.
Key FFI Functions
| Function Name | Purpose |
|---|---|
LLVM_Hs_createExecutionSession | Initializes the JIT execution environment. |
LLVM_Hs_IRLayer_addModule | Adds a compiled module to a specific JIT dynamic library. |
LLVM_Hs_ExecutionSession_lookupSymbol | Retrieves the memory address of a function or variable by name. |
LLVM_Hs_GetTargetMachineDataLayout | Extracts the data layout (alignment, sizes) for the target C environment. |
LLVM_Hs_ModuleAppendInlineAsm | Allows raw assembly injection into the runtime module. |
Sources: jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/OrcJITC.cpp:155-168, jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/TargetC.cpp:324-327, jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/ModuleC.cpp:73-75
Metadata and Debugging Support
The runtime architecture includes extensive support for DWARF debug metadata. This allows the Jazz runtime to provide meaningful stack traces and debugging information by mapping machine code back to Jazz source positions (DILocation).
- DILocation: Tracks line and column numbers in the source file.
- DISubprogram: Describes functions and their scopes for debuggers.
- DIBasicType: Maps Jazz types to DWARF-encoded primitive types.
Sources: jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/MetadataC.cpp:143-160, jazz-hs/local-deps/llvm-hs/src/LLVM/Internal/FFI/Metadata.h:11-40
Summary
The C Runtime Architecture in Jazz is a robust layer built upon LLVM OrcV2 and DWARF standards. It provides the necessary infrastructure for JIT compilation, thread-safe module management, and cross-language communication via FFI. By enforcing strict primitive contracts and providing target-specific machine configurations, it ensures that the functional semantics of the Jazz language are accurately and efficiently translated into executable machine code.