Skip to content

Commit e3cfb41

Browse files
committed
Compiler: move c2_trace functions to libs/trace/c2_trace.c2
* add **generator/c2_trace.c2** source module. This file is incorporated in the compiler using the @embed attribute * add **libs/c2/c2_trace_tables.c2i** to define the types and tables generated by the compiler when call tracing is enabled. * generate call tracing tables in **c2_trace_tables.c** for fast builds
1 parent 32a49c1 commit e3cfb41

File tree

10 files changed

+204
-182
lines changed

10 files changed

+204
-182
lines changed

common/build_target.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public type File struct {
100100
}
101101

102102
public type Target struct @(opaque) {
103-
u32 name_idx; // into aux pool
103+
u32 name_idx; // index into auxPool
104104
SrcLoc loc;
105105
warning_flags.Flags warnings;
106106
Kind kind;

compiler/compiler.c2

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ fn component.Kind target2compKind(build_target.Kind k) {
199199
return component.Kind.Executable;
200200
}
201201

202+
const char[] C2_trace @(embed="generator/c2_trace.c2");
203+
202204
fn void Compiler.build(Compiler* c,
203205
string_pool.Pool* auxPool,
204206
source_mgr.SourceMgr* sm,
@@ -296,6 +298,8 @@ fn void Compiler.build(Compiler* c,
296298
if (opts.msan) c.addFeature("__MSAN__", "1");
297299
if (opts.ubsan) c.addFeature("__UBSAN__", "1");
298300

301+
target.addLib(c.auxPool.add("c2", 2, true), false);
302+
299303
c.parser = c2_parser.create(sm,
300304
diags,
301305
c.astPool,
@@ -362,14 +366,21 @@ fn void Compiler.build(Compiler* c,
362366
const build_target.File* f = target.getFile(j);
363367
i32 file_id = sm.open(f.name, f.loc, true);
364368
if (file_id == -1) return; // note: error already printed
365-
366369
console.debug("parsing %s", sm.getFileName(file_id));
367370

368371
// parse error indicator updated in c.parser state
369372
c.parser.parse(file_id, false, false);
370-
371373
sm.close(file_id);
372374
}
375+
if (c.opts.trace_calls) {
376+
i32 file_id = sm.addResource(c.auxPool.addStr("generator/c2_trace.c2", true),
377+
C2_trace, elemsof(C2_trace) - 1);
378+
if (file_id == -1) return; // note: error already printed
379+
console.debug("parsing %s", sm.getFileName(file_id));
380+
c.parser.parse(file_id, false, false);
381+
sm.close(file_id);
382+
}
383+
373384
u64 t1_end = utils.now();
374385
console.log_time("parsing", t1_end - t1_start);
375386
if (!c.diags.isOk()) return;

compiler/main.c2

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,6 @@ fn bool Context.build_target(Context* c,
594594
}
595595
}
596596

597-
target.addLib(c.auxPool.add("c2", 2, true), false);
598-
599597
compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.pluginHandler);
600598

601599
// TODO unload target-specific plugins?

generator/c/c_generator.c2

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type Generator struct {
7979
bool msan;
8080
bool ubsan;
8181
bool trace_calls;
82+
bool no_trace; //to disable tracing on c2_trace module
8283

8384
// set during generation
8485
bool cur_external; // whether current component is external
@@ -1058,6 +1059,9 @@ fn void Generator.on_module(void* arg, Module* m) {
10581059
gen.mod_name = m.getName();
10591060
gen.mod = m;
10601061

1062+
// Temporary disable call tracing when compiling the c2_trace module
1063+
gen.no_trace = !string.strcmp(gen.mod_name, "c2_trace");
1064+
10611065
if (gen.fast_build) {
10621066
out.clear();
10631067
gen.header.clear();
@@ -1268,9 +1272,17 @@ public fn void generate(string_pool.Pool* astPool,
12681272

12691273
mainComp.visitModules(Generator.on_module, &gen);
12701274

1271-
if (fast_build) gen.out.clear();
1272-
if (gen.trace_calls) gen.writeCalls(gen.out);
1273-
if (!fast_build || gen.trace_calls) {
1275+
if (fast_build) {
1276+
if (gen.trace_calls) {
1277+
gen.out.clear();
1278+
gen.out.add("#include \"c2_trace_tables.h\"\n\n");
1279+
gen.writeCalls(gen.out);
1280+
gen.write(dir, "c2_trace_tables.c", gen.out);
1281+
}
1282+
} else {
1283+
if (gen.trace_calls) {
1284+
gen.writeCalls(gen.out);
1285+
}
12741286
gen.write(dir, "build.c", gen.out);
12751287
}
12761288

generator/c/c_generator_call.c2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn void Generator.emitCall(Generator* gen, string_buffer.Buf* out, Expr* e) {
5454
assert(func.getKind() == ExprKind.Member);
5555
MemberExpr* m = cast<MemberExpr*>(func);
5656
dest = m.getFullDecl();
57-
if (gen.trace_calls) {
57+
if (gen.trace_calls && !gen.no_trace) {
5858
out.print("(c2_trace_counts[%d]++, ",
5959
gen.addCall(dest.getFullName(), call.getStartLoc()));
6060
gen.emitCNameMod(out, dest, dest.getModule());
@@ -78,7 +78,7 @@ fn void Generator.emitCall(Generator* gen, string_buffer.Buf* out, Expr* e) {
7878
gen.emitMemberExprBase(out, func);
7979
}
8080
} else {
81-
bool no_trace = false;
81+
bool no_trace = gen.no_trace;
8282
// can be Member or Identifier
8383
if (func.getKind() == ExprKind.Identifier) {
8484
IdentifierExpr* i = cast<IdentifierExpr*>(func);

generator/c/c_generator_special.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ fn void Generator.createMakefile(Generator* gen,
105105
if (!m.isExternal() && m.isUsed()) out.print(" %s.o", m.getName());
106106
}
107107
if (gen.trace_calls) {
108-
out.add(" build.o");
108+
out.add(" c2_trace_tables.o");
109109
}
110110
out.newline();
111111
} else {

generator/c/c_generator_trace.c2

Lines changed: 9 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -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

357200
fn 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

Comments
 (0)