+2004-06-10 Rhys Weatherley <rweather@southern-storm.com.au>
+
+ * jit/jit-apply-arm.c, jit/jit-gen-arm.c, jit/jit-gen-arm.h,
+ jit/jit-rules-arm.c, jit/jit-rules-arm.h, jit/jit-rules-arm.sel,
+ tools/gen-sel-parser.y: redesign the ARM code generation macros
+ so that they have stronger protection against buffer overruns.
+
+ * jit/jit-rules-arm.sel: flush the constant pool after unconditional
+ branches, to try to minimize the probability that the pool will
+ be flushed in the middle of a loop body.
+
+ * jit/jit-dump.c: dump the hex address of external functions,
+ to aid with debugging native disassembly dumps.
+
+ * include/jit/jit-insn.h, include/jit/jit-opcode.h,
+ include/jit/jit-plus.h, jit/jit-insn.c, jit/jit-internal.h,
+ jit/jit-interp.c, jit/jit-opcode.c, jit/jit-rules-arm.c,
+ jit/jit-rules-arm.sel, jitplus/jit-plus-function.cpp:
+ add support for outgoing parameter areas, which should reduce
+ the overhead of function calls that involve stacked arguments
+ on non-x86 platforms; use parameter areas in the ARM back end.
+
2004-06-09 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-arm.c (flush_constants): update the instruction
* jit/jit-rules-arm.c (_jit_gen_load_value): use ARM register pairs
properly for "long" and "float64" values.
- * jit/jit-apply-arm.c, jit/jit-gen-arm.c, jit/jit-gen-arm.h,
- jit/jit-rules-arm.c, jit/jit-rules-arm.h, jit/jit-rules-arm.sel,
- tools/gen-sel-parser.y: redesign the ARM code generation macros
- so that they have stronger protection against buffer overruns.
-
- * jit/jit-rules-arm.sel: flush the constant pool after unconditional
- branches, to try to minimize the probability that the pool will
- be flushed in the middle of a loop body.
-
- * jit/jit-dump.c: dump the hex address of external functions,
- to aid with debugging native disassembly dumps.
-
2004-06-08 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/Makefile.am, jit/jit-cpuid-x86.c, jit/jit-cpuid-x86.h:
int jit_insn_push(jit_function_t func, jit_value_t value) JIT_NOTHROW;
int jit_insn_push_ptr
(jit_function_t func, jit_value_t value, jit_type_t type) JIT_NOTHROW;
+int jit_insn_set_param
+ (jit_function_t func, jit_value_t value, jit_nint offset) JIT_NOTHROW;
+int jit_insn_set_param_ptr
+ (jit_function_t func, jit_value_t value, jit_type_t type,
+ jit_nint offset) JIT_NOTHROW;
int jit_insn_pop_stack(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
int jit_insn_defer_pop_stack
(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
#define JIT_OP_PUSH_STRUCT 0x016E
#define JIT_OP_POP_STACK 0x016F
#define JIT_OP_FLUSH_SMALL_STRUCT 0x0170
+#define JIT_OP_SET_PARAM_INT 0x0171
+#define JIT_OP_SET_PARAM_LONG 0x0172
+#define JIT_OP_SET_PARAM_FLOAT32 0x0173
+#define JIT_OP_SET_PARAM_FLOAT64 0x0174
+#define JIT_OP_SET_PARAM_NFLOAT 0x0175
+#define JIT_OP_SET_PARAM_STRUCT 0x0176
/*
* Pointer-relative loads and stores.
*/
-#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0171
-#define JIT_OP_LOAD_RELATIVE_UBYTE 0x0172
-#define JIT_OP_LOAD_RELATIVE_SHORT 0x0173
-#define JIT_OP_LOAD_RELATIVE_USHORT 0x0174
-#define JIT_OP_LOAD_RELATIVE_INT 0x0175
-#define JIT_OP_LOAD_RELATIVE_LONG 0x0176
-#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x0177
-#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x0178
-#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0179
-#define JIT_OP_LOAD_RELATIVE_STRUCT 0x017A
-#define JIT_OP_STORE_RELATIVE_BYTE 0x017B
-#define JIT_OP_STORE_RELATIVE_SHORT 0x017C
-#define JIT_OP_STORE_RELATIVE_INT 0x017D
-#define JIT_OP_STORE_RELATIVE_LONG 0x017E
-#define JIT_OP_STORE_RELATIVE_FLOAT32 0x017F
-#define JIT_OP_STORE_RELATIVE_FLOAT64 0x0180
-#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0181
-#define JIT_OP_STORE_RELATIVE_STRUCT 0x0182
-#define JIT_OP_ADD_RELATIVE 0x0183
+#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0177
+#define JIT_OP_LOAD_RELATIVE_UBYTE 0x0178
+#define JIT_OP_LOAD_RELATIVE_SHORT 0x0179
+#define JIT_OP_LOAD_RELATIVE_USHORT 0x017A
+#define JIT_OP_LOAD_RELATIVE_INT 0x017B
+#define JIT_OP_LOAD_RELATIVE_LONG 0x017C
+#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x017D
+#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x017E
+#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x017F
+#define JIT_OP_LOAD_RELATIVE_STRUCT 0x0180
+#define JIT_OP_STORE_RELATIVE_BYTE 0x0181
+#define JIT_OP_STORE_RELATIVE_SHORT 0x0182
+#define JIT_OP_STORE_RELATIVE_INT 0x0183
+#define JIT_OP_STORE_RELATIVE_LONG 0x0184
+#define JIT_OP_STORE_RELATIVE_FLOAT32 0x0185
+#define JIT_OP_STORE_RELATIVE_FLOAT64 0x0186
+#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0187
+#define JIT_OP_STORE_RELATIVE_STRUCT 0x0188
+#define JIT_OP_ADD_RELATIVE 0x0189
/*
* Array element loads and stores.
*/
-#define JIT_OP_LOAD_ELEMENT_SBYTE 0x0184
-#define JIT_OP_LOAD_ELEMENT_UBYTE 0x0185
-#define JIT_OP_LOAD_ELEMENT_SHORT 0x0186
-#define JIT_OP_LOAD_ELEMENT_USHORT 0x0187
-#define JIT_OP_LOAD_ELEMENT_INT 0x0188
-#define JIT_OP_LOAD_ELEMENT_LONG 0x0189
-#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x018A
-#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x018B
-#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x018C
-#define JIT_OP_STORE_ELEMENT_BYTE 0x018D
-#define JIT_OP_STORE_ELEMENT_SHORT 0x018E
-#define JIT_OP_STORE_ELEMENT_INT 0x018F
-#define JIT_OP_STORE_ELEMENT_LONG 0x0190
-#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0191
-#define JIT_OP_STORE_ELEMENT_FLOAT64 0x0192
-#define JIT_OP_STORE_ELEMENT_NFLOAT 0x0193
+#define JIT_OP_LOAD_ELEMENT_SBYTE 0x018A
+#define JIT_OP_LOAD_ELEMENT_UBYTE 0x018B
+#define JIT_OP_LOAD_ELEMENT_SHORT 0x018C
+#define JIT_OP_LOAD_ELEMENT_USHORT 0x018D
+#define JIT_OP_LOAD_ELEMENT_INT 0x018E
+#define JIT_OP_LOAD_ELEMENT_LONG 0x018F
+#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x0190
+#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x0191
+#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x0192
+#define JIT_OP_STORE_ELEMENT_BYTE 0x0193
+#define JIT_OP_STORE_ELEMENT_SHORT 0x0194
+#define JIT_OP_STORE_ELEMENT_INT 0x0195
+#define JIT_OP_STORE_ELEMENT_LONG 0x0196
+#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0197
+#define JIT_OP_STORE_ELEMENT_FLOAT64 0x0198
+#define JIT_OP_STORE_ELEMENT_NFLOAT 0x0199
/*
* Block operations.
*/
-#define JIT_OP_MEMCPY 0x0194
-#define JIT_OP_MEMMOVE 0x0195
-#define JIT_OP_MEMSET 0x0196
+#define JIT_OP_MEMCPY 0x019A
+#define JIT_OP_MEMMOVE 0x019B
+#define JIT_OP_MEMSET 0x019C
/*
* Allocate memory from the stack.
*/
-#define JIT_OP_ALLOCA 0x0197
+#define JIT_OP_ALLOCA 0x019D
/*
* The number of opcodes in the above list.
*/
-#define JIT_OP_NUM_OPCODES 0x0198
+#define JIT_OP_NUM_OPCODES 0x019E
/*
* Opcode information.
jit_value insn_import(jit_value value);
void insn_push(const jit_value& value);
void insn_push_ptr(const jit_value& value, jit_type_t type);
+ void insn_set_param(const jit_value& value, jit_nint offset);
+ void insn_set_param_ptr
+ (const jit_value& value, jit_type_t type, jit_nint offset);
void insn_return(const jit_value& value);
void insn_return();
void insn_return_ptr(const jit_value& value, jit_type_t type);
}
}
+/*@
+ * @deftypefun int jit_insn_set_param (jit_function_t func, jit_value_t value, jit_nint offset)
+ * Set the parameter slot at @code{offset} in the outgoing parameter area
+ * to @code{value}. This may be used instead of @code{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.
+ *
+ * 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.
+ * @end deftypefun
+@*/
+int jit_insn_set_param(jit_function_t func, jit_value_t value, jit_nint offset)
+{
+ jit_type_t type;
+ if(!value)
+ {
+ return 0;
+ }
+ type = jit_type_promote_int(jit_type_normalize(jit_value_get_type(value)));
+ switch(type->kind)
+ {
+ case JIT_TYPE_SBYTE:
+ case JIT_TYPE_UBYTE:
+ case JIT_TYPE_SHORT:
+ case JIT_TYPE_USHORT:
+ case JIT_TYPE_INT:
+ case JIT_TYPE_UINT:
+ {
+ return create_note(func, JIT_OP_SET_PARAM_INT, value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, offset));
+ }
+ /* Not reached */
+
+ case JIT_TYPE_LONG:
+ case JIT_TYPE_ULONG:
+ {
+ return create_note(func, JIT_OP_SET_PARAM_LONG, value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, offset));
+ }
+ /* Not reached */
+
+ case JIT_TYPE_FLOAT32:
+ {
+ return create_note(func, JIT_OP_SET_PARAM_FLOAT32, value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, offset));
+ }
+ /* Not reached */
+
+ case JIT_TYPE_FLOAT64:
+ {
+ return create_note(func, JIT_OP_SET_PARAM_FLOAT64, value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, offset));
+ }
+ /* Not reached */
+
+ case JIT_TYPE_NFLOAT:
+ {
+ return create_note(func, JIT_OP_SET_PARAM_NFLOAT, value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, offset));
+ }
+ /* Not reached */
+
+ case JIT_TYPE_STRUCT:
+ case JIT_TYPE_UNION:
+ {
+ /* We need the address of the value for "push_struct" */
+ value = jit_insn_address_of(func, value);
+ if(!value)
+ {
+ return 0;
+ }
+ return apply_ternary
+ (func, JIT_OP_SET_PARAM_STRUCT,
+ jit_value_create_nint_constant(func, jit_type_nint, offset),
+ value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, (jit_nint)jit_type_get_size(type)));
+ }
+ /* Not reached */
+ }
+ return 1;
+}
+
+/*@
+ * @deftypefun int jit_insn_set_param_ptr (jit_function_t func, jit_value_t value, jit_type_t type, jit_nint offset)
+ * Same as @code{jit_insn_set_param_ptr}, except that the parameter is
+ * at @code{*value}.
+ * @end deftypefun
+@*/
+int jit_insn_set_param_ptr
+ (jit_function_t func, jit_value_t value, jit_type_t type, jit_nint offset)
+{
+ if(!value || !type)
+ {
+ return 0;
+ }
+ switch(jit_type_normalize(type)->kind)
+ {
+ case JIT_TYPE_STRUCT:
+ case JIT_TYPE_UNION:
+ {
+ /* Set the structure into the parameter area by address */
+ return apply_ternary
+ (func, JIT_OP_SET_PARAM_STRUCT,
+ jit_value_create_nint_constant(func, jit_type_nint, offset),
+ value,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, (jit_nint)jit_type_get_size(type)));
+ }
+ /* Not reached */
+
+ default:
+ {
+ /* Load the value from the address and set it normally */
+ return jit_insn_set_param
+ (func, jit_insn_load_relative(func, value, 0, type), offset);
+ }
+ /* Not reached */
+ }
+}
+
/*@
* @deftypefun int jit_insn_pop_stack (jit_function_t func, jit_nint num_items)
* Pop @code{num_items} items from the function call stack. You normally
/* Number of stack items that are queued for a deferred pop */
jit_nint deferred_items;
+ /* Size of the outgoing parameter area in the frame */
+ jit_nint param_area_size;
+
};
/*
VMCASE(JIT_OP_PUSH_FLOAT64):
VMCASE(JIT_OP_PUSH_NFLOAT):
VMCASE(JIT_OP_FLUSH_SMALL_STRUCT):
+ VMCASE(JIT_OP_SET_PARAM_INT):
+ VMCASE(JIT_OP_SET_PARAM_LONG):
+ VMCASE(JIT_OP_SET_PARAM_FLOAT32):
+ VMCASE(JIT_OP_SET_PARAM_FLOAT64):
+ VMCASE(JIT_OP_SET_PARAM_NFLOAT):
+ VMCASE(JIT_OP_SET_PARAM_STRUCT):
VMCASE(JIT_OP_ENTER_FINALLY):
VMCASE(JIT_OP_ENTER_FILTER):
VMCASE(JIT_OP_CALL_FILTER_RETURN):
{"push_struct", F_(EMPTY, ANY, PTR) | NINT_ARG},
{"pop_stack", F_(EMPTY, INT, EMPTY) | NINT_ARG},
{"flush_small_struct", F_(EMPTY, ANY, EMPTY)},
+ {"set_param_int", F_(EMPTY, INT, PTR)},
+ {"set_param_long", F_(EMPTY, LONG, PTR)},
+ {"set_param_float32", F_(EMPTY, FLOAT32, PTR)},
+ {"set_param_float64", F_(EMPTY, FLOAT64, PTR)},
+ {"set_param_nfloat", F_(EMPTY, NFLOAT, PTR)},
+ {"set_param_struct", F_(PTR, PTR, PTR)},
/*
* Pointer-relative loads and stores.
unsigned int index;
unsigned int num_stack_args;
unsigned int word_regs;
+ unsigned int param_offset;
/* Determine which values are going to end up in registers */
word_regs = 0;
}
num_stack_args = num_args - index;
- /* Push all of the stacked arguments in reverse order */
+ /* Determine the highest parameter offset */
+ param_offset = 0;
+ for(index = 0; index < num_stack_args; ++index)
+ {
+ size = jit_type_get_size
+ (jit_value_get_type(args[num_args - 1 - index]));
+ param_offset += ROUND_STACK(size);
+ }
+ if(param_offset > (unsigned int)(func->builder->param_area_size))
+ {
+ func->builder->param_area_size = (jit_nint)param_offset;
+ }
+
+ /* Set all of the stacked arguments in reverse order. We set them
+ into the outgoing parameter area, which allows us to avoid constantly
+ updating the stack pointer when pushing stacked arguments */
while(num_stack_args > 0)
{
--num_stack_args;
--num_args;
- if(!jit_insn_push(func, args[num_args]))
+ size = jit_type_get_size(jit_value_get_type(args[num_args]));
+ param_offset -= ROUND_STACK(size);
+ if(!jit_insn_set_param(func, args[num_args], (jit_nint)param_offset))
{
return 0;
}
jit_value_t *args, unsigned int num_args,
jit_value_t return_value, int is_nested)
{
- jit_nint pop_bytes;
- unsigned int size;
jit_type_t return_type;
int ptr_return;
- /* Calculate the number of bytes that we need to pop */
+ /* Bail out now if we don't need to worry about return values */
return_type = jit_type_normalize(jit_type_get_return(signature));
ptr_return = jit_type_return_via_pointer(return_type);
- pop_bytes = 0;
- while(num_args > 0)
- {
- --num_args;
- size = jit_type_get_size(jit_value_get_type(args[num_args]));
- pop_bytes += ROUND_STACK(size);
- }
- if(ptr_return)
- {
- pop_bytes += sizeof(void *);
- }
- if(is_nested)
- {
- pop_bytes += sizeof(void *);
- }
- if(pop_bytes > (ARM_NUM_PARAM_REGS * sizeof(void *)))
- {
- pop_bytes -= (ARM_NUM_PARAM_REGS * sizeof(void *));
- }
- else
- {
- pop_bytes = 0;
- }
-
- /* Pop the bytes from the system stack */
- if(pop_bytes > 0)
- {
- if(!jit_insn_pop_stack(func, pop_bytes))
- {
- return 0;
- }
- }
-
- /* Bail out now if we don't need to worry about return values */
if(!return_value || ptr_return)
{
return 0;
the space for the registers that we just saved. The pc, lr,
and fp registers are always saved, so account for them too */
frame_size = func->builder->frame_size - (saved + 3 * sizeof(void *));
+ frame_size += (unsigned int)(func->builder->param_area_size);
if(frame_size > 0)
{
arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, frame_size);
}
}
+JIT_OP_SET_PARAM_INT: unary_note
+ [reg] -> {
+ arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
+ }
+
+JIT_OP_SET_PARAM_LONG: manual
+ [] -> {
+ arm_inst_buf inst;
+ _jit_regs_force_out(gen, insn->value1, 0);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(insn->value1->is_constant)
+ {
+ mov_reg_imm
+ (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ mov_reg_imm
+ (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+ insn->value1->frame_offset);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+ insn->value1->frame_offset + 4);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+ }
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note
+ [freg] -> {
+ arm_store_membase_float32(inst, $1, ARM_SP, insn->value2->address);
+ }
+
+JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+ [] -> {
+ arm_inst_buf inst;
+ _jit_regs_force_out(gen, insn->value1, 0);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(insn->value1->is_constant)
+ {
+ mov_reg_imm
+ (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+ insn->value1->frame_offset);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ }
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+ (JIT_ARM_HAS_FLOAT_REGS): unary_note
+ [freg] -> {
+ arm_store_membase_float64(inst, $1, ARM_SP, insn->value2->address);
+ }
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+ (!JIT_ARM_HAS_FLOAT_REGS): manual
+ [] -> {
+ arm_inst_buf inst;
+ _jit_regs_force_out(gen, insn->value1, 0);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(insn->value1->is_constant)
+ {
+ mov_reg_imm
+ (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ mov_reg_imm
+ (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+ insn->value1->frame_offset);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+ insn->value1->frame_offset + 4);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
+ }
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_SET_PARAM_STRUCT: unary_note
+ [reg] -> {
+ /* TODO */
+ TODO();
+ }
+
/*
* Pointer-relative loads and stores.
*/
* @deftypemethodx jit_function jit_value insn_import (jit_value value)
* @deftypemethodx jit_function void insn_push ({const jit_value&} value)
* @deftypemethodx jit_function void insn_push_ptr ({const jit_value&} value, jit_type_t type)
+ * @deftypemethodx jit_function void insn_set_param ({const jit_value&} value, jit_nint offset)
+ * @deftypemethodx jit_function void insn_set_param_ptr ({const jit_value&} value, jit_type_t type, jit_nint offset)
* @deftypemethodx jit_function void insn_return ({const jit_value&} value)
* @deftypemethodx jit_function void insn_return ()
* @deftypemethodx jit_function void insn_return_ptr ({const jit_value&} value, jit_type_t type)
}
}
+void jit_function::insn_set_param(const jit_value& value, jit_nint offset)
+{
+ if(!jit_insn_set_param(func, value.raw(), offset))
+ {
+ out_of_memory();
+ }
+}
+
+void jit_function::insn_set_param_ptr
+ (const jit_value& value, jit_type_t type, jit_nint offset)
+{
+ if(!jit_insn_set_param_ptr(func, value.raw(), type, offset))
+ {
+ out_of_memory();
+ }
+}
+
void jit_function::insn_return(const jit_value& value)
{
if(!jit_insn_return(func, value.raw()))