mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
debug.c
00001 #include <string.h> 00002 #include "mruby.h" 00003 #include "mruby/irep.h" 00004 #include "mruby/debug.h" 00005 00006 static mrb_irep_debug_info_file * 00007 get_file(mrb_irep_debug_info *info, uint32_t pc) 00008 { 00009 mrb_irep_debug_info_file **ret; 00010 int32_t count; 00011 00012 if (pc >= info->pc_count) { return NULL; } 00013 /* get upper bound */ 00014 ret = info->files; 00015 count = info->flen; 00016 while (count > 0) { 00017 int32_t step = count / 2; 00018 mrb_irep_debug_info_file **it = ret + step; 00019 if (!(pc < (*it)->start_pos)) { 00020 ret = it + 1; 00021 count -= step + 1; 00022 } else { count = step; } 00023 } 00024 00025 --ret; 00026 00027 /* check returning file exists inside debug info */ 00028 mrb_assert(info->files <= ret && ret < (info->files + info->flen)); 00029 /* check pc is within the range of returning file */ 00030 mrb_assert((*ret)->start_pos <= pc && 00031 pc < (((ret + 1 - info->files) < info->flen) 00032 ? (*(ret+1))->start_pos : info->pc_count)); 00033 00034 return *ret; 00035 } 00036 00037 static mrb_debug_line_type 00038 select_line_type(const uint16_t *lines, size_t lines_len) 00039 { 00040 size_t line_count = 0; 00041 int prev_line = -1; 00042 size_t i; 00043 for (i = 0; i < lines_len; ++i) { 00044 if (lines[i] != prev_line) { 00045 ++line_count; 00046 } 00047 } 00048 return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count) 00049 ? mrb_debug_line_ary : mrb_debug_line_flat_map; 00050 } 00051 00052 MRB_API char const* 00053 mrb_debug_get_filename(mrb_irep *irep, uint32_t pc) 00054 { 00055 if (irep && pc < irep->ilen) { 00056 mrb_irep_debug_info_file* f = NULL; 00057 if (!irep->debug_info) { return irep->filename; } 00058 else if ((f = get_file(irep->debug_info, pc))) { 00059 return f->filename; 00060 } 00061 } 00062 return NULL; 00063 } 00064 00065 MRB_API int32_t 00066 mrb_debug_get_line(mrb_irep *irep, uint32_t pc) 00067 { 00068 if (irep && pc < irep->ilen) { 00069 mrb_irep_debug_info_file* f = NULL; 00070 if (!irep->debug_info) { 00071 return irep->lines? irep->lines[pc] : -1; 00072 } 00073 else if ((f = get_file(irep->debug_info, pc))) { 00074 switch (f->line_type) { 00075 case mrb_debug_line_ary: 00076 mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count)); 00077 return f->lines.ary[pc - f->start_pos]; 00078 00079 case mrb_debug_line_flat_map: { 00080 /* get upper bound */ 00081 mrb_irep_debug_info_line *ret = f->lines.flat_map; 00082 uint32_t count = f->line_entry_count; 00083 while (count > 0) { 00084 int32_t step = count / 2; 00085 mrb_irep_debug_info_line *it = ret + step; 00086 if (!(pc < it->start_pos)) { 00087 ret = it + 1; 00088 count -= step + 1; 00089 } else { count = step; } 00090 } 00091 00092 --ret; 00093 00094 /* check line entry pointer range */ 00095 mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count)); 00096 /* check pc range */ 00097 mrb_assert(ret->start_pos <= pc && 00098 pc < (((uint32_t)(ret + 1 - f->lines.flat_map) < f->line_entry_count) 00099 ? (ret+1)->start_pos : irep->debug_info->pc_count)); 00100 00101 return ret->line; 00102 } 00103 } 00104 } 00105 } 00106 return -1; 00107 } 00108 00109 MRB_API mrb_irep_debug_info * 00110 mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep) 00111 { 00112 static const mrb_irep_debug_info initial = { 0, 0, NULL }; 00113 mrb_irep_debug_info *ret; 00114 00115 mrb_assert(!irep->debug_info); 00116 ret = (mrb_irep_debug_info *)mrb_malloc(mrb, sizeof(*ret)); 00117 *ret = initial; 00118 irep->debug_info = ret; 00119 return ret; 00120 } 00121 00122 MRB_API mrb_irep_debug_info_file * 00123 mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, 00124 uint32_t start_pos, uint32_t end_pos) 00125 { 00126 mrb_irep_debug_info *info; 00127 mrb_irep_debug_info_file *ret; 00128 uint32_t file_pc_count; 00129 size_t fn_len; 00130 mrb_int len; 00131 uint32_t i; 00132 00133 if (!irep->debug_info) { return NULL; } 00134 00135 mrb_assert(irep->filename); 00136 mrb_assert(irep->lines); 00137 00138 info = irep->debug_info; 00139 00140 if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) { 00141 return NULL; 00142 } 00143 00144 ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret)); 00145 info->files = 00146 (mrb_irep_debug_info_file**)( 00147 info->files 00148 ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1)) 00149 : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*))); 00150 info->files[info->flen++] = ret; 00151 00152 file_pc_count = end_pos - start_pos; 00153 00154 ret->start_pos = start_pos; 00155 info->pc_count = end_pos; 00156 00157 fn_len = strlen(irep->filename); 00158 ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len); 00159 len = 0; 00160 ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); 00161 00162 ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos); 00163 ret->lines.ptr = NULL; 00164 00165 switch (ret->line_type) { 00166 case mrb_debug_line_ary: 00167 ret->line_entry_count = file_pc_count; 00168 ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); 00169 for (i = 0; i < file_pc_count; ++i) { 00170 ret->lines.ary[i] = irep->lines[start_pos + i]; 00171 } 00172 break; 00173 00174 case mrb_debug_line_flat_map: { 00175 uint16_t prev_line = 0; 00176 mrb_irep_debug_info_line m; 00177 ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); 00178 ret->line_entry_count = 0; 00179 for (i = 0; i < file_pc_count; ++i) { 00180 if (irep->lines[start_pos + i] == prev_line) { continue; } 00181 00182 ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc( 00183 mrb, ret->lines.flat_map, 00184 sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); 00185 m.start_pos = start_pos + i; 00186 m.line = irep->lines[start_pos + i]; 00187 ret->lines.flat_map[ret->line_entry_count] = m; 00188 00189 /* update */ 00190 ++ret->line_entry_count; 00191 prev_line = irep->lines[start_pos + i]; 00192 } 00193 } break; 00194 00195 default: mrb_assert(0); break; 00196 } 00197 00198 return ret; 00199 } 00200 00201 MRB_API void 00202 mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d) 00203 { 00204 uint32_t i; 00205 00206 if (!d) { return; } 00207 00208 for (i = 0; i < d->flen; ++i) { 00209 mrb_assert(d->files[i]); 00210 mrb_free(mrb, d->files[i]->lines.ptr); 00211 mrb_free(mrb, d->files[i]); 00212 } 00213 mrb_free(mrb, d->files); 00214 mrb_free(mrb, d); 00215 } 00216
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2