numbers and breakpoints.
+2004-10-04 Rhys Weatherley <rweather@southern-storm.com.au>
+
+ * include/jit/jit-function.h, include/jit/jit-insn.h,
+ include/jit/jit-opcode.h, include/jit/jit-plus.h, jit/jit-function.c,
+ jit/jit-insn.c, jit/jit-internal.h, jit/jit-interp.c,
+ jit/jit-opcode.c, jit/jit-rules-interp.c, jit/jit-rules-arm.sel,
+ jit/jit-rules-x86.sel, jitplus/jit-plus-function.cpp:
+ add instructions and function API's for supporting debug line
+ numbers and breakpoints.
+
2004-09-10 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-x86.sel: pointer-relative loads and stores
unsigned int jit_function_get_optimization_level
(jit_function_t func) JIT_NOTHROW;
unsigned int jit_function_get_max_optimization_level(void) JIT_NOTHROW;
+void jit_function_enable_breakpoints(jit_function_t func, int flag) JIT_NOTHROW;
+int jit_function_breakpoints_enabled(jit_function_t func) JIT_NOTHROW;
#ifdef __cplusplus
};
(jit_function_t func, jit_value_t size) JIT_NOTHROW;
int jit_insn_move_blocks_to_end
- (jit_function_t func, jit_label_t from_label, jit_label_t to_label);
+ (jit_function_t func, jit_label_t from_label, jit_label_t to_label)
+ JIT_NOTHROW;
int jit_insn_move_blocks_to_start
- (jit_function_t func, jit_label_t from_label, jit_label_t to_label);
+ (jit_function_t func, jit_label_t from_label, jit_label_t to_label)
+ JIT_NOTHROW;
+
+int jit_insn_mark_offset
+ (jit_function_t func, jit_int offset) JIT_NOTHROW;
+int jit_insn_mark_debug
+ (jit_function_t func, jit_nint data1, jit_nint data2) JIT_NOTHROW;
void jit_insn_iter_init(jit_insn_iter_t *iter, jit_block_t block) JIT_NOTHROW;
void jit_insn_iter_init_last
*/
#define JIT_OP_ALLOCA 0x019F
+/*
+ * Debugging support.
+ */
+#define JIT_OP_MARK_OFFSET 0x01A0
+#define JIT_OP_MARK_DEBUG 0x01A1
+
/*
* The number of opcodes in the above list.
*/
-#define JIT_OP_NUM_OPCODES 0x01A0
+#define JIT_OP_NUM_OPCODES 0x01A2
/*
* Opcode information.
(const jit_label& from_label, const jit_label& to_label);
void insn_move_blocks_to_start
(const jit_label& from_label, const jit_label& to_label);
+ void insn_mark_offset(jit_int offset);
+ void insn_mark_debug(jit_nint data1, jit_nint data2);
private:
jit_function_t func;
}
break;
+ case JIT_OP_MARK_OFFSET:
+ {
+ /* Mark the current code position as corresponding
+ to a particular bytecode offset */
+ _jit_cache_mark_bytecode
+ (&(gen->posn), (unsigned long)(long)
+ jit_value_get_nint_constant(insn->value1));
+ }
+ break;
+
default:
{
/* Generate code for the instruction with the back end */
/* TODO - implement more than basic optimization */
return 0;
}
+
+/*@
+ * @deftypefun void jit_function_enable_breakpoints (jit_function_t func)
+ * Enable or disable all breakpoints in the specified function. Breakpoints
+ * occur at locations marked by @code{jit_insn_mark_debug}.
+ *
+ * The @code{libjit} library provides a very simple breakpoint mechanism.
+ * Upon reaching each breakpoint in the function, the global debug hook
+ * is called. It is up to the debug hook to decide whether to stop execution
+ * or to ignore the breakpoint.
+ *
+ * Typically, the debug hook will inspect a table to determine which
+ * breakpoints were actually selected by the user in a debugger's user
+ * interface. The debug hook may even evaluate a complicated expression,
+ * taking the function, current thread, and the value of local variables
+ * into account, to make the decision.
+ * @end deftypefun
+@*/
+void jit_function_enable_breakpoints(jit_function_t func, int flag)
+{
+ if(func)
+ {
+ func->breakpoints_enabled = flag;
+ }
+}
+
+/*@
+ * @deftypefun int jit_function_breakpoints_enabled (jit_function_t func)
+ * Determine if breakpoints are enabled on the specified function.
+ * @end deftypefun
+@*/
+int jit_function_breakpoints_enabled(jit_function_t func)
+{
+ if(func)
+ {
+ return func->breakpoints_enabled;
+ }
+ else
+ {
+ return 0;
+ }
+}
return 1;
}
+/*@
+ * @deftypefun int jit_insn_mark_offset (jit_function_t func, jit_int offset)
+ * Mark the current position in @code{func} as corresponding to the
+ * specified bytecode @code{offset}. This value will be returned
+ * by @code{jit_stack_trace_get_offset}, and is useful for associating
+ * code positions with source line numbers.
+ * @end deftypefun
+@*/
+int jit_insn_mark_offset(jit_function_t func, jit_int offset)
+{
+ if(!jit_insn_new_block(func))
+ {
+ return 0;
+ }
+ return create_unary_note(func, JIT_OP_MARK_OFFSET,
+ jit_value_create_nint_constant
+ (func, jit_type_int, offset));
+}
+
+/*@
+ * @deftypefun int jit_insn_mark_debug (jit_function_t func, jit_nint data1, jit_nint data2)
+ * Mark the current position in @code{func} as corresponding to a breakpoint
+ * location. When a break occurs, the global debug hook is called with
+ * @code{func}, @code{data1}, and @code{data2} as arguments. See the
+ * description for @code{jit_function_enable_breakpoints} for more
+ * information on breakpoint support.
+ * @end deftypefun
+@*/
+int jit_insn_mark_debug
+ (jit_function_t func, jit_nint data1, jit_nint data2)
+{
+ if(!jit_insn_new_block(func))
+ {
+ return 0;
+ }
+ return create_note(func, JIT_OP_MARK_DEBUG,
+ jit_value_create_nint_constant
+ (func, jit_type_nint, data1),
+ jit_value_create_nint_constant
+ (func, jit_type_nint, data2));
+}
+
/*@
* @deftypefun void jit_insn_iter_init ({jit_insn_iter_t *} iter, jit_block_t block)
* Initialize an iterator to point to the first instruction in @code{block}.
int has_try : 1;
int optimization_level : 8;
int volatile is_compiled;
+ int volatile breakpoints_enabled;
/* The entry point for the function's compiled code */
void * volatile entry_point;
}
VMBREAK;
+ /******************************************************************
+ * Debugging support.
+ ******************************************************************/
+
+ VMCASE(JIT_OP_MARK_DEBUG):
+ {
+ /* Process a breakpoint within the current function */
+ /* TODO */
+ VM_MODIFY_PC_AND_STACK(3, 0);
+ }
+ VMBREAK;
+
/******************************************************************
* Opcodes that aren't used by the interpreter. These are replaced
* by more specific instructions during function compilation.
VMCASE(JIT_OP_ENTER_FINALLY):
VMCASE(JIT_OP_ENTER_FILTER):
VMCASE(JIT_OP_CALL_FILTER_RETURN):
+ VMCASE(JIT_OP_MARK_OFFSET):
{
/* Shouldn't happen, but skip the instruction anyway */
VM_MODIFY_PC_AND_STACK(1, 0);
*/
{"alloca", F_(PTR, PTR, EMPTY)},
+ /*
+ * Debugging support.
+ */
+ {"mark_offset", F_(EMPTY, INT, EMPTY)},
+ {"mark_debug", F_(EMPTY, PTR, PTR)},
+
};
#if defined(JIT_BACKEND_INTERP)
arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address);
}
}
+
+/*
+ * Debugging support.
+ */
+
+JIT_OP_MARK_DEBUG: manual
+ [] -> {
+ /* TODO */
+ TODO();
+ }
}
break;
+ case JIT_OP_MARK_DEBUG:
+ {
+ /* Mark the current location as a potential breakpoint */
+ jit_cache_opcode(&(gen->posn), insn->opcode);
+ jit_cache_native(&(gen->posn), insn->value1->address);
+ jit_cache_native(&(gen->posn), insn->value2->address);
+ }
+ break;
+
default:
{
/* Whatever opcodes are left are ordinary operators,
x86_mov_reg_reg(inst, $1, X86_ESP, 4);
gen->stack_changed = 1;
}
+
+/*
+ * Debugging support.
+ */
+
+JIT_OP_MARK_DEBUG: manual
+ [] -> {
+ /* TODO */
+ TODO();
+ }
* @deftypemethodx jit_function jit_value jit_insn_alloca ({const jit_value&} size)
* @deftypemethodx jit_function void insn_move_blocks_to_end ({const jit_label&} from_label, {const jit_label&} to_label)
* @deftypemethodx jit_function void insn_move_blocks_to_start ({const jit_label&} from_label, {const jit_label&} to_label)
+ * @deftypemethodx jit_function void insn_mark_offset (jit_int offset)
+ * @deftypemethodx jit_function void insn_mark_debug (jit_nint data1, jit_nint data2)
* Create instructions of various kinds. @xref{Instructions}, for more
* information on the individual instructions and their arguments.
* @end deftypemethod
}
}
+void jit_function::insn_mark_offset(jit_int offset)
+{
+ if(!jit_insn_mark_offset(func, offset))
+ {
+ out_of_memory();
+ }
+}
+
+void jit_function::insn_mark_debug(jit_nint data1, jit_nint data2)
+{
+ if(!jit_insn_mark_debug(func, data1, data2))
+ {
+ out_of_memory();
+ }
+}
+
void jit_function::register_on_demand()
{
jit_function_set_on_demand_compiler(func, on_demand_compiler);