Procedures#
-
class unit::Procedure#
A procedure represents a single function to be compiled. It holds the stack-based IR and provides methods to emit instructions.
Procedures cannot be copied or moved.
-
explicit Procedure(Context &ctx, const std::string &name)#
Create a new procedure.
- Parameters:
ctx – The context that owns this procedure’s memory.
name – The symbol name for the compiled function.
- Throws:
unit::error – If initialization fails.
-
UNIT_Procedure *raw()#
Return the underlying C procedure pointer.
-
void optimize()#
Run stack IR optimization passes: inlining, constant folding, dead store elimination, and local variable optimization. Call this before
compile().- Throws:
unit::error – If optimization fails.
-
CompiledProcedure compile(Platform platform)#
Compile the procedure to machine code for the given platform.
- Parameters:
platform – Target platform (e.g.
Platform::host()).- Returns:
A compiled procedure ready for JIT or object file output.
- Throws:
unit::error – If compilation fails.
-
void print_instructions(FILE *stream = stdout)#
Print the stack IR to a file stream. Useful for debugging.
Stack Operations
-
void load_integer(int64_t value)#
Push an integer constant onto the stack. See
UNIT_OP_LOAD_INTEGER.Stack effect:
-- valueExample# proc.load_integer(42); // stack: [42]
-
void load_string(const std::string &value)#
Push a string constant onto the stack. The string is copied internally. See
UNIT_Procedure_AddStringLoad().Stack effect:
-- pointer
-
void load_argument(uint8_t index)#
Push a function argument onto the stack. Argument 0 is the first parameter. See
UNIT_OP_LOAD_ARGUMENT.Stack effect:
-- value
-
void load_local(int64_t index)#
Push a local variable onto the stack by index. See
UNIT_OP_LOAD_LOCAL.Stack effect:
-- value
-
void store_local(int64_t index)#
Pop the top of the stack into a local variable by index. See
UNIT_OP_STORE_LOCAL.Stack effect:
value --
-
void load_name(Local local)#
Push a local variable onto the stack by handle. See
UNIT_Procedure_AddLoadName().Stack effect:
-- value
-
void store_name(Local local)#
Pop the top of the stack into a local variable by handle. See
UNIT_Procedure_AddStoreName().Stack effect:
value --
-
void pop()#
Discard the top of the stack. See
UNIT_OP_POP.Stack effect:
value --
-
void copy(int64_t offset)#
Duplicate the stack item at the given depth.
copy(0)duplicates the top. SeeUNIT_OP_COPY.Stack effect:
-- valueproc.load_integer(10); // stack: [10] proc.load_integer(20); // stack: [10, 20] proc.copy(1); // stack: [10, 20, 10]
-
void swap(int64_t offset)#
Swap the top of the stack with the item at the given depth. See
UNIT_OP_SWAP.Stack effect: unchanged (items rearranged)
Arithmetic
-
void add()#
Pop two values, push their sum. See
UNIT_OP_ADD.Stack effect:
a b -- a+b
-
void subtract()#
Pop two values, push their difference. See
UNIT_OP_SUBTRACT.Stack effect:
a b -- a-b
-
void multiply()#
Pop two values, push their product. See
UNIT_OP_MULTIPLY.Stack effect:
a b -- a*b
-
void divide()#
Pop two values, push their quotient (integer division, truncated toward zero). See
UNIT_OP_DIVIDE.Stack effect:
a b -- a/b
-
void modulo()#
Pop two values, push the remainder. See
UNIT_OP_MODULO.Stack effect:
a b -- a%b
Comparisons
All comparisons pop two values, push a comparison result consumed by
jump_if_true()orjump_if_false().-
void compare_equal()#
-
Stack effect:
a b -- result
-
void compare_not_equal()#
See
UNIT_OP_COMPARE_NOT_EQUAL.Stack effect:
a b -- result
-
void compare_less()#
See
UNIT_OP_COMPARE_LESS.Stack effect:
a b -- result
-
void compare_less_equal()#
See
UNIT_OP_COMPARE_LESS_EQUAL.Stack effect:
a b -- result
-
void compare_greater()#
-
Stack effect:
a b -- result
-
void compare_greater_equal()#
See
UNIT_OP_COMPARE_GREATER_EQUAL.Stack effect:
a b -- result
Control Flow
-
JumpLabel create_jump_label(const std::string &name)#
Create a jump target. The label must later be placed with
use_label().- Returns:
A label handle for use with jump instructions.
- Throws:
unit::error – If allocation fails.
-
void use_label(JumpLabel label)#
Place a label at the current position in the instruction stream. All jumps to this label will target the next instruction emitted.
-
void jump_if_true(JumpLabel label)#
Pop a comparison result. Jump if true. See
UNIT_OP_JUMP_IF_TRUE.Stack effect:
comparison --
-
void jump_if_false(JumpLabel label)#
Pop a comparison result. Jump if false. See
UNIT_OP_JUMP_IF_FALSE.Stack effect:
comparison --
Example# auto 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
-
void call_name(const std::string &name, uint8_t nargs)#
Call an external function by name. The top nargs 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 -- resultExample# proc.load_string("%d\n"); proc.load_integer(42); proc.call_name("printf", 2); proc.pop(); // discard printf return value
-
void call_procedure(Procedure &target, uint8_t nargs)#
Call another UNIT procedure. This enables inlining during optimization. See
UNIT_Procedure_AddCallProcedure().Stack effect:
arg1 arg2 ... argN -- result
-
void return_value()#
Pop the top of the stack and return it to the caller. See
UNIT_OP_RETURN_VALUE.Stack effect:
value --
-
void exit()#
Terminate the process immediately. See
UNIT_OP_EXIT.
Memory Access
-
void read_bytes(uint8_t num_bytes)#
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
-
void write_bytes(uint8_t num_bytes)#
Pop an address and a value, write num_bytes of the value to the address. See
UNIT_OP_WRITE_BYTES.Stack effect:
address value --
-
void address_of(Local local)#
Push the memory address of a local variable. See
UNIT_OP_ADDRESS_OF.Stack effect:
-- address
Type Conversion
-
void convert(IntegerType type)#
Convert the top of the stack to a different integer width. See
UNIT_OP_CONVERT.Stack effect:
value -- converted_value
Locals
-
Local create_local(const std::string &name)#
Create a named local variable. Returns a handle for use with
store_name()andload_name().- Throws:
unit::error – If allocation fails.
-
explicit Procedure(Context &ctx, const std::string &name)#
Local variables#
Jump labels#
Flags#
-
enum class unit::Flag : uint32_t#
Procedure flags, combined with bitwise OR.
-
enumerator NONE = 0#
No flags.
-
enumerator NO_OPTIMIZE_TRANSLATION = UNIT_FLAG_NO_OPTIMIZE_TRANSLATION#
Skip register IR optimization (move coalescing, dead move elimination, forward copy propagation) during compilation.
-
enumerator FORCE_NO_INLINE = UNIT_FLAG_FORCE_NO_INLINE#
Prevent this procedure from being inlined into callers during optimization, regardless of size.
-
enumerator FORCE_INLINE = UNIT_FLAG_FORCE_INLINE#
Always inline this procedure into callers, regardless of size.
-
enumerator PRINT_TRANSLATION_PREOP = UNIT_FLAG_PRINT_TRANSLATION_PREOP#
Print the register IR to stderr before optimization runs. Useful for debugging.
-
enumerator PRINT_TRANSLATION_POSTOP = UNIT_FLAG_PRINT_TRANSLATION_POSTOP#
Print the register IR to stderr after optimization runs. Useful for debugging.
Example# proc.set_flags(unit::Flag::FORCE_NO_INLINE); // Combine flags with bitwise OR proc.set_flags(unit::Flag::FORCE_NO_INLINE | unit::Flag::NO_OPTIMIZE_TRANSLATION);
-
enumerator NONE = 0#
Compiled procedures#
-
class unit::CompiledProcedure#
A compiled procedure, ready for JIT execution or object file output. Returned by
Procedure::compile(). Cannot be copied. Move-only.-
template<typename Func>
ExecutableBuffer<Func> jit()# JIT compile and return an executable buffer. Symbols are resolved via
dlsym.- Throws:
unit::error – If JIT compilation fails.
-
template<typename Func>
ExecutableBuffer<Func> jit(SymbolMap &symbols)# JIT compile with custom symbol resolution. Symbols in the map are checked before falling back to
dlsym.- Throws:
unit::error – If JIT compilation fails.
-
void write_object_file(const std::string &path, ExecutableFormat format)#
Write the compiled procedure to an object file.
- Parameters:
path – Output file path.
format – Object file format (e.g.,
ExecutableFormat::ELF).
- Throws:
unit::error – If writing fails.
-
void print_translated(FILE *stream = stdout)#
Print the register IR to a file stream. Useful for debugging.
-
UNIT_CompiledProcedure *raw() const#
Return the underlying C compiled procedure pointer.
-
template<typename Func>
Executable buffers#
-
template<typename Func>
class unit::ExecutableBuffer# A JIT-compiled function, callable directly. Returned by
CompiledProcedure::jit(). Cannot be copied. Move-only. The executable memory is freed on destruction.Funcis the function pointer type, e.g.int64_t(*)(int64_t).
Symbol maps#
-
class unit::SymbolMap#
A map from symbol names to addresses, used for custom symbol resolution during JIT compilation. Cannot be copied or moved.
-
explicit SymbolMap(Context &ctx)#
Create an empty symbol map.
- Throws:
unit::error – If initialization fails.
-
void register_symbol(const std::string &name, void *address)#
Register a symbol name with its address.
- Parameters:
name – The symbol name (e.g.
"my_function").address – The function pointer or data address.
Example# unit::SymbolMap symbols(ctx); symbols.register_symbol("my_callback", (void *)my_callback); auto fn = compiled.jit<int64_t(*)()>(symbols);
-
explicit SymbolMap(Context &ctx)#