mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
support multiple filename in irep
This commit is contained in:
@@ -38,6 +38,7 @@ void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(stru
|
||||
typedef struct mrb_ast_node {
|
||||
struct mrb_ast_node *car, *cdr;
|
||||
short lineno;
|
||||
char const* filename;
|
||||
} mrb_ast_node;
|
||||
|
||||
/* lexer states */
|
||||
@@ -110,7 +111,7 @@ struct mrb_parser_state {
|
||||
FILE *f;
|
||||
#endif
|
||||
mrbc_context *cxt;
|
||||
char *filename;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int column;
|
||||
|
||||
@@ -150,6 +151,8 @@ struct mrb_parser_state* mrb_parser_new(mrb_state*);
|
||||
void mrb_parser_free(struct mrb_parser_state*);
|
||||
void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
|
||||
|
||||
void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
|
||||
|
||||
/* utility functions */
|
||||
#ifdef ENABLE_STDIO
|
||||
struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef MRUBY_DEBUG_H
|
||||
#define MRUBY_DEBUG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mruby/value.h"
|
||||
|
||||
typedef enum mrb_debug_line_type {
|
||||
mrb_debug_line_ary = 0,
|
||||
mrb_debug_line_flat_map = 1
|
||||
} mrb_debug_line_type;
|
||||
|
||||
typedef struct mrb_irep_debug_info_line {
|
||||
uint32_t start_pos;
|
||||
uint16_t line;
|
||||
} mrb_irep_debug_info_line;
|
||||
|
||||
typedef struct mrb_irep_debug_info_file {
|
||||
uint32_t start_pos;
|
||||
char const* filename;
|
||||
mrb_sym filename_sym;
|
||||
uint32_t line_entry_count;
|
||||
mrb_debug_line_type line_type;
|
||||
union {
|
||||
void* line_ptr;
|
||||
mrb_irep_debug_info_line* line_flat_map;
|
||||
uint16_t* line_ary;
|
||||
};
|
||||
} mrb_irep_debug_info_file;
|
||||
|
||||
typedef struct mrb_irep_debug_info {
|
||||
uint32_t pc_count;
|
||||
uint16_t flen;
|
||||
mrb_irep_debug_info_file** files;
|
||||
} mrb_irep_debug_info;
|
||||
|
||||
struct mrb_irep;
|
||||
struct mrb_state;
|
||||
|
||||
/*
|
||||
* get line from irep's debug info and program counter
|
||||
* @return returns NULL if not found
|
||||
*/
|
||||
char const* mrb_get_filename(struct mrb_irep* irep, uint32_t pc);
|
||||
|
||||
/*
|
||||
* get line from irep's debug info and program counter
|
||||
* @return returns -1 if not found
|
||||
*/
|
||||
int32_t mrb_get_line(struct mrb_irep* irep, uint32_t pc);
|
||||
|
||||
mrb_irep_debug_info_file* mrb_debug_info_append_file(
|
||||
struct mrb_state* mrb, struct mrb_irep* irep,
|
||||
uint32_t start_pos, uint32_t end_pos);
|
||||
mrb_irep_debug_info* mrb_debug_info_alloc(struct mrb_state* mrb, struct mrb_irep* irep);
|
||||
void mrb_debug_info_free(struct mrb_state* mrb, mrb_irep_debug_info* d);
|
||||
|
||||
#endif /* MRUBY_DEBUG_H */
|
||||
+10
-2
@@ -52,6 +52,7 @@ mrb_value mrb_load_irep_file(mrb_state*,FILE*);
|
||||
#define RITE_BINARY_EOF "END\0"
|
||||
#define RITE_SECTION_IREP_IDENTIFIER "IREP"
|
||||
#define RITE_SECTION_LINENO_IDENTIFIER "LINE"
|
||||
#define RITE_SECTION_DEBUG_IDENTIFIER "DBG\0"
|
||||
|
||||
#define MRB_DUMP_DEFAULT_STR_LEN 128
|
||||
|
||||
@@ -79,14 +80,21 @@ struct rite_section_irep_header {
|
||||
|
||||
uint8_t rite_version[4]; // Rite Instruction Specification Version
|
||||
uint8_t nirep[2]; // Number of ireps
|
||||
uint8_t sirep[2]; // Start index
|
||||
uint8_t sirep[2]; // Start index
|
||||
};
|
||||
|
||||
struct rite_section_lineno_header {
|
||||
RITE_SECTION_HEADER;
|
||||
|
||||
uint8_t nirep[2]; // Number of ireps
|
||||
uint8_t sirep[2]; // Start index
|
||||
uint8_t sirep[2]; // Start index
|
||||
};
|
||||
|
||||
struct rite_section_debug_header {
|
||||
RITE_SECTION_HEADER;
|
||||
|
||||
uint8_t nirep[2]; // Number of ireps
|
||||
uint8_t sirep[2]; // Start index
|
||||
};
|
||||
|
||||
struct rite_binary_footer {
|
||||
|
||||
@@ -25,6 +25,7 @@ typedef struct mrb_irep {
|
||||
/* debug info */
|
||||
const char *filename;
|
||||
uint16_t *lines;
|
||||
struct mrb_irep_debug_info* debug_info;
|
||||
|
||||
size_t ilen, plen, slen;
|
||||
} mrb_irep;
|
||||
|
||||
+14
-14
@@ -10,6 +10,7 @@
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/class.h"
|
||||
#include "mruby/debug.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef void (*output_stream_func)(mrb_state*, void*, int, const char*, ...);
|
||||
@@ -70,7 +71,7 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
|
||||
|
||||
for (i = ciidx; i >= 0; i--) {
|
||||
ci = &mrb->c->cibase[i];
|
||||
filename = "(unknown)";
|
||||
filename = NULL;
|
||||
line = -1;
|
||||
|
||||
if (!verbose && MRB_PROC_CFUNC_P(ci->proc)) {
|
||||
@@ -78,21 +79,16 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
|
||||
}
|
||||
if(!MRB_PROC_CFUNC_P(ci->proc)) {
|
||||
mrb_irep *irep = ci->proc->body.irep;
|
||||
if (irep->filename != NULL)
|
||||
filename = irep->filename;
|
||||
if (irep->lines != NULL) {
|
||||
mrb_code *pc;
|
||||
mrb_code *pc;
|
||||
|
||||
if (i+1 <= ciidx) {
|
||||
pc = mrb->c->cibase[i+1].pc;
|
||||
}
|
||||
else {
|
||||
pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6)));
|
||||
}
|
||||
if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
|
||||
line = irep->lines[pc - irep->iseq - 1];
|
||||
}
|
||||
if (i+1 <= ciidx) {
|
||||
pc = mrb->c->cibase[i+1].pc;
|
||||
}
|
||||
else {
|
||||
pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6)));
|
||||
}
|
||||
filename = mrb_get_filename(irep, pc - irep->iseq - 1);
|
||||
line = mrb_get_line(irep, pc - irep->iseq - 1);
|
||||
}
|
||||
if (!verbose && line == -1) continue;
|
||||
if (ci->target_class == ci->proc->target_class)
|
||||
@@ -100,6 +96,10 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
|
||||
else
|
||||
sep = "#";
|
||||
|
||||
if (!filename) {
|
||||
filename = "(unknown)";
|
||||
}
|
||||
|
||||
method = mrb_sym2name(mrb, ci->mid);
|
||||
if (verbose && !method && ci->proc->env) {
|
||||
method = mrb_sym2name(mrb, ci->proc->env->mid);
|
||||
|
||||
+31
-5
@@ -12,6 +12,7 @@
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/numeric.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/debug.h"
|
||||
#include "node.h"
|
||||
#include "opcode.h"
|
||||
#include "re.h"
|
||||
@@ -51,7 +52,7 @@ typedef struct scope {
|
||||
|
||||
struct loopinfo *loop;
|
||||
int ensure_level;
|
||||
char *filename;
|
||||
char const *filename;
|
||||
short lineno;
|
||||
|
||||
mrb_code *iseq;
|
||||
@@ -67,6 +68,8 @@ typedef struct scope {
|
||||
int ai;
|
||||
|
||||
int idx;
|
||||
|
||||
int debug_start_pos;
|
||||
} codegen_scope;
|
||||
|
||||
static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
|
||||
@@ -142,6 +145,7 @@ genop(codegen_scope *s, mrb_code i)
|
||||
s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
|
||||
if (s->lines) {
|
||||
s->lines = (short*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
|
||||
s->irep->lines = s->lines;
|
||||
}
|
||||
}
|
||||
s->iseq[s->pc] = i;
|
||||
@@ -1107,6 +1111,17 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
int nt;
|
||||
|
||||
if (!tree) return;
|
||||
|
||||
if (s->irep) {
|
||||
if (s->pc > 0 && strcmp(s->filename, tree->filename) != 0) {
|
||||
mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
|
||||
s->debug_start_pos = s->pc;
|
||||
// fprintf(stderr, "%s\n", s->filename);
|
||||
}
|
||||
s->irep->filename = tree->filename;
|
||||
s->filename = tree->filename;
|
||||
}
|
||||
|
||||
nt = (intptr_t)tree->car;
|
||||
s->lineno = tree->lineno;
|
||||
tree = tree->cdr;
|
||||
@@ -2395,6 +2410,18 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
|
||||
p->lines = (short*)mrb_malloc(mrb, sizeof(short)*p->icapa);
|
||||
}
|
||||
p->lineno = prev->lineno;
|
||||
|
||||
// debug setting
|
||||
p->debug_start_pos = 0;
|
||||
if(p->filename) {
|
||||
mrb_debug_info_alloc(mrb, p->irep);
|
||||
p->irep->filename = p->filename;
|
||||
p->irep->lines = p->lines;
|
||||
}
|
||||
else {
|
||||
p->irep->debug_info = NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -2420,6 +2447,8 @@ scope_finish(codegen_scope *s)
|
||||
irep->pool = (mrb_value *)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
|
||||
irep->syms = (mrb_sym *)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
|
||||
if (s->filename) {
|
||||
mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
|
||||
|
||||
fname_len = strlen(s->filename);
|
||||
fname = codegen_malloc(s, fname_len + 1);
|
||||
memcpy(fname, s->filename, fname_len);
|
||||
@@ -2831,7 +2860,6 @@ codedump_all(mrb_state *mrb, int start)
|
||||
codedump(mrb, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
codegen_start(mrb_state *mrb, parser_state *p)
|
||||
{
|
||||
@@ -2841,9 +2869,7 @@ codegen_start(mrb_state *mrb, parser_state *p)
|
||||
return -1;
|
||||
}
|
||||
scope->mrb = mrb;
|
||||
if (p->filename) {
|
||||
scope->filename = p->filename;
|
||||
}
|
||||
scope->filename = p->filename;
|
||||
if (setjmp(scope->jmp) == 0) {
|
||||
// prepare irep
|
||||
codegen(scope, p->tree, NOVAL);
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
#include "mruby/debug.h"
|
||||
|
||||
#include "mruby.h"
|
||||
#include "mruby/irep.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static mrb_irep_debug_info_file*
|
||||
get_file(mrb_irep_debug_info* info, uint32_t const pc)
|
||||
{
|
||||
if(pc >= info->pc_count) { return NULL; }
|
||||
|
||||
// get upper bound
|
||||
mrb_irep_debug_info_file** ret = info->files;
|
||||
int32_t count = info->flen;
|
||||
while (count > 0) {
|
||||
int32_t const step = count / 2;
|
||||
mrb_irep_debug_info_file** const it = ret + step;
|
||||
if (!(pc < (*it)->start_pos)) {
|
||||
ret = it + 1;
|
||||
count -= step + 1;
|
||||
} else { count = step; }
|
||||
}
|
||||
|
||||
--ret;
|
||||
|
||||
mrb_assert(ret < (info->files + info->flen));
|
||||
mrb_assert((*ret)->start_pos <= pc &&
|
||||
pc < (((ret + 1 - info->files) < info->flen)
|
||||
? (*(ret+1))->start_pos : info->pc_count));
|
||||
|
||||
return *ret;
|
||||
}
|
||||
|
||||
static mrb_debug_line_type
|
||||
select_line_type(uint32_t pc_count, uint16_t line_count)
|
||||
{
|
||||
return (sizeof(uint16_t) * pc_count) < (sizeof(mrb_irep_debug_info_line) * line_count)
|
||||
? mrb_debug_line_ary : mrb_debug_line_flat_map;
|
||||
}
|
||||
|
||||
char const*
|
||||
mrb_get_filename(mrb_irep* irep, uint32_t pc)
|
||||
{
|
||||
mrb_irep_debug_info_file* f = NULL;
|
||||
if (irep) {
|
||||
if (!irep->debug_info) { return irep->filename; }
|
||||
else if ((f = get_file(irep->debug_info, pc))) {
|
||||
return f->filename;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t
|
||||
mrb_get_line(mrb_irep* irep, uint32_t const pc)
|
||||
{
|
||||
mrb_irep_debug_info_file* f = NULL;
|
||||
if (irep) {
|
||||
if (!irep->debug_info) {
|
||||
return irep->lines? irep->lines[pc] : -1;
|
||||
}
|
||||
else if ((f = get_file(irep->debug_info, pc))) {
|
||||
switch(f->line_type) {
|
||||
case mrb_debug_line_ary:
|
||||
mrb_assert(pc < (f->start_pos + f->line_entry_count));
|
||||
return f->line_ary[pc];
|
||||
|
||||
case mrb_debug_line_flat_map: {
|
||||
// get upper bound
|
||||
mrb_irep_debug_info_line* ret = f->line_flat_map;
|
||||
int32_t count = f->line_entry_count;
|
||||
while (count > 0) {
|
||||
int32_t const step = count / 2;
|
||||
mrb_irep_debug_info_line* const it = ret + step;
|
||||
if (!(pc < it->start_pos)) {
|
||||
ret = it + 1;
|
||||
count -= step + 1;
|
||||
} else { count = step; }
|
||||
}
|
||||
|
||||
--ret;
|
||||
|
||||
mrb_assert((ret - f->line_flat_map) < f->line_entry_count);
|
||||
mrb_assert(ret->start_pos <= pc &&
|
||||
pc < (((ret + 1 - f->line_flat_map) < f->line_entry_count)
|
||||
? (ret+1)->start_pos : irep->debug_info->pc_count));
|
||||
|
||||
return ret->line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
mrb_irep_debug_info*
|
||||
mrb_debug_info_alloc(mrb_state* mrb, mrb_irep* irep)
|
||||
{
|
||||
static mrb_irep_debug_info const initial = { 0, 0, NULL };
|
||||
mrb_assert(!irep->debug_info);
|
||||
|
||||
mrb_irep_debug_info* const ret = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
|
||||
*ret = initial;
|
||||
irep->debug_info = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mrb_irep_debug_info_file*
|
||||
mrb_debug_info_append_file(mrb_state* mrb, mrb_irep* irep,
|
||||
uint32_t const start_pos, uint32_t const end_pos)
|
||||
{
|
||||
if (!irep->debug_info) { return NULL; }
|
||||
|
||||
mrb_assert(irep->filename);
|
||||
mrb_assert(irep->lines);
|
||||
|
||||
mrb_irep_debug_info* info = irep->debug_info;
|
||||
|
||||
if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mrb_irep_debug_info_file* const ret =
|
||||
(mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file));
|
||||
info->files =
|
||||
(mrb_irep_debug_info_file*)info->files
|
||||
? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
|
||||
: mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*));
|
||||
info->files[info->flen++] = ret;
|
||||
|
||||
uint32_t const file_pc_count = end_pos - start_pos;
|
||||
|
||||
ret->start_pos = start_pos;
|
||||
info->pc_count = end_pos;
|
||||
|
||||
size_t const fn_len = strlen(irep->filename);
|
||||
ret->filename_sym = mrb_intern2(mrb, irep->filename, fn_len);
|
||||
size_t len = 0;
|
||||
ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
|
||||
|
||||
ret->line_type = select_line_type(
|
||||
file_pc_count, irep->lines[end_pos - 1] - irep->lines[0] + 1);
|
||||
ret->line_ptr = NULL;
|
||||
|
||||
switch(ret->line_type) {
|
||||
case mrb_debug_line_ary:
|
||||
ret->line_entry_count = file_pc_count;
|
||||
ret->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
|
||||
for(uint32_t i = 0; i < file_pc_count; ++i) {
|
||||
ret->line_ary[i] = irep->lines[start_pos + i];
|
||||
}
|
||||
break;
|
||||
|
||||
case mrb_debug_line_flat_map: {
|
||||
ret->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
|
||||
ret->line_entry_count = 0;
|
||||
uint16_t prev_line = 0;
|
||||
for(uint32_t i = 0; i < file_pc_count; ++i) {
|
||||
if(irep->lines[start_pos + i] == prev_line) { continue; }
|
||||
|
||||
ret->line_flat_map = mrb_realloc(
|
||||
mrb, ret->line_flat_map,
|
||||
sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
|
||||
mrb_irep_debug_info_line const m = { start_pos + i, irep->lines[start_pos + i] };
|
||||
ret->line_flat_map[ret->line_entry_count] = m;
|
||||
|
||||
// update
|
||||
++ret->line_entry_count;
|
||||
prev_line = irep->lines[start_pos + i];
|
||||
}
|
||||
} break;
|
||||
|
||||
default: mrb_assert(0); break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
mrb_debug_info_free(mrb_state* mrb, mrb_irep_debug_info* d)
|
||||
{
|
||||
if(!d) { return; }
|
||||
|
||||
for(uint32_t i = 0; i < d->flen; ++i) {
|
||||
mrb_assert(d->files[i]);
|
||||
mrb_free(mrb, d->files[i]->line_ptr);
|
||||
mrb_free(mrb, d->files[i]);
|
||||
}
|
||||
mrb_free(mrb, d->files);
|
||||
mrb_free(mrb, d);
|
||||
}
|
||||
+206
-15
@@ -11,6 +11,8 @@
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/numeric.h"
|
||||
#include "mruby/debug.h"
|
||||
#include "mruby/array.h"
|
||||
|
||||
static size_t get_irep_record_size(mrb_state *mrb, mrb_irep *irep);
|
||||
|
||||
@@ -257,7 +259,7 @@ mrb_write_eof(mrb_state *mrb, uint8_t *bin)
|
||||
|
||||
static int
|
||||
mrb_write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
|
||||
{
|
||||
{
|
||||
struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
|
||||
|
||||
memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify));
|
||||
@@ -300,7 +302,7 @@ mrb_write_section_irep(mrb_state *mrb, size_t start_index, uint8_t *bin)
|
||||
|
||||
static int
|
||||
mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
|
||||
{
|
||||
{
|
||||
struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
|
||||
|
||||
// TODO
|
||||
@@ -313,7 +315,7 @@ mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
|
||||
get_lineno_record_size(mrb_state *mrb, mrb_irep *irep)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
@@ -388,9 +390,152 @@ mrb_write_section_lineno(mrb_state *mrb, size_t start_index, uint8_t *bin)
|
||||
return MRB_DUMP_OK;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_debug_record_size(mrb_state* mrb, mrb_irep *irep) {
|
||||
(void)mrb;
|
||||
size_t ret = 0;
|
||||
|
||||
ret += sizeof(uint32_t); // record size
|
||||
ret += sizeof(uint16_t); // file count
|
||||
|
||||
for(uint32_t f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx];
|
||||
|
||||
ret += sizeof(uint32_t); // position
|
||||
ret += sizeof(uint16_t); // filename index
|
||||
|
||||
// lines
|
||||
ret += sizeof(uint32_t); // entry count
|
||||
ret += sizeof(uint8_t); // line type
|
||||
switch(file->line_type) {
|
||||
case mrb_debug_line_ary:
|
||||
ret += sizeof(uint16_t) * file->line_entry_count;
|
||||
break;
|
||||
|
||||
case mrb_debug_line_flat_map:
|
||||
ret += (sizeof(uint32_t) + sizeof(uint16_t)) * file->line_entry_count;
|
||||
break;
|
||||
|
||||
default: mrb_assert(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
find_filename_index(mrb_value const ary, mrb_sym s) {
|
||||
for(mrb_int i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
mrb_assert(mrb_symbol_p(RARRAY_PTR(ary)[i]));
|
||||
if(mrb_symbol(RARRAY_PTR(ary)[i]) == s) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
write_debug_record(mrb_state* mrb, mrb_irep *irep, uint8_t * const bin, mrb_value filenames)
|
||||
{
|
||||
uint8_t *cur = bin + sizeof(uint32_t); // skip record size
|
||||
|
||||
cur += uint16_to_bin(irep->debug_info->flen, cur); // file count
|
||||
for(uint32_t f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx];
|
||||
|
||||
// position
|
||||
cur += uint32_to_bin(file->start_pos, cur);
|
||||
|
||||
// filename index
|
||||
int const filename_idx = find_filename_index(filenames, file->filename_sym);
|
||||
mrb_assert(filename_idx != -1);
|
||||
cur += uint16_to_bin(filename_idx, cur);
|
||||
|
||||
// lines
|
||||
cur += uint32_to_bin(file->line_entry_count, cur);
|
||||
cur += uint8_to_bin(file->line_type, cur);
|
||||
switch(file->line_type) {
|
||||
case mrb_debug_line_ary: {
|
||||
for(size_t l = 0; l < file->line_entry_count; ++l) {
|
||||
cur += uint16_to_bin(file->line_ary[l], cur);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mrb_debug_line_flat_map:
|
||||
for(uint32_t line = 0; line < file->line_entry_count; ++line) {
|
||||
cur += uint32_to_bin(file->line_flat_map[line].start_pos, cur);
|
||||
cur += uint16_to_bin(file->line_flat_map[line].line, cur);
|
||||
}
|
||||
break;
|
||||
|
||||
default: mrb_assert(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t const ret = cur - bin;
|
||||
uint32_to_bin(ret, bin);
|
||||
|
||||
mrb_assert((cur - bin) == (int)get_debug_record_size(mrb, irep));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_write_section_debug(mrb_state* mrb, size_t start_index, uint8_t *cur)
|
||||
{
|
||||
uint32_t section_size = 0;
|
||||
uint8_t* const bin = cur;
|
||||
|
||||
if (mrb == NULL || start_index >= mrb->irep_len || cur == NULL) {
|
||||
return MRB_DUMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct rite_section_debug_header* header = (struct rite_section_debug_header*)bin;
|
||||
cur += sizeof(struct rite_section_debug_header);
|
||||
section_size += sizeof(struct rite_section_debug_header);
|
||||
|
||||
// filename table
|
||||
mrb_value const filenames = mrb_ary_new(mrb);
|
||||
uint8_t* const filenames_len = cur;
|
||||
cur += sizeof(uint16_t);
|
||||
section_size += sizeof(uint16_t);
|
||||
for (size_t irep_i = start_index; irep_i < mrb->irep_len; ++irep_i) {
|
||||
mrb_irep_debug_info const* debug_info = mrb->irep[irep_i]->debug_info;
|
||||
|
||||
for(size_t file_i = 0; file_i < debug_info->flen; ++file_i) {
|
||||
mrb_irep_debug_info_file const* file = debug_info->files[file_i];
|
||||
if(find_filename_index(filenames, file->filename_sym) != -1) continue;
|
||||
|
||||
// register filename
|
||||
mrb_ary_push(mrb, filenames, mrb_symbol_value(file->filename_sym));
|
||||
|
||||
// filename
|
||||
uint16_t const fn_len = strlen(file->filename);
|
||||
cur += uint16_to_bin(fn_len, cur);
|
||||
memcpy(cur, file->filename, fn_len);
|
||||
cur += fn_len;
|
||||
|
||||
section_size += sizeof(uint16_t) + fn_len;
|
||||
}
|
||||
}
|
||||
uint16_to_bin(RARRAY_LEN(filenames), filenames_len);
|
||||
|
||||
// records
|
||||
for (size_t i = start_index; i < mrb->irep_len; ++i) {
|
||||
uint32_t rlen = write_debug_record(mrb, mrb->irep[i], cur, filenames);
|
||||
cur += rlen;
|
||||
section_size += rlen;
|
||||
}
|
||||
|
||||
memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify));
|
||||
uint32_to_bin(section_size, header->section_size);
|
||||
uint16_to_bin(mrb->irep_len - start_index, header->nirep);
|
||||
uint16_to_bin(start_index, header->sirep);
|
||||
|
||||
return MRB_DUMP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin)
|
||||
{
|
||||
{
|
||||
struct rite_binary_header *header = (struct rite_binary_header*)bin;
|
||||
uint16_t crc;
|
||||
size_t offset;
|
||||
@@ -400,7 +545,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin)
|
||||
memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
|
||||
memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
|
||||
uint32_to_bin(binary_size, header->binary_size);
|
||||
|
||||
|
||||
offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t);
|
||||
crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
|
||||
uint16_to_bin(crc, header->binary_crc);
|
||||
@@ -408,6 +553,13 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin)
|
||||
return MRB_DUMP_OK;
|
||||
}
|
||||
|
||||
mrb_bool is_debug_info_defined(mrb_state* mrb, size_t const start_index) {
|
||||
for (size_t i = start_index; i < mrb->irep_len; ++i) {
|
||||
if (!mrb->irep[i]->debug_info) { return 0; }
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, size_t *bin_size)
|
||||
{
|
||||
@@ -418,6 +570,8 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin,
|
||||
size_t irep_no;
|
||||
uint8_t *cur = NULL;
|
||||
|
||||
mrb_bool const debug_info_defined = is_debug_info_defined(mrb, start_index);
|
||||
|
||||
if (mrb == NULL || start_index >= mrb->irep_len) {
|
||||
*bin = NULL;
|
||||
return MRB_DUMP_GENERAL_FAILURE;
|
||||
@@ -431,11 +585,39 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin,
|
||||
|
||||
/* DEBUG section size */
|
||||
if (debug_info) {
|
||||
section_lineno_size += sizeof(struct rite_section_lineno_header);
|
||||
for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
|
||||
section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]);
|
||||
if (debug_info_defined) {
|
||||
section_lineno_size += sizeof(struct rite_section_debug_header);
|
||||
|
||||
// filename table
|
||||
mrb_value const filenames = mrb_ary_new(mrb);
|
||||
// filename table size
|
||||
section_lineno_size += sizeof(uint16_t);
|
||||
for (size_t irep_i = start_index; irep_i < mrb->irep_len; ++irep_i) {
|
||||
mrb_irep_debug_info const* di = mrb->irep[irep_i]->debug_info;
|
||||
|
||||
for(size_t file_i = 0; file_i < di->flen; ++file_i) {
|
||||
mrb_irep_debug_info_file const* file = di->files[file_i];
|
||||
if(find_filename_index(filenames, file->filename_sym) != -1) continue;
|
||||
|
||||
// register filename
|
||||
mrb_ary_push(mrb, filenames, mrb_symbol_value(file->filename_sym));
|
||||
// filename
|
||||
section_lineno_size += sizeof(uint16_t) + strlen(file->filename);
|
||||
}
|
||||
}
|
||||
|
||||
for(irep_no = start_index; irep_no < mrb->irep_len; ++irep_no) {
|
||||
section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]);
|
||||
}
|
||||
section_size += section_lineno_size;
|
||||
}
|
||||
else {
|
||||
section_lineno_size += sizeof(struct rite_section_lineno_header);
|
||||
for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
|
||||
section_lineno_size += get_lineno_record_size(mrb, mrb->irep[irep_no]);
|
||||
}
|
||||
section_size += section_lineno_size;
|
||||
}
|
||||
section_size += section_lineno_size;
|
||||
}
|
||||
|
||||
*bin_size += sizeof(struct rite_binary_header) + section_size + sizeof(struct rite_binary_footer);
|
||||
@@ -450,16 +632,25 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin,
|
||||
if (result != MRB_DUMP_OK) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
|
||||
cur += section_irep_size;
|
||||
|
||||
|
||||
/* write DEBUG section */
|
||||
if (debug_info) {
|
||||
result = mrb_write_section_lineno(mrb, start_index, cur);
|
||||
if (result != MRB_DUMP_OK) {
|
||||
goto error_exit;
|
||||
if(debug_info_defined) {
|
||||
result = mrb_write_section_debug(mrb, start_index, cur);
|
||||
if(result != MRB_DUMP_OK) {
|
||||
goto error_exit;
|
||||
}
|
||||
cur += section_lineno_size;
|
||||
}
|
||||
else {
|
||||
result = mrb_write_section_lineno(mrb, start_index, cur);
|
||||
if (result != MRB_DUMP_OK) {
|
||||
goto error_exit;
|
||||
}
|
||||
cur += section_lineno_size;
|
||||
}
|
||||
cur += section_lineno_size;
|
||||
}
|
||||
|
||||
mrb_write_eof(mrb, cur);
|
||||
|
||||
+6
-3
@@ -15,6 +15,7 @@
|
||||
#include "mruby/proc.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/variable.h"
|
||||
#include "mruby/debug.h"
|
||||
#include "error.h"
|
||||
|
||||
mrb_value
|
||||
@@ -198,9 +199,11 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
|
||||
if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
|
||||
mrb_irep *irep = ci->proc->body.irep;
|
||||
|
||||
if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
|
||||
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename));
|
||||
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
|
||||
int32_t const line = mrb_get_line(irep, pc - irep->iseq - 1);
|
||||
char const* file = mrb_get_filename(irep, pc - irep->iseq - 1);
|
||||
if(line != -1 && file) {
|
||||
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, file));
|
||||
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(line));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+113
-1
@@ -16,6 +16,8 @@
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/proc.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/debug.h"
|
||||
#include "mruby/array.h"
|
||||
|
||||
#if !defined(_WIN32) && SIZE_MAX < UINT32_MAX
|
||||
# define SIZE_ERROR_MUL(x, y) ((x) > SIZE_MAX / (y))
|
||||
@@ -299,6 +301,97 @@ error_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int read_rite_debug_record(mrb_state* mrb, uint8_t const *start, size_t irepno, uint32_t *len, mrb_value const filenames) {
|
||||
uint8_t const* bin = start;
|
||||
|
||||
mrb_irep* const irep = mrb->irep[irepno];
|
||||
|
||||
if(irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
|
||||
|
||||
irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
|
||||
irep->debug_info->pc_count = irep->ilen;
|
||||
|
||||
size_t const record_size = bin_to_uint32(bin); bin += sizeof(uint32_t);
|
||||
|
||||
irep->debug_info->flen = bin_to_uint16(bin);
|
||||
irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen);
|
||||
bin += sizeof(uint16_t);
|
||||
|
||||
for (uint16_t f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
mrb_irep_debug_info_file* const file = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file));
|
||||
irep->debug_info->files[f_idx] = file;
|
||||
|
||||
file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t);
|
||||
|
||||
// filename
|
||||
file->filename_sym = mrb_symbol(RARRAY_PTR(filenames)[bin_to_uint16(bin)]);
|
||||
size_t len = 0;
|
||||
file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
|
||||
bin += sizeof(uint16_t);
|
||||
|
||||
file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t);
|
||||
file->line_type = bin_to_uint8(bin); bin += sizeof(uint8_t);
|
||||
switch(file->line_type) {
|
||||
case mrb_debug_line_ary:
|
||||
file->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file->line_entry_count);
|
||||
for(size_t l = 0; l < file->line_entry_count; ++l) {
|
||||
file->line_ary[l] = bin_to_uint16(bin); bin += sizeof(uint16_t);
|
||||
}
|
||||
break;
|
||||
|
||||
case mrb_debug_line_flat_map:
|
||||
file->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count);
|
||||
for(size_t l = 0; l < file->line_entry_count; ++l) {
|
||||
file->line_flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t);
|
||||
file->line_flat_map[l].line = bin_to_uint16(bin); bin += sizeof(uint16_t);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return MRB_DUMP_GENERAL_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if((long)record_size != (bin - start)) {
|
||||
return MRB_DUMP_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
*len = bin - start;
|
||||
|
||||
return MRB_DUMP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
read_rite_section_debug(mrb_state* mrb, const uint8_t* start, size_t sirep)
|
||||
{
|
||||
uint8_t const* bin = start;
|
||||
struct rite_section_debug_header const* header = (struct rite_section_debug_header const*)bin;
|
||||
bin += sizeof(struct rite_section_debug_header);
|
||||
|
||||
uint16_t const nirep = bin_to_uint16(header->nirep);
|
||||
|
||||
uint16_t const filenames_len = bin_to_uint16(bin);
|
||||
mrb_value const filenames = mrb_ary_new_capa(mrb, filenames_len);
|
||||
bin += sizeof(uint16_t);
|
||||
for(uint16_t i = 0; i < filenames_len; ++i) {
|
||||
uint16_t const f_len = bin_to_uint16(bin);
|
||||
bin += sizeof(uint16_t);
|
||||
mrb_ary_push(mrb, filenames, mrb_symbol_value(mrb_intern2(mrb, (char const*)bin, f_len)));
|
||||
bin += f_len;
|
||||
}
|
||||
|
||||
for(uint16_t i = sirep; i < (sirep + nirep); ++i) {
|
||||
uint32_t len = 0;
|
||||
int result = read_rite_debug_record(mrb, bin, i, &len, filenames);
|
||||
if (result != MRB_DUMP_OK) { return result; }
|
||||
bin += len;
|
||||
}
|
||||
|
||||
if ((bin - start) != bin_to_uint32(header->section_size)) {
|
||||
return MRB_DUMP_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
return sirep + bin_to_uint16(header->sirep);
|
||||
}
|
||||
|
||||
static int
|
||||
read_rite_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc)
|
||||
@@ -364,6 +457,12 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (memcmp(section_header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
|
||||
result = read_rite_section_debug(mrb, bin, sirep);
|
||||
if (result < MRB_DUMP_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
bin += bin_to_uint32(section_header->section_size);
|
||||
} while (memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0);
|
||||
|
||||
@@ -566,7 +665,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp)
|
||||
/* You don't need use SIZE_ERROR as block_size is enough small. */
|
||||
for (i = 0; i < block_fallback_count; i++,block_size >>= 1){
|
||||
buf = mrb_malloc_simple(mrb, block_size);
|
||||
if (buf) break;
|
||||
if (buf) break;
|
||||
}
|
||||
if (!buf) {
|
||||
return MRB_DUMP_GENERAL_FAILURE;
|
||||
@@ -608,6 +707,19 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (memcmp(section_header.section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
|
||||
uint8_t* const bin = mrb_malloc(mrb, section_size);
|
||||
fseek(fp, fpos, SEEK_SET);
|
||||
if(fread((char*)bin, section_size, 1, fp) != section_size) {
|
||||
mrb_free(mrb, bin);
|
||||
return MRB_DUMP_READ_FAULT;
|
||||
}
|
||||
result = read_rite_section_debug(mrb, bin, sirep);
|
||||
mrb_free(mrb, bin);
|
||||
if (result < MRB_DUMP_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fseek(fp, fpos + section_size, SEEK_SET);
|
||||
} while (memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0);
|
||||
|
||||
@@ -120,6 +120,7 @@ cons_gen(parser_state *p, node *car, node *cdr)
|
||||
c->car = car;
|
||||
c->cdr = cdr;
|
||||
c->lineno = p->lineno;
|
||||
c->filename = p->filename;
|
||||
return c;
|
||||
}
|
||||
#define cons(a,b) cons_gen(p,(a),(b))
|
||||
@@ -5179,6 +5180,13 @@ mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser
|
||||
c->partial_data = data;
|
||||
}
|
||||
|
||||
void
|
||||
mrb_parser_set_filename(struct mrb_parser_state* p, char const* f)
|
||||
{
|
||||
p->filename = mrbc_filename(p->mrb, p->cxt, f);
|
||||
p->lineno = 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_STDIO
|
||||
parser_state*
|
||||
mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "mruby/class.h"
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/variable.h"
|
||||
#include "mruby/debug.h"
|
||||
|
||||
void mrb_init_heap(mrb_state*);
|
||||
void mrb_init_core(mrb_state*);
|
||||
@@ -115,6 +116,8 @@ mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
|
||||
mrb_free(mrb, (void *)irep->filename);
|
||||
mrb_free(mrb, irep->lines);
|
||||
mrb_free(mrb, irep);
|
||||
|
||||
mrb_debug_info_free(mrb, irep->debug_info);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+2
-4
@@ -145,7 +145,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
@@ -177,9 +177,7 @@ partial_hook(struct mrb_parser_state *p)
|
||||
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
|
||||
return -1;
|
||||
}
|
||||
mrbc_filename(p->mrb, c, fn);
|
||||
p->filename = c->filename;
|
||||
p->lineno = 1;
|
||||
mrb_parser_set_filename(p, fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user