feat: implement System V ABI-compliant C FFI lowering#283
Merged
LunaStev merged 1 commit intoFeb 6, 2026
Merged
Conversation
This commit introduces a robust C calling convention (ABI) lowering
mechanism to the LLVM backend. It allows Wave to interface with external
C functions by correctly handling complex data types (structs and arrays)
according to standard ABI rules, such as SRet, ByVal, and register splitting.
Changes:
- **ABI Lowering Logic (`abi_c.rs`)**:
- Implemented `ParamLowering` and `RetLowering` to classify how types
should be passed (Direct, Split, ByVal, or SRet).
- Added support for **SRet** (Structured Return) to handle large
aggregates via a hidden first parameter.
- Added support for **ByVal** attributes to pass structures by value
with proper ABI alignment.
- Implemented **Split/HFA (Homogeneous Floating-point Aggregate)**
logic to pass small aggregates using multiple floating-point or
vector registers.
- **Backend Infrastructure**:
- Updated the codegen pipeline to initialize and propagate `TargetData`
and `TargetMachine`, enabling accurate size and alignment calculations.
- Introduced `ExternCInfo` to store lowered function metadata and
propagated it through all expression and statement generators.
- Added bit-packing (`pack_agg_to_int`) and unpacking utilities to
facilitate passing small structs via integer registers.
- **Expression & Statement Generators**:
- Refactored `gen_function_call` to check for extern C signatures and
apply necessary ABI transformations (e.g., bit-casting, loading
from SRet pointers, or splitting HFAs).
- Propagated `TargetData` to `generate_lvalue_ir` and other generators
to support context-aware codegen.
- **Cleanup**:
- Removed unused variables and refined internal type inference logic
in the parser and codegen.
These changes ensure that Wave can safely and efficiently invoke
external C libraries, handling complex signatures that involve
passing or returning structures by value.
Signed-off-by: LunaStev <luna@lunastev.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a robust C calling convention (ABI) lowering layer to the Wave compiler's LLVM backend. Until now, calling external C functions was limited to simple types. This update allows Wave to interface with complex C APIs that involve passing or returning structures and arrays by value, strictly adhering to the System V ABI (x86_64) standards.
Key Changes
1. ABI Lowering Logic (
abi_c.rs)Implemented a new lowering engine to classify how Wave types should be translated for the C ABI:
ByValattribute for structures, ensuring they are passed on the stack or in registers with correct alignment as expected by C.pack_agg_to_int) when possible, matching the standard optimization behavior of C compilers.2. Backend Infrastructure & Metadata
TargetDataandTargetMachine. This ensures the compiler has precise information about the host's size and alignment requirements.ExternCInfo: Introduced a metadata container to track lowered function signatures, ensuring that the calling site (at the LLVM level) matches the ABI transformations applied to the declaration.TargetDataand ABI info through all major generators, includinggen_function_callandgenerate_lvalue_ir.3. Refactored Function Calls
gen_function_calllogic has been refactored to check if a target is anextern(c)function. If so, it applies the necessary transformations:4. Maintenance
Example Impact
Previously, passing a struct like
struct Vec2 { x: f32, y: f32 }to a C function might fail if the ABI expected them in a single SSE register. Now, Wave correctly identifies this as an HFA and emits the proper IR to match C's expected register layout.Benefits
structpassing (e.g.,stat,ioctl, or high-performance math libraries).