infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
infix_internals.h
Go to the documentation of this file.
1#pragma once
31#include "common/infix_config.h" // Include the internal platform detection logic.
32#include <infix/infix.h>
33
42typedef struct {
43#if defined(INFIX_OS_WINDOWS)
44 HANDLE handle;
45#else
46 int shm_fd;
47#endif
48 void * rx_ptr;
49 void * rw_ptr;
50 size_t size;
52
60typedef struct {
61 void * rw_ptr;
62 size_t size;
64
81
93typedef void (*infix_internal_dispatch_callback_fn)(infix_reverse_t *, void *, void **);
94
125
131 char * buffer;
132 size_t capacity;
134 bool error;
135};
136
151
164
169typedef struct {
170 uint8_t * code;
171 size_t capacity;
172 size_t size;
173 bool error;
176
184#define INFIX_MAX_STACK_ALLOC (1024 * 1024 * 4) // 4MB
185
192#define INFIX_MAX_ARG_SIZE (1024 * 64) // 64KB
193
198typedef enum {
200#if defined(INFIX_ABI_AAPCS64)
201 ARG_LOCATION_VPR,
203 ARG_LOCATION_GPR_REFERENCE,
204 ARG_LOCATION_VPR_HFA,
205#else // x86-64 ABIs
211#endif
214
226
234typedef struct {
236 uint8_t num_gpr_args;
237#if defined(INFIX_ABI_AAPCS64)
238 uint8_t num_vpr_args;
239#else
240 uint8_t num_xmm_args;
241#endif
246 size_t num_args;
247 void * target_fn;
249
264
272typedef struct {
274 infix_status (*prepare_forward_call_frame)(
275 infix_arena_t *, infix_call_frame_layout **, infix_type *, infix_type **, size_t, size_t, void *);
277 infix_status (*generate_forward_prologue)(code_buffer *, infix_call_frame_layout *);
280 infix_status (*generate_forward_argument_moves)(
281 code_buffer *, infix_call_frame_layout *, infix_type **, size_t, size_t);
283 infix_status (*generate_forward_call_instruction)(code_buffer *, infix_call_frame_layout *);
285 infix_status (*generate_forward_epilogue)(code_buffer *, infix_call_frame_layout *, infix_type *);
287
292typedef struct {
296 infix_status (*generate_reverse_prologue)(code_buffer *, infix_reverse_call_frame_layout *);
298 infix_status (*generate_reverse_argument_marshalling)(code_buffer *,
302 infix_status (*generate_reverse_dispatcher_call)(code_buffer *,
308
309// Function Prototypes for Internal Modules
310
311// From error.c
317void _infix_clear_error(void);
318
319// From types.c
322
323// From registry.c
326
327// From signature.c
330 infix_arena_t **,
331 const char *,
333
334// From trampoline.c
342void code_buffer_append(code_buffer *, const void *, size_t);
344void emit_byte(code_buffer *, uint8_t);
346void emit_int32(code_buffer *, int32_t);
348void emit_int64(code_buffer *, int64_t);
351 infix_forward_t **, infix_type *, infix_type **, size_t, size_t, infix_arena_t *, void *);
352
353// From executor.c
368
370#define EMIT_BYTES(buf, ...) \
371 do { \
372 const uint8_t bytes[] = {__VA_ARGS__}; \
373 code_buffer_append((buf), bytes, sizeof(bytes)); \
374 } while (0)
375
383static inline size_t _infix_align_up(size_t value, size_t alignment) {
384 // Standard bit-twiddling hack for alignment.
385 return (value + alignment - 1) & ~(alignment - 1);
386}
387
389static inline bool is_float(const infix_type * type) {
391}
392
394static inline bool is_double(const infix_type * type) {
396}
397
399static inline bool is_long_double(const infix_type * type) {
401}
402
403// Include the correct ABI-specific instruction emitter header for the target platform.
404#if defined(INFIX_ABI_SYSV_X64) || defined(INFIX_ABI_WINDOWS_X64)
406#elif defined(INFIX_ABI_AAPCS64)
408#endif
Declares internal helper functions for emitting AArch64 machine code.
Declares internal helper functions for emitting x86-64 machine code.
#define c23_nodiscard
Definition compat_c23.h:93
infix_error_code_t
Specific error codes providing detailed information about a failure.
Definition infix.h:1055
infix_error_category_t
Broad categories for errors that can occur in the library.
Definition infix.h:1039
infix_status
An enumeration of all possible success or failure codes from the public API.
Definition infix.h:351
@ INFIX_PRIMITIVE_LONG_DOUBLE
long double
Definition infix.h:147
@ INFIX_PRIMITIVE_FLOAT
float
Definition infix.h:145
@ INFIX_PRIMITIVE_DOUBLE
double
Definition infix.h:146
@ INFIX_TYPE_PRIMITIVE
A built-in type like int, float, double.
Definition infix.h:115
Internal-only header for platform, architecture, and ABI detection.
void infix_executable_free(infix_executable_t)
Frees executable memory, creating a guard page to prevent use-after-free.
Definition executor.c:388
const infix_forward_abi_spec * get_current_forward_abi_spec(void)
Gets the ABI v-table for the current target platform (forward calls).
Definition trampoline.c:80
void code_buffer_append(code_buffer *, const void *, size_t)
Appends raw bytes to a code buffer, reallocating if necessary.
Definition trampoline.c:128
c23_nodiscard infix_status _infix_resolve_type_graph(infix_type **, infix_registry_t *)
Walks a type graph, replacing all @Name placeholders with their concrete definitions from a registry.
Definition type_registry.c:398
static bool is_long_double(const infix_type *type)
Convenience helper to check if an infix_type is a longdouble.
Definition infix_internals.h:399
c23_nodiscard bool infix_executable_make_executable(infix_executable_t)
Makes a JIT memory region readable and executable (and non-writable).
Definition executor.c:453
void _infix_set_error(infix_error_category_t, infix_error_code_t, size_t)
Sets the thread-local error details for a library-internal error.
Definition error.c:44
c23_nodiscard infix_status _infix_parse_type_internal(infix_type **, infix_arena_t **, const char *, infix_registry_t *)
The core, non-resolving entry point for the signature parser.
Definition signature.c:1040
c23_nodiscard infix_executable_t infix_executable_alloc(size_t)
Allocates a page-aligned block of W^X-compliant executable memory.
Definition executor.c:286
void emit_int64(code_buffer *, int64_t)
Appends a 64-bit integer to a code buffer.
Definition trampoline.c:171
infix_type * _copy_type_graph_to_arena(infix_arena_t *, const infix_type *)
Performs a deep copy of a type graph from one arena to another.
Definition types.c:610
infix_arg_location_type
Definition infix_internals.h:198
@ ARG_LOCATION_GPR_PAIR
A struct passed in two GPRs (System V only).
Definition infix_internals.h:207
@ ARG_LOCATION_STACK
Argument is passed on the stack.
Definition infix_internals.h:212
@ ARG_LOCATION_XMM
Argument is passed in an XMM (SSE) register.
Definition infix_internals.h:206
@ ARG_LOCATION_INTEGER_SSE_PAIR
A struct split between a GPR and an XMM register (System V only).
Definition infix_internals.h:209
@ ARG_LOCATION_GPR
Argument is passed in a General-Purpose Register.
Definition infix_internals.h:199
@ ARG_LOCATION_SSE_SSE_PAIR
A struct passed in two XMM registers (System V only).
Definition infix_internals.h:208
@ ARG_LOCATION_SSE_INTEGER_PAIR
A struct split between an XMM and a GPR (System V only).
Definition infix_internals.h:210
static size_t _infix_align_up(size_t value, size_t alignment)
Definition infix_internals.h:383
static bool is_double(const infix_type *type)
Convenience helper to check if an infix_type is a double.
Definition infix_internals.h:394
void emit_int32(code_buffer *, int32_t)
Appends a 32-bit integer to a code buffer.
Definition trampoline.c:166
const infix_reverse_abi_spec * get_current_reverse_abi_spec(void)
Gets the ABI v-table for the current target platform (reverse calls).
Definition trampoline.c:97
c23_nodiscard infix_protected_t infix_protected_alloc(size_t)
Allocates a page-aligned block of data memory.
Definition executor.c:507
void code_buffer_init(code_buffer *, infix_arena_t *)
Initializes a code buffer for JIT code generation.
Definition trampoline.c:114
void _infix_clear_error(void)
Resets the thread-local error state. Called at the start of every public API function.
Definition error.c:76
void _infix_set_system_error(infix_error_category_t, infix_error_code_t, long, const char *)
Sets the thread-local error details for an error originating from the OS.
Definition error.c:56
static bool is_float(const infix_type *type)
Convenience helper to check if an infix_type is a float.
Definition infix_internals.h:389
void infix_protected_free(infix_protected_t)
Frees a block of protected data memory.
Definition executor.c:546
c23_nodiscard infix_status _infix_forward_create_internal(infix_forward_t **, infix_type *, infix_type **, size_t, size_t, infix_arena_t *, void *)
The internal core logic for creating a forward trampoline.
Definition trampoline.c:251
void infix_internal_dispatch_callback_fn_impl(infix_reverse_t *, void *, void **)
The high-level C dispatcher function called by reverse trampoline stubs.
Definition executor.c:610
void(* infix_internal_dispatch_callback_fn)(infix_reverse_t *, void *, void **)
Definition infix_internals.h:93
void emit_byte(code_buffer *, uint8_t)
Appends a single byte to a code buffer.
Definition trampoline.c:161
c23_nodiscard bool infix_protected_make_readonly(infix_protected_t)
Hardens a block of protected data memory to be read-only.
Definition executor.c:577
Definition infix_internals.h:144
bool is_forward_declaration
Definition infix_internals.h:147
const char * name
Definition infix_internals.h:145
infix_type * type
Definition infix_internals.h:146
struct _infix_registry_entry_t * next
Definition infix_internals.h:148
Definition infix_internals.h:169
uint8_t * code
The buffer holding the machine code.
Definition infix_internals.h:170
bool error
A flag that is set if a memory allocation fails.
Definition infix_internals.h:173
size_t size
The current number of bytes written to the buffer.
Definition infix_internals.h:172
size_t capacity
The allocated capacity of the buffer.
Definition infix_internals.h:171
infix_arena_t * arena
The arena to use for allocations.
Definition infix_internals.h:174
Definition infix_internals.h:130
char * buffer
The pointer to the large, pre-allocated memory block.
Definition infix_internals.h:131
bool error
A sticky flag that is set if any allocation from this arena fails.
Definition infix_internals.h:134
size_t capacity
The total size of the buffer in bytes.
Definition infix_internals.h:132
size_t current_offset
The high-water mark; the offset of the next free byte.
Definition infix_internals.h:133
Definition infix_internals.h:219
uint32_t stack_offset
The byte offset from the stack pointer if passed on the stack.
Definition infix_internals.h:224
uint8_t reg_index
The index of the first register used (e.g., 0 for RCX/RDI/X0).
Definition infix_internals.h:221
infix_arg_location_type type
The classification of the argument's location.
Definition infix_internals.h:220
uint8_t reg_index2
The index of the second register if the argument is split.
Definition infix_internals.h:222
uint8_t num_regs
The number of registers this argument occupies (e.g., for HFAs).
Definition infix_internals.h:223
Definition infix_internals.h:234
bool is_variadic
True if the call is variadic, requiring special ABI handling.
Definition infix_internals.h:244
size_t num_stack_args
The number of arguments passed on the stack.
Definition infix_internals.h:245
void * target_fn
If non-NULL, the target function for a bound trampoline.
Definition infix_internals.h:247
infix_arg_location * arg_locations
An array detailing the location of each argument.
Definition infix_internals.h:242
size_t total_stack_alloc
Total bytes for ABI-compliant stack arguments, 16-byte aligned.
Definition infix_internals.h:235
uint8_t num_gpr_args
The highest index of a GPR used for arguments.
Definition infix_internals.h:236
bool return_value_in_memory
True if the return value is passed via a hidden pointer argument.
Definition infix_internals.h:243
size_t num_args
The total number of arguments.
Definition infix_internals.h:246
uint8_t num_xmm_args
The highest index of an XMM register used for arguments.
Definition infix_internals.h:240
Definition infix_internals.h:42
size_t size
The total size of the allocated memory region in bytes.
Definition infix_internals.h:50
void * rw_ptr
Pointer with Read+Write permissions (where code is written).
Definition infix_internals.h:49
void * rx_ptr
Pointer with Read+Execute permissions (the callable address).
Definition infix_internals.h:48
int shm_fd
File descriptor for the shared memory object on POSIX systems that use dual-mapping.
Definition infix_internals.h:46
Definition infix_internals.h:272
Definition infix_internals.h:72
infix_executable_t exec
Handle to the executable JIT-compiled stub.
Definition infix_internals.h:74
void * target_fn
If non-NULL, the hardcoded target function for a "bound" trampoline.
Definition infix_internals.h:79
size_t num_args
The total number of arguments.
Definition infix_internals.h:77
size_t num_fixed_args
The number of non-variadic arguments.
Definition infix_internals.h:78
infix_type ** arg_types
An array of infix_type pointers for each argument.
Definition infix_internals.h:76
infix_type * return_type
The infix_type of the trampoline's return value.
Definition infix_internals.h:75
infix_arena_t * arena
The arena that owns all the type metadata for this trampoline.
Definition infix_internals.h:73
Definition infix_internals.h:60
size_t size
The size of the allocated memory region in bytes.
Definition infix_internals.h:62
void * rw_ptr
A pointer to the read-write data memory.
Definition infix_internals.h:61
Definition infix_internals.h:158
size_t num_items
Definition infix_internals.h:161
infix_arena_t * arena
Definition infix_internals.h:159
_infix_registry_entry_t ** buckets
Definition infix_internals.h:162
size_t num_buckets
Definition infix_internals.h:160
Definition infix_internals.h:292
Definition infix_internals.h:256
int32_t args_array_offset
Offset to the void** array passed to the C dispatcher.
Definition infix_internals.h:259
int32_t xmm_save_area_offset
Offset to where incoming XMM/VPR arguments are saved.
Definition infix_internals.h:262
int32_t saved_args_offset
Offset to the area where by-value argument data is saved.
Definition infix_internals.h:260
int32_t gpr_save_area_offset
Offset to where incoming GPR arguments are saved.
Definition infix_internals.h:261
size_t total_stack_alloc
Total bytes to allocate on the stub's stack frame.
Definition infix_internals.h:257
int32_t return_buffer_offset
Offset from frame pointer to the return value buffer.
Definition infix_internals.h:258
Definition infix_internals.h:102
infix_type * return_type
The infix_type of the callback's return value.
Definition infix_internals.h:106
void * user_data
Arbitrary user-data pointer associated with this callback.
Definition infix_internals.h:112
void * user_callback_fn
Pointer to the user's actual C callback handler function.
Definition infix_internals.h:111
infix_executable_t exec
Handle to the executable JIT-compiled entry stub.
Definition infix_internals.h:104
infix_internal_dispatch_callback_fn internal_dispatcher
Pointer to the C function that bridges from assembly.
Definition infix_internals.h:113
size_t num_args
The total number of arguments.
Definition infix_internals.h:108
size_t num_fixed_args
The number of non-variadic arguments.
Definition infix_internals.h:109
infix_protected_t protected_ctx
Handle to the memory where this very context struct resides.
Definition infix_internals.h:105
bool is_variadic
True if the function signature is variadic.
Definition infix_internals.h:110
infix_forward_t * cached_forward_trampoline
A pre-compiled forward trampoline for calling a type-safe user C callback.
Definition infix_internals.h:123
infix_arena_t * arena
The arena that owns all type metadata for this callback.
Definition infix_internals.h:103
infix_type ** arg_types
An array of infix_type pointers for each argument.
Definition infix_internals.h:107
The central structure for describing any data type in the FFI system.
Definition infix.h:161
union infix_type_t::@0 meta
Type-specific metadata.
infix_type_category category
The fundamental category of the type.
Definition infix.h:162
infix_primitive_type_id primitive_id
For INFIX_TYPE_PRIMITIVE.
Definition infix.h:169