From 5952bf08262d3e776aff52b833daf70cae897e16 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 4 Oct 2004 00:51:45 +0000 Subject: [PATCH] Add instructions and function API's for supporting debug line numbers and breakpoints. --- ChangeLog | 10 +++++++ include/jit/jit-function.h | 2 ++ include/jit/jit-insn.h | 11 ++++++-- include/jit/jit-opcode.h | 8 +++++- include/jit/jit-plus.h | 2 ++ jit/jit-function.c | 52 +++++++++++++++++++++++++++++++++++ jit/jit-insn.c | 42 ++++++++++++++++++++++++++++ jit/jit-internal.h | 1 + jit/jit-interp.c | 13 +++++++++ jit/jit-opcode.c | 6 ++++ jit/jit-rules-arm.sel | 10 +++++++ jit/jit-rules-interp.c | 9 ++++++ jit/jit-rules-x86.sel | 10 +++++++ jitplus/jit-plus-function.cpp | 18 ++++++++++++ 14 files changed, 191 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f83863e..53ce649 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ +2004-10-04 Rhys Weatherley + + * 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 * jit/jit-rules-x86.sel: pointer-relative loads and stores diff --git a/include/jit/jit-function.h b/include/jit/jit-function.h index cd5e5d6..c376d7f 100644 --- a/include/jit/jit-function.h +++ b/include/jit/jit-function.h @@ -70,6 +70,8 @@ void jit_function_set_optimization_level 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 }; diff --git a/include/jit/jit-insn.h b/include/jit/jit-insn.h index d974121..299ee79 100644 --- a/include/jit/jit-insn.h +++ b/include/jit/jit-insn.h @@ -304,9 +304,16 @@ jit_value_t jit_insn_alloca (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 diff --git a/include/jit/jit-opcode.h b/include/jit/jit-opcode.h index b6f20d3..ec370a5 100644 --- a/include/jit/jit-opcode.h +++ b/include/jit/jit-opcode.h @@ -511,10 +511,16 @@ extern "C" { */ #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. diff --git a/include/jit/jit-plus.h b/include/jit/jit-plus.h index 05bb291..6f118d5 100644 --- a/include/jit/jit-plus.h +++ b/include/jit/jit-plus.h @@ -350,6 +350,8 @@ public: (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; diff --git a/jit/jit-function.c b/jit/jit-function.c index 578622b..6e7f3d3 100644 --- a/jit/jit-function.c +++ b/jit/jit-function.c @@ -518,6 +518,16 @@ static void compile_block(jit_gencode_t gen, 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 */ @@ -1278,3 +1288,45 @@ unsigned int jit_function_get_max_optimization_level(void) /* 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; + } +} diff --git a/jit/jit-insn.c b/jit/jit-insn.c index fb460c8..e334eef 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -7675,6 +7675,48 @@ int jit_insn_move_blocks_to_start 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}. diff --git a/jit/jit-internal.h b/jit/jit-internal.h index 4cb6ac5..4afbe51 100644 --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@ -377,6 +377,7 @@ struct _jit_function 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; diff --git a/jit/jit-interp.c b/jit/jit-interp.c index b92fb76..0de6402 100644 --- a/jit/jit-interp.c +++ b/jit/jit-interp.c @@ -4456,6 +4456,18 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args, } 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. @@ -4495,6 +4507,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args, 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); diff --git a/jit/jit-opcode.c b/jit/jit-opcode.c index ed60e5c..0d2a992 100644 --- a/jit/jit-opcode.c +++ b/jit/jit-opcode.c @@ -527,6 +527,12 @@ jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES] = { */ {"alloca", F_(PTR, PTR, EMPTY)}, + /* + * Debugging support. + */ + {"mark_offset", F_(EMPTY, INT, EMPTY)}, + {"mark_debug", F_(EMPTY, PTR, PTR)}, + }; #if defined(JIT_BACKEND_INTERP) diff --git a/jit/jit-rules-arm.sel b/jit/jit-rules-arm.sel index 173033f..d41b761 100644 --- a/jit/jit-rules-arm.sel +++ b/jit/jit-rules-arm.sel @@ -1399,3 +1399,13 @@ JIT_OP_ADD_RELATIVE: unary arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address); } } + +/* + * Debugging support. + */ + +JIT_OP_MARK_DEBUG: manual + [] -> { + /* TODO */ + TODO(); + } diff --git a/jit/jit-rules-interp.c b/jit/jit-rules-interp.c index 032054e..e8ceefc 100644 --- a/jit/jit-rules-interp.c +++ b/jit/jit-rules-interp.c @@ -1631,6 +1631,15 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, } 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, diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index 30aa4cc..2d7f612 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -2800,3 +2800,13 @@ JIT_OP_ALLOCA: unary x86_mov_reg_reg(inst, $1, X86_ESP, 4); gen->stack_changed = 1; } + +/* + * Debugging support. + */ + +JIT_OP_MARK_DEBUG: manual + [] -> { + /* TODO */ + TODO(); + } diff --git a/jitplus/jit-plus-function.cpp b/jitplus/jit-plus-function.cpp index 1723771..df486a7 100644 --- a/jitplus/jit-plus-function.cpp +++ b/jitplus/jit-plus-function.cpp @@ -672,6 +672,8 @@ jit_value jit_function::get_struct_pointer() * @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 @@ -1426,6 +1428,22 @@ void jit_function::insn_move_blocks_to_start } } +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); -- 2.47.3