source: EcnlProtoTool/trunk/mruby-1.2.0/src/debug.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 6.0 KB
Line 
1#include <string.h>
2#include "mruby.h"
3#include "mruby/irep.h"
4#include "mruby/debug.h"
5
6static mrb_irep_debug_info_file *
7get_file(mrb_irep_debug_info *info, uint32_t pc)
8{
9 mrb_irep_debug_info_file **ret;
10 int32_t count;
11
12 if (pc >= info->pc_count) { return NULL; }
13 /* get upper bound */
14 ret = info->files;
15 count = info->flen;
16 while (count > 0) {
17 int32_t step = count / 2;
18 mrb_irep_debug_info_file **it = ret + step;
19 if (!(pc < (*it)->start_pos)) {
20 ret = it + 1;
21 count -= step + 1;
22 } else { count = step; }
23 }
24
25 --ret;
26
27 /* check returning file exists inside debug info */
28 mrb_assert(info->files <= ret && ret < (info->files + info->flen));
29 /* check pc is within the range of returning file */
30 mrb_assert((*ret)->start_pos <= pc &&
31 pc < (((ret + 1 - info->files) < info->flen)
32 ? (*(ret+1))->start_pos : info->pc_count));
33
34 return *ret;
35}
36
37static mrb_debug_line_type
38select_line_type(const uint16_t *lines, size_t lines_len)
39{
40 size_t line_count = 0;
41 int prev_line = -1;
42 size_t i;
43 for (i = 0; i < lines_len; ++i) {
44 if (lines[i] != prev_line) {
45 ++line_count;
46 }
47 }
48 return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count)
49 ? mrb_debug_line_ary : mrb_debug_line_flat_map;
50}
51
52MRB_API char const*
53mrb_debug_get_filename(mrb_irep *irep, uint32_t pc)
54{
55 if (irep && pc < irep->ilen) {
56 mrb_irep_debug_info_file* f = NULL;
57 if (!irep->debug_info) { return irep->filename; }
58 else if ((f = get_file(irep->debug_info, pc))) {
59 return f->filename;
60 }
61 }
62 return NULL;
63}
64
65MRB_API int32_t
66mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
67{
68 if (irep && pc < irep->ilen) {
69 mrb_irep_debug_info_file* f = NULL;
70 if (!irep->debug_info) {
71 return irep->lines? irep->lines[pc] : -1;
72 }
73 else if ((f = get_file(irep->debug_info, pc))) {
74 switch (f->line_type) {
75 case mrb_debug_line_ary:
76 mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count));
77 return f->lines.ary[pc - f->start_pos];
78
79 case mrb_debug_line_flat_map: {
80 /* get upper bound */
81 mrb_irep_debug_info_line *ret = f->lines.flat_map;
82 uint32_t count = f->line_entry_count;
83 while (count > 0) {
84 int32_t step = count / 2;
85 mrb_irep_debug_info_line *it = ret + step;
86 if (!(pc < it->start_pos)) {
87 ret = it + 1;
88 count -= step + 1;
89 } else { count = step; }
90 }
91
92 --ret;
93
94 /* check line entry pointer range */
95 mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count));
96 /* check pc range */
97 mrb_assert(ret->start_pos <= pc &&
98 pc < (((uint32_t)(ret + 1 - f->lines.flat_map) < f->line_entry_count)
99 ? (ret+1)->start_pos : irep->debug_info->pc_count));
100
101 return ret->line;
102 }
103 }
104 }
105 }
106 return -1;
107}
108
109MRB_API mrb_irep_debug_info *
110mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep)
111{
112 static const mrb_irep_debug_info initial = { 0, 0, NULL };
113 mrb_irep_debug_info *ret;
114
115 mrb_assert(!irep->debug_info);
116 ret = (mrb_irep_debug_info *)mrb_malloc(mrb, sizeof(*ret));
117 *ret = initial;
118 irep->debug_info = ret;
119 return ret;
120}
121
122MRB_API mrb_irep_debug_info_file *
123mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
124 uint32_t start_pos, uint32_t end_pos)
125{
126 mrb_irep_debug_info *info;
127 mrb_irep_debug_info_file *ret;
128 uint32_t file_pc_count;
129 size_t fn_len;
130 mrb_int len;
131 uint32_t i;
132
133 if (!irep->debug_info) { return NULL; }
134
135 mrb_assert(irep->filename);
136 mrb_assert(irep->lines);
137
138 info = irep->debug_info;
139
140 if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
141 return NULL;
142 }
143
144 ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
145 info->files =
146 (mrb_irep_debug_info_file**)(
147 info->files
148 ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
149 : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)));
150 info->files[info->flen++] = ret;
151
152 file_pc_count = end_pos - start_pos;
153
154 ret->start_pos = start_pos;
155 info->pc_count = end_pos;
156
157 fn_len = strlen(irep->filename);
158 ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len);
159 len = 0;
160 ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
161
162 ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos);
163 ret->lines.ptr = NULL;
164
165 switch (ret->line_type) {
166 case mrb_debug_line_ary:
167 ret->line_entry_count = file_pc_count;
168 ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
169 for (i = 0; i < file_pc_count; ++i) {
170 ret->lines.ary[i] = irep->lines[start_pos + i];
171 }
172 break;
173
174 case mrb_debug_line_flat_map: {
175 uint16_t prev_line = 0;
176 mrb_irep_debug_info_line m;
177 ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
178 ret->line_entry_count = 0;
179 for (i = 0; i < file_pc_count; ++i) {
180 if (irep->lines[start_pos + i] == prev_line) { continue; }
181
182 ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
183 mrb, ret->lines.flat_map,
184 sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
185 m.start_pos = start_pos + i;
186 m.line = irep->lines[start_pos + i];
187 ret->lines.flat_map[ret->line_entry_count] = m;
188
189 /* update */
190 ++ret->line_entry_count;
191 prev_line = irep->lines[start_pos + i];
192 }
193 } break;
194
195 default: mrb_assert(0); break;
196 }
197
198 return ret;
199}
200
201MRB_API void
202mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
203{
204 uint32_t i;
205
206 if (!d) { return; }
207
208 for (i = 0; i < d->flen; ++i) {
209 mrb_assert(d->files[i]);
210 mrb_free(mrb, d->files[i]->lines.ptr);
211 mrb_free(mrb, d->files[i]);
212 }
213 mrb_free(mrb, d->files);
214 mrb_free(mrb, d);
215}
Note: See TracBrowser for help on using the repository browser.