Freestanding C Binding
This section defines the compiler-runtime and ELF linkage obligations of the freestanding C profile. It covers compiler-generated helper calls, C symbols, and ELF linkage.
Compiler Runtime Helpers
The compiler lowers addition, subtraction, negation, bitwise operations, comparisons, truncation, and extension of 128-bit integers inline. It may call one of the helpers below for 128-bit multiplication, division, remainder, and shifts; conversion between a 128-bit integer and a supported floating-point type; or complex multiplication and division.
Every compiler-runtime helper is an ordinary bedrock-c function. Its arguments and results therefore follow Section 5, including the R1:R0 return convention for __int128.
The tables below are the complete baseline helper set. A compiler emits implicit references from this set or from a target extension that defines the symbol and its ABI. A runtime may export additional symbols as explicit interfaces.
In the signature column, i128 means __int128, u128 means unsigned __int128, c32 means float _Complex, and c64 means double _Complex. The signatures use ordinary C parameter and result classification; a shift count has type int.
__int128 Arithmetic and Shift Helpers
| Operation | Helper | Signature |
|---|---|---|
| Multiply | __multi3 |
i128(i128, i128) |
| Signed divide | __divti3 |
i128(i128, i128) |
| Unsigned divide | __udivti3 |
u128(u128, u128) |
| Signed remainder | __modti3 |
i128(i128, i128) |
| Unsigned remainder | __umodti3 |
u128(u128, u128) |
| Shift left | __ashlti3 |
i128(i128, int) |
| Arithmetic shift right | __ashrti3 |
i128(i128, int) |
| Logical shift right | __lshrti3 |
u128(u128, int) |
__int128 and Floating-Point Conversion Helpers
| Conversion | Helper | Signature |
|---|---|---|
| Signed to binary32 | __floattisf |
float(i128) |
| Signed to binary64 | __floattidf |
double(i128) |
| Unsigned to binary32 | __floatuntisf |
float(u128) |
| Unsigned to binary64 | __floatuntidf |
double(u128) |
| Binary32 to signed | __fixsfti |
i128(float) |
| Binary64 to signed | __fixdfti |
i128(double) |
| Binary32 to unsigned | __fixunssfti |
u128(float) |
| Binary64 to unsigned | __fixunsdfti |
u128(double) |
Complex Arithmetic Helpers
| Operation | Helper | Signature |
|---|---|---|
| Binary32 multiply | __mulsc3 |
c32(float, float, float, float) |
| Binary32 divide | __divsc3 |
c32(float, float, float, float) |
| Binary64 multiply | __muldc3 |
c64(double, double, double, double) |
| Binary64 divide | __divdc3 |
c64(double, double, double, double) |
The four scalar arguments to a complex helper are the real and imaginary parts of its two operands, in operand order. Bedrock long double has the binary64 representation and call classification, so conversions involving long double use the corresponding df helper and long double _Complex multiplication or division uses the corresponding dc3 helper.
Pointers and External Objects
A C function pointer is 64 bits wide and its value is a pre-segment near-call coordinate. Code and data pointers have the same size and alignment, while their distinct C type categories preserve separate code and data address spaces.
A common symbol has the ABI alignment of its declared type. An external object retains its declared alignment up to the 16-byte aggregate maximum. An explicit extension owns stronger placement requirements.
Calls, Relocations, and Relaxation
The relocation records the linkage path selected for a C call:
C Call Relocation Quick Reference
| Call form | Relocation |
|---|---|
| Direct C call | R_BEDROCK_CALL32S |
| External call through the PLT | R_BEDROCK_PLT32S |
The assembler and linker may relax an instruction sequence, but relaxation must preserve the C call interface, symbol identity, and observable control transfer defined by the original relocation. The relaxed sequence remains part of the same C calling convention.
TLS Relationship
The Bedrock ELF ABI defines TLS models, symbols, relocations, and the GS0-relative materialization protocols consumed by C code.