Procedures#
- class unit.Procedure(name, *, context=None, inlining=None, optimize_translation=True)#
A procedure represents a single function to be compiled. Provides methods to emit stack-based IR instructions.
- Parameters:
name (str) – Symbol name for the compiled function.
context (Context) – The context that owns this procedure’s memory. If
None, uses the current context or creates a new one (viaunit.Context.current_or_new()).inlining (str) – Inlining behavior –
"force","never", orNone(default). SeeUNIT_FLAG_FORCE_INLINEandUNIT_FLAG_FORCE_NO_INLINE.optimize_translation (bool) – Whether to run register IR optimization during compilation. See
UNIT_FLAG_NO_OPTIMIZE_TRANSLATION.
Example# # Simple usage proc = unit.Procedure("main") proc.load_integer(42) proc.return_value() # With explicit options proc = unit.Procedure( "helper", context=ctx, inlining="never", optimize_translation=False, )
Properties
- property inlining: str | None#
Get or set the inlining behavior.
"force","never", orNone.
- property optimize_translation: bool#
Get or set whether register IR optimization runs during compilation.
Compilation
- optimize() None#
Run stack IR optimization passes: inlining, constant folding, dead store elimination, and local variable optimization. Call this before
compile().- Raises:
unit.Error – If optimization fails.
- compile(platform=None) CompiledProcedure#
Compile the procedure to machine code.
- Parameters:
platform (Platform) – Target platform. Defaults to
Platform.host().- Returns:
A compiled procedure ready for JIT or object file output.
- Return type:
- Raises:
unit.Error – If compilation fails.
- instructions_text(*, visualize_stack_effect=True, ignore_errors=True) str#
Return the stack IR as a string. Useful for debugging.
- Parameters:
visualize_stack_effect (bool) – Show stack state after each instruction.
ignore_errors (bool) – Suppress errors from incomplete procedures.
Stack Operations
- load_integer(value) None#
Push an integer constant onto the stack. See
UNIT_OP_LOAD_INTEGER.Stack effect:
-- value- Parameters:
value (int) – The integer to push.
- Raises:
TypeError – If value is not an int.
- load_string(value) None#
Push a string constant onto the stack. See
UNIT_Procedure_AddStringLoad().Stack effect:
-- pointer- Parameters:
value (str) – The string to push. Copied internally.
- Raises:
TypeError – If value is not a str.
- load_argument(arg_number) None#
Push a function argument onto the stack. Argument 0 is the first parameter. See
UNIT_OP_LOAD_ARGUMENT.Stack effect:
-- value- Parameters:
arg_number (int) – The argument index.
- load_local(id) None#
Push a local variable onto the stack. See
UNIT_OP_LOAD_LOCAL.Stack effect:
-- value- Parameters:
id (int) – The local variable index.
- store_local(id) None#
Pop the top of the stack into a local variable. See
UNIT_OP_STORE_LOCAL.Stack effect:
value --- Parameters:
id (int) – The local variable index.
- pop() None#
Discard the top of the stack. See
UNIT_OP_POP.Stack effect:
value --
- copy(offset_from_top) None#
Duplicate the stack item at the given depth.
copy(0)duplicates the top. SeeUNIT_OP_COPY.Stack effect:
-- value- Parameters:
offset_from_top (int) – Depth of the item to copy (0 = top).
proc.load_integer(10) # stack: [10] proc.load_integer(20) # stack: [10, 20] proc.copy(1) # stack: [10, 20, 10]
- swap(offset_from_top) None#
Swap the top of the stack with the item at the given depth. See
UNIT_OP_SWAP.Stack effect: unchanged (items rearranged)
- Parameters:
offset_from_top (int) – Depth of the item to swap with (1 = second item).
Arithmetic
- add() None#
Pop two values, push their sum. See
UNIT_OP_ADD.Stack effect:
a b -- a+b
- subtract() None#
Pop two values, push their difference. See
UNIT_OP_SUBTRACT.Stack effect:
a b -- a-b
- multiply() None#
Pop two values, push their product. See
UNIT_OP_MULTIPLY.Stack effect:
a b -- a*b
- divide() None#
Pop two values, push their quotient (integer division). See
UNIT_OP_DIVIDE.Stack effect:
a b -- a/b
- modulo() None#
Pop two values, push the remainder. See
UNIT_OP_MODULO.Stack effect:
a b -- a%b
Comparisons
All comparisons pop two values and push a comparison result consumed by
jump_if_true()orjump_if_false().- compare_equal() None#
-
Stack effect:
a b -- result
- compare_not_equal() None#
See
UNIT_OP_COMPARE_NOT_EQUAL.Stack effect:
a b -- result
- compare_less() None#
See
UNIT_OP_COMPARE_LESS.Stack effect:
a b -- result
- compare_less_equal() None#
See
UNIT_OP_COMPARE_LESS_EQUAL.Stack effect:
a b -- result
- compare_greater() None#
-
Stack effect:
a b -- result
- compare_greater_equal() None#
See
UNIT_OP_COMPARE_GREATER_EQUAL.Stack effect:
a b -- result
Control Flow
- create_jump_label(name) JumpLabel#
Create a jump target. Place it later with
use_label().- Parameters:
name (str) – A descriptive name for the label.
- Returns:
A label handle.
- Return type:
- Raises:
TypeError – If name is not a str.
- use_label(label) None#
Place a label at the current position. All jumps to this label target the next instruction emitted.
- Parameters:
label (JumpLabel) – The label to place.
- jump(label) None#
Unconditional jump. See
UNIT_OP_JUMP_TO.- Parameters:
label (JumpLabel) – The target label.
- jump_if_true(label) None#
Pop a comparison result. Jump if true. See
UNIT_OP_JUMP_IF_TRUE.Stack effect:
comparison --- Parameters:
label (JumpLabel) – The target label.
- jump_if_false(label) None#
Pop a comparison result. Jump if false. See
UNIT_OP_JUMP_IF_FALSE.Stack effect:
comparison --- Parameters:
label (JumpLabel) – The target label.
end = proc.create_jump_label("end") proc.load_integer(5) proc.load_integer(5) proc.compare_equal() proc.jump_if_true(end) # ... not-equal path ... proc.use_label(end) # ... equal path continues here ...
Calls
- call_name(name, num_args) None#
Call an external function by name. The top num_args stack items are passed as arguments (first argument pushed first). The return value is pushed onto the stack. See
UNIT_Procedure_AddCallName().Stack effect:
arg1 arg2 ... argN -- result- Parameters:
name (str) – The function name (resolved via
dlsymorSymbolMapduring JIT).num_args (int) – Number of arguments.
- Raises:
TypeError – If name is not a str or num_args is not an int.
ValueError – If num_args is negative.
proc.load_string("%d\n") proc.load_integer(42) proc.call_name("printf", 2) proc.pop() # discard printf return value
- return_value() None#
Pop the top of the stack and return it to the caller. See
UNIT_OP_RETURN_VALUE.Stack effect:
value --
- exit() None#
Terminate the process immediately. See
UNIT_OP_EXIT.
Memory Access
- read_bytes(num_bytes) None#
Pop an address, read num_bytes from it (1, 2, 4, or 8), push the value. See
UNIT_OP_READ_BYTES.Stack effect:
address -- value- Parameters:
num_bytes (int) – Number of bytes to read.
- write_bytes(num_bytes) None#
Pop an address and a value, write num_bytes of the value to the address. See
UNIT_OP_WRITE_BYTES.Stack effect:
address value --- Parameters:
num_bytes (int) – Number of bytes to write.
- address_of(id) None#
Push the memory address of a local variable. See
UNIT_OP_ADDRESS_OF.Stack effect:
-- address- Parameters:
id (int) – The local variable index.
Jump labels#
- class unit.JumpLabel#
A handle to a jump target, returned by
Procedure.create_jump_label(). Not constructed directly.
Platforms#
- class unit.Platform(architecture, abi)#
Target platform for compilation.
- Parameters:
architecture (str) –
"amd64"or"aarch64".abi (str) –
"systemv","apple", or"win64".
Example# # Explicit platform platform = unit.Platform("amd64", "systemv") compiled = proc.compile(platform) # Host platform (auto-detected) compiled = proc.compile() # uses Platform.host() internally
- architecture: str#
"amd64"or"aarch64".
- abi: str#
"systemv","apple", or"win64".
Compiled procedures#
- class unit.CompiledProcedure#
A compiled procedure, ready for JIT execution or object file output. Returned by
Procedure.compile(). Not constructed directly.- jit(extra_symbols=None) ExecutableBuffer#
JIT compile and return an executable buffer. Symbols are resolved via
dlsym. Custom symbols can be provided for JIT-to-JIT calls or trampolines.- Parameters:
extra_symbols (dict) – Optional mapping of symbol names to integer addresses. See Symbol resolution.
- Returns:
A callable executable buffer.
- Return type:
- Raises:
unit.Error – If JIT compilation fails.
Example# # Simple JIT buf = compiled.jit() result = buf(42) # With custom symbols import ctypes addr = ctypes.cast(my_func, ctypes.c_void_p).value buf = compiled.jit(extra_symbols={"my_func": addr})
- write_object_file(path, format) None#
Write the compiled procedure to an object file.
- Parameters:
path (str) – Output file path.
format (str) –
"elf","macho", or"pe".
- Raises:
ValueError – If format is not recognized.
unit.Error – If writing fails.
Example# compiled.write_object_file("output.o", "elf")
- translation_text() str#
Return the register IR as a string. Useful for debugging.
Executable buffers#
- class unit.ExecutableBuffer#
A JIT-compiled function, callable directly. Returned by
CompiledProcedure.jit(). Not constructed directly.Arguments are automatically converted to ctypes types:
int–c_int64float–c_doublestr–c_char_p(encoded to UTF-8)bytes–c_char_p
The return type is always
c_int64. For finer control, use theaddressproperty with ctypes directly.- __call__(*args) int#
Call the JIT-compiled function.
- Raises:
TypeError – If an argument has an unsupported type.
buf = compiled.jit() result = buf(10, 20) # call with two int arguments
- address: int#
The raw function pointer address. Use with ctypes for custom calling conventions or return types.
import ctypes func_type = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double) fn = func_type(buf.address) result = fn(3.14)
Symbol resolution#
The extra_symbols parameter on CompiledProcedure.jit() accepts
a dictionary mapping symbol names to integer addresses. This is used for
custom symbol resolution during JIT compilation – for example, to provide
trampolines for calling between JIT-compiled functions.
import ctypes
@ctypes.CFUNCTYPE(ctypes.c_int64, ctypes.c_int64)
def my_trampoline(n):
return n * 2
addr = ctypes.cast(my_trampoline, ctypes.c_void_p).value
buf = compiled.jit(extra_symbols={"my_func": addr})
Symbols in the dictionary are checked before falling back to dlsym.
See UNIT_SymbolMap for the underlying C API.