@@ -169,196 +169,34 @@ fn void Generator.writeCalls(Generator* gen, string_buffer.Buf* out) {
169169 if (!gen.trace_calls)
170170 return;
171171
172- out.add("static const char *c2_filenames[] = {\n");
172+ out.add("const char *c2_filenames[] = {\n");
173173 u32 n = gen.filenames.length();
174174 for (u32 i = 0; i < n; i++) {
175175 out.print(" \"%s\",\n", gen.filenames.get(i));
176176 }
177177 out.add("};\n\n");
178178
179- out.add(
180- ```c
181- struct c2_func_t {
182- unsigned count;
183- unsigned short filename_idx;
184- unsigned short line;
185- const char *funcname;
186- };
187- static struct c2_func_t c2_func_data[] = {
188- ```);
179+ out.add("c2_func_t c2_func_data[] = {\n");
180+
189181 // TODO: store function definition location
190182 n = gen.funcnames.length();
191183 for (u32 i = 0; i < n; i++) {
192184 out.print(" { 0, 0, 0, \"%s\" },\n", gen.funcnames.get(i));
193185 }
194- out.add(
195- ```c
196- };
186+ out.add("};\n\n");
197187
198- struct c2_trace_t {
199- unsigned count;
200- unsigned char filename_idx;
201- unsigned char column;
202- unsigned short line;
203- unsigned short caller_idx;
204- unsigned short callee_idx;
205- };
206- static struct c2_trace_t c2_trace_data[] = {
207- ```);
188+ out.add("c2_trace_t c2_trace_data[] = {\n");
208189 for (u32 i = 0; i < gen.calls.count; i++) {
209190 out.print(" { 0, %d, %d, %d, %d, %d },\n",
210191 gen.calls.array[i].filename_idx, gen.calls.array[i].column, gen.calls.array[i].line,
211192 gen.calls.array[i].caller_idx, gen.calls.array[i].callee_idx);
212193 }
194+ out.add("};\n\n");
213195
214- out.add(
215- ```c
216- };
217-
218- static const unsigned c2_trace_length = sizeof(c2_trace_data) / sizeof(c2_trace_data[0]);
219- unsigned c2_trace_counts[sizeof(c2_trace_data) / sizeof(c2_trace_data[0])];
220-
221- char *getenv(const char *);
222- int dprintf(int fd, const char *format, ...);
223- int strcmp(const char *s1, const char *s2);
224- typedef unsigned long size_t;
225- void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
226- int sscanf(const char *, const char *, ...);
227-
228- static int c2_match_name(const char *name, const char *pattern) {
229- for (;;) {
230- char c1, c2;
231- while ((c1 = *name++) == (c2 = *pattern++)) {
232- if (!c1) return 1;
233- }
234- if (c2 == '?') {
235- if (c1) continue;
236- return 0;
237- }
238- if (c2 == '*') {
239- c2 = *pattern++;
240- if (!c2 || c2 == ',' || c2 == ';') return 1;
241- for (; c1; c1 = *name++) {
242- if (c1 == c2 && c2_match_name(name, pattern)) return 1;
243- }
244- return 0;
245- }
246- return (!c1 && (c2 == ',' || c2 == ';'));
247- }
248- }
249-
250- static int c2_match_pattern(const char *name, const char *pattern) {
251- if (!pattern || !*pattern) return 1;
252- for (const char *p = pattern; *p;) {
253- if (c2_match_name(name, p)) return 1;
254- char c;
255- while ((c = *p++) != 0 && c != ',' && c != ';') continue;
256- if (c != ',') break;
257- }
258- return 0;
259- }
260-
261- static int c2_cmp_funcs(const void *a, const void *b) {
262- const struct c2_trace_t *aa = a;
263- const struct c2_trace_t *bb = b;
264- struct c2_func_t *fa = &c2_func_data[aa->callee_idx];
265- struct c2_func_t *fb = &c2_func_data[bb->callee_idx];
266- if (fa->count != fb->count) return fa->count < fb->count ? 1 : -1;
267- if (fa != fb) return strcmp(fa->funcname, fb->funcname);
268- return (aa->count < bb->count) - (aa->count > bb->count);
269- }
270-
271- static int c2_cmp_calls(const void *a, const void *b) {
272- const struct c2_trace_t *aa = a;
273- const struct c2_trace_t *bb = b;
274- return (aa->count < bb->count) - (aa->count > bb->count);
275- }
276-
277- void __attribute__((destructor)) c2_trace_calls(void) {
278- const char *p = getenv("C2_TRACE");
279- const char *pattern = 0;
280- const char *filename = 0;
281- const char *caller = 0;
282- if (!p || !*p) return;
283- unsigned min = 1, min2 = 1;
284- int pos = 0, mode = 3, fd = 1, indent = 2;
285- for (; *p; p += pos) {
286- for (pos = 0;;) {
287- sscanf(p, " min%*1[=]%n%u", &pos, &min);
288- if (pos) break;
289- sscanf(p, " min2%*1[=]%n%u", &pos, &min2);
290- if (pos) break;
291- sscanf(p, " indent%*1[=]%n%u", &pos, &indent);
292- if (pos) break;
293- sscanf(p, " mode%*1[=]%n%d", &pos, &mode);
294- if (pos) break;
295- sscanf(p, " fd%*1[=]%n%d", &pos, &fd);
296- if (pos) break;
297- sscanf(p, " name%*1[=]%n", &pos);
298- if (pos) { pattern = p + pos; break; }
299- sscanf(p, " filename%*1[=]%n", &pos);
300- if (pos) { filename = p + pos; break; }
301- sscanf(p, " caller%*1[=]%n", &pos);
302- if (pos) { caller = p + pos; break; }
303- sscanf(p, "%*[^;=]%*1[=]%n", &pos);
304- break;
305- }
306- if (!pos) pattern = p;
307- while (p[pos] && p[pos++] != ';') continue;
308- }
309- if (!mode) return;
310- unsigned *counts = c2_trace_counts;
311- struct c2_trace_t* data = c2_trace_data;
312- unsigned n = c2_trace_length;
313- for (unsigned i = 0; i < n; i++) {
314- struct c2_trace_t *cp = &data[i];
315- if (c2_match_pattern(c2_func_data[cp->callee_idx].funcname, pattern)
316- && c2_match_pattern(c2_filenames[cp->filename_idx], filename)
317- && c2_match_pattern(c2_func_data[cp->caller_idx].funcname, caller)) {
318- cp->count = counts[i];
319- c2_func_data[cp->callee_idx].count += counts[i];
320- }
321- }
322- if (mode == 2) {
323- qsort(data, n, sizeof(*data), c2_cmp_calls);
324- indent = 0;
325- min2 = min;
326- } else {
327- qsort(data, n, sizeof(*data), c2_cmp_funcs);
328- }
329- struct c2_func_t *last = 0;
330- int show = 0;
331- for (unsigned i = 0; i < n; i++) {
332- struct c2_trace_t *cp = &data[i];
333- struct c2_func_t *func = &c2_func_data[cp->callee_idx];
334- unsigned count1 = func->count;
335- unsigned count2 = cp->count;
336- if (count1 < min) continue;
337- if (func != last) {
338- show = mode & 2;
339- if (mode & 1) {
340- dprintf(fd, "%.*s%s: %u call%.*s\n", show, "\n",
341- func->funcname, count1, count1 != 1, "s");
342- }
343- last = func;
344- }
345- if (show && count2 >= min2) {
346- dprintf(fd, "%*s%s:%d:%d: %s: %u call%.*s from %s\n",
347- indent, "",
348- c2_filenames[cp->filename_idx], cp->line, cp->column,
349- func->funcname, count2, count2 != 1, "s",
350- c2_func_data[cp->caller_idx].funcname);
351- }
352- }
353- }
354- ```);
196+ out.add("uint32_t c2_trace_length = sizeof(c2_trace_data) / sizeof(c2_trace_data[0]);\n"
197+ "uint32_t c2_trace_counts[sizeof(c2_trace_data) / sizeof(c2_trace_data[0])];\n\n");
355198}
356199
357200fn void Generator.writeCallExterns(Generator* gen, string_buffer.Buf* out) {
358- out.add(
359- ```c
360- extern unsigned c2_trace_counts[];
361- extern void c2_trace_calls(void);
362- extern int atexit(void (*func)(void));
363- ```);
201+ out.add("extern uint32_t c2_trace_counts[];\n");
364202}
0 commit comments