Determine if the current point in the function is dead. That is, there are no existing branches or fall-throughs to this point. This differs slightly from jit_block_ends_in_dead in that this can skip past zero-length blocks that may not appear to be dead to find the dead block at the head of a chain of empty blocks.
Determine if a block is reachable from some other point in its function. Unreachable blocks can be discarded in their entirety. If the JIT is uncertain as to whether a block is reachable, or it does not wish to perform expensive flow analysis to find out, then it will err on the side of caution and assume that it is reachable.
Iterate over the blocks in a function, in order of their creation. The previous argument should be NULL on the first call. This function will return NULL if there are no further blocks to iterate.
Iterate over the blocks in a function, in reverse order of their creation. The previous argument should be NULL on the first call. This function will return NULL if there are no further blocks to iterate.
Tag a block with some metadata. Returns zero if out of memory. If the type already has some metadata associated with it, then the previous value will be freed. Metadata may be used to store dependency graphs, branch prediction information, or any other information that is useful to optimizers or code generators.
This function is called to report a builtin exception. The JIT will automatically embed calls to this function wherever a builtin exception needs to be reported.
When a builtin exception occurs, the current thread’s exception handler is called to construct an appropriate object, which is then thrown.
If there is no exception handler set, or the handler returns NULL, then libjit will print an error message to stderr and cause the program to exit with a status of 1. You normally don’t want this behavior and you should override it if possible.
Get the last exception object that occurred on this thread, or NULL if there is no exception object on this thread. As far as libjit is concerned, an exception is just a pointer. The precise meaning of the data at the pointer is determined by the front end.
Get the last exception object that occurred on this thread and also clear the exception state to NULL. This combines the effect of both jit_exception_get_last and jit_exception_clear_last.
Create an object that represents the current call stack. This is normally used to indicate the location of an exception. Returns NULL if a stack trace is not available, or there is insufficient memory to create it.
Set the last exception object that occurred on this thread, so that it can be retrieved by a later call to jit_exception_get_last. This is normally used by jit_function_apply to save the exception object before returning to regular code.
Throw an exception object within the current thread. As far as libjit is concerned, the exception object is just a pointer. The precise meaning of the data at the pointer is determined by the front end.
Add the constant offset to the specified pointer value. This is functionally identical to calling jit_insn_add, but the JIT can optimize the code better if it knows that the addition is being used to perform a relative adjustment on a pointer. In particular, multiple relative adjustments on the same pointer can be collapsed into a single adjustment.
Get the address of label into a new temporary. This is typically used for exception handling, to track where in a function an exception was actually thrown.
Call the filter subroutine at label, passing it value as its argument. This function returns a value of the specified type, indicating the filter’s result.
Call a function via an indirect pointer. This version differs from jit_insn_call_indirect in that we assume that value contains a pointer that resulted from calling jit_function_to_vtable_pointer. Indirect vtable pointer calls may be more efficient on some platforms than regular indirect calls.
Add an instruction to return a default value if control reaches this point. This is typically used at the end of a function to ensure that all paths return to the caller. Returns zero if out of memory, 1 if a default return was added, and 2 if a default return was not needed.
This is similar to jit_insn_pop_stack, except that it tries to defer the pop as long as possible. Multiple subroutine calls may result in parameters collecting up on the stack, and only being popped at the next branch or label instruction. You normally wouldn’t call this yourself - it is used by CPU back ends.
Returns a non-zero value if the destination for insn is actually a source value. This can happen with instructions such as jit_insn_store_relative where the instruction needs three source operands, and the real destination is a side-effect on one of the sources.
Divide two values and return the quotient in a new temporary value. Throws an exception on division by zero or arithmetic error (an arithmetic error is one where the minimum possible signed integer value is divided by -1).
Flush any deferred items that were scheduled for popping by jit_insn_defer_pop_stack if there are num_items or more items scheduled. You normally wouldn’t call this yourself - it is used by CPU back ends to clean up the stack just prior to a subroutine call when too many items have collected up. Calling jit_insn_flush_defer_pop(func, 0) will flush all deferred items.
Flush a small structure return value out of registers and back into the local variable frame. You normally wouldn’t call this yourself - it is used internally by the CPU back ends to handle structure returns from functions.
Get an object that represents the current position in the code, and all of the functions that are currently on the call stack. This is equivalent to calling jit_exception_get_stack_trace, and is normally used just prior to jit_insn_throw to record the location of the exception that is being thrown.
Retrieve the frame pointer of the parent of target. Returns NULL when target is not a sibling, an ancestor, or a sibling of one of the ancestors of func. Returns NULL if out of memory.
Import value from an outer nested scope into func. Returns the effective address of the value for local access via a pointer. Returns NULL if out of memory or the value is not accessible via a parent, grandparent, or other ancestor of func.
Output an instruction that notes that the contents of value can be found in the stack frame at frame_offset. This should only be called once per value, to prevent values from changing their address when they might be addressable.
Branch to a label from the labels table. The value is the index of the label. It is allowed to have identical labels in the table. If an entry in the table has jit_label_undefined value then it is replaced with a newly allocated label.
Start a new basic block within the function func and give it the specified label but attempt to reuse the last block if it is empty. Returns zero if out of memory.
If the contents of label are jit_label_undefined, then this function will allocate a new label for this block. Otherwise it will reuse the specified label from a previous branch instruction.
Load an element of type elem_type from position index within the array starting at base_addr. The effective address of the array element is base_addr + index * sizeof(elem_type).
Load the effective address of an element of type elem_type at position index within the array starting at base_addr. Essentially, this computes the expression base_addr + index * sizeof(elem_type), but may be more efficient than performing the steps with jit_insn_mul and jit_insn_add.
Mark the current position in func as corresponding to a breakpoint location. When a break occurs, the debugging routines are passed func, data1, and data2 as arguments. By convention, data1 is the type of breakpoint (source line, function entry, function exit, etc).
Mark the current position in func as corresponding to the specified bytecode offset. This value will be returned byw]lysw`jit_stack_trace_get_offset, and is useful for associating code positions with source line numbers.
Move all of the blocks between from_label (inclusive) and to_label (exclusive) to the end of the current function. This is typically used to move the expression in a while loop to the end of the body, where it can be executed more efficiently.
Move all of the blocks between from_label (inclusive) and to_label (exclusive) to the start of the current function. This is typically used to move initialization code to the head of the function.
Emits “no operation” instruction. You may want to do that if you need an empty block to move it with jit_insn_move_blocks_XXX later. If you will not put empty instruction between two labels, both labels will point to the same block, and block moving will fail.
Output an instruction that copies the contents of value into the register reg at this point in the code. This is typically used just before making an outgoing subroutine call.
Pop num_items items from the function call stack. You normally wouldn’t call this yourself - it is used by CPU back ends to clean up the stack after calling a subroutine. The size of an item is specific to the back end (it could be bytes, words, or some other measurement).
Push a value onto the function call stack, in preparation for a call. You normally wouldn’t call this yourself - it is used internally by the CPU back ends to set up the stack for a subroutine call.
Push *value onto the function call stack, in preparation for a call. This is normally used for returning struct and union values where you have the effective address of the structure, rather than the structure’s contents, in value.
Push the interpreter’s return area pointer onto the stack. You normally wouldn’t call this yourself - it is used internally by the CPU back ends to set up the stack for a subroutine call.
Divide two values and return the remainder in a new temporary value. Throws an exception on division by zero or arithmetic error (an arithmetic error is one where the minimum possible signed integer value is divided by -1).
Divide two values and return the remainder in a new temporary value. Throws an exception on division by zero or arithmetic error (an arithmetic error is one where the minimum possible signed integer value is divided by -1). This function is identical to jit_insn_rem, except that it uses IEEE rules for computing the remainder of floating-point values.
Output an instruction to return value as the function’s result. If value is NULL, then the function is assumed to return void. If the function returns a structure, this will copy the value into the memory at the structure return address.
Output an instruction to return *value as the function’s result. This is normally used for returning struct and union values where you have the effective address of the structure, rather than the structure’s contents, in value.
Output an instruction that notes that the contents of value can be found in the register reg at this point in the code. This is similar to jit_insn_incoming_reg, except that it refers to return values, not parameter values.
Set the parameter slot at offset in the outgoing parameter area to value. This may be used instead of jit_insn_push if it is more efficient to store directly to the stack than to push. The outgoing parameter area is allocated within the frame when the function is first entered.
Perform a bitwise right shift on two values and return the result in a new temporary value. This performs a signed shift on signed operators, and an unsigned shift on unsigned operands.
Perform a bitwise right shift on two values and return the result in a new temporary value. This performs an signed shift on both signed and unsigned operands.
Start the catcher block for func. There should be exactly one catcher block for any function that involves a try. All exceptions that are thrown within the function will cause control to jump to this point. Returns a value that holds the exception that was thrown.
Store the contents of value at the location referred to by dest. The dest should be a jit_value_t representing a local variable or temporary. Use jit_insn_store_relative to store to a location referred to by a pointer.
Store value at position index of the array starting at base_addr. The effective address of the storage location is base_addr + index * sizeof(jit_value_get_type(value)).
Throw a pointer value as an exception object. This can also be used to “rethrow” an object from a catch handler that is not interested in handling the exception.
Notify the function building process that func contains some form of catch clause for catching exceptions. This must be called before any instruction that is covered by a try, ideally at the start of the function output process.
Perform a bitwise right shift on two values and return the result in a new temporary value. This performs an unsigned shift on both signed and unsigned operands.
Get the function that is at position posn within a stack trace. Position 0 is the function that created the stack trace. If this returns NULL, then it indicates that there is a native callout at posn within the stack trace.
Get the bytecode offset that is recorded for position posn within a stack trace. This will be JIT_NO_OFFSET if there is no bytecode offset associated with posn.
Get the program counter that corresponds to position posn within a stack trace. This is the point within the function where execution had reached at the time of the trace.
Create a new value in the context of a function’s current block. The value initially starts off as a block-specific temporary. It will be converted into a function-wide local variable if it is ever referenced from a different block. Returns NULL if out of memory.
Create a new constant from a generic constant structure in the specified function. Returns NULL if out of memory or if the type in const_value is not suitable for a constant.
Create a new 64-bit integer constant in the specified function. This can also be used to create constants of type jit_type_ulong. Returns NULL if out of memory.
Get the value that contains the structure return pointer for a function. If the function does not have a structure return pointer (i.e. structures are returned in registers), then this returns NULL.
Create a reference to the specified value from the current block in func. This will convert a temporary value into a local value if value is being referenced from a different block than its original.
Set a flag on a value to indicate that it is addressable. This should be used when you want to take the address of a value (e.g. &variable in C). The value is guaranteed to not be stored in a register across a function call. If you refer to a value from a nested function (jit_value_ref), then the value will be automatically marked as addressable.
Set a flag on a value to indicate that it is volatile. The contents of the value must always be reloaded from memory, never from a cached register copy.