authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-03 18:37:30-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-10-03 18:37:30-04:00
logeca2aa66feae60e1e11e482b31443692aa3002ef
treef1a9609e9db26c688ced5eae2ae87d5f0a3717c0
parent7640bec8e0e735eaba49087840b7f6e6b2dd74ab
parent39d47b2c51d43d98f414ed5d5622c9e582ec9aa6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3372 from ziglang/dump-analysis

add -fdump-analysis to dump type information to json

11 files changed, 845 insertions(+), 145 deletions(-)

CMakeLists.txt+1-1
...@@ -443,6 +443,7 @@ set(ZIG_SOURCES...@@ -443,6 +443,7 @@ set(ZIG_SOURCES
443 "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"443 "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
444 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"444 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
445 "${CMAKE_SOURCE_DIR}/src/compiler.cpp"445 "${CMAKE_SOURCE_DIR}/src/compiler.cpp"
446 "${CMAKE_SOURCE_DIR}/src/dump_analysis.cpp"
446 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"447 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
447 "${CMAKE_SOURCE_DIR}/src/error.cpp"448 "${CMAKE_SOURCE_DIR}/src/error.cpp"
448 "${CMAKE_SOURCE_DIR}/src/glibc.cpp"449 "${CMAKE_SOURCE_DIR}/src/glibc.cpp"
...@@ -453,7 +454,6 @@ set(ZIG_SOURCES...@@ -453,7 +454,6 @@ set(ZIG_SOURCES
453 "${CMAKE_SOURCE_DIR}/src/os.cpp"454 "${CMAKE_SOURCE_DIR}/src/os.cpp"
454 "${CMAKE_SOURCE_DIR}/src/parser.cpp"455 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
455 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"456 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"
456 "${CMAKE_SOURCE_DIR}/src/stack_report.cpp"
457 "${CMAKE_SOURCE_DIR}/src/target.cpp"457 "${CMAKE_SOURCE_DIR}/src/target.cpp"
458 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"458 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
459 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"459 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
src/all_types.hpp+7
...@@ -1300,6 +1300,12 @@ struct ZigTypeEnum {...@@ -1300,6 +1300,12 @@ struct ZigTypeEnum {
1300uint32_t type_ptr_hash(const ZigType *ptr);1300uint32_t type_ptr_hash(const ZigType *ptr);
1301bool type_ptr_eql(const ZigType *a, const ZigType *b);1301bool type_ptr_eql(const ZigType *a, const ZigType *b);
13021302
1303uint32_t pkg_ptr_hash(const ZigPackage *ptr);
1304bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b);
1305
1306uint32_t tld_ptr_hash(const Tld *ptr);
1307bool tld_ptr_eql(const Tld *a, const Tld *b);
1308
1303struct ZigTypeUnion {1309struct ZigTypeUnion {
1304 AstNode *decl_node;1310 AstNode *decl_node;
1305 TypeUnionField *fields;1311 TypeUnionField *fields;
...@@ -2056,6 +2062,7 @@ struct CodeGen {...@@ -2056,6 +2062,7 @@ struct CodeGen {
2056 bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic2062 bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
2057 bool have_stack_probing;2063 bool have_stack_probing;
2058 bool function_sections;2064 bool function_sections;
2065 bool enable_dump_analysis;
20592066
2060 Buf *mmacosx_version_min;2067 Buf *mmacosx_version_min;
2061 Buf *mios_version_min;2068 Buf *mios_version_min;
src/analyze.cpp+16
...@@ -7303,6 +7303,22 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {...@@ -7303,6 +7303,22 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {
7303 return a == b;7303 return a == b;
7304}7304}
73057305
7306uint32_t pkg_ptr_hash(const ZigPackage *ptr) {
7307 return hash_ptr((void*)ptr);
7308}
7309
7310bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b) {
7311 return a == b;
7312}
7313
7314uint32_t tld_ptr_hash(const Tld *ptr) {
7315 return hash_ptr((void*)ptr);
7316}
7317
7318bool tld_ptr_eql(const Tld *a, const Tld *b) {
7319 return a == b;
7320}
7321
7306ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {7322ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
7307 Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));7323 Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
7308 resolve_top_level_decl(codegen, tld, nullptr, false);7324 resolve_top_level_decl(codegen, tld, nullptr, false);
src/codegen.cpp+23-6
...@@ -20,6 +20,7 @@...@@ -20,6 +20,7 @@
20#include "util.hpp"20#include "util.hpp"
21#include "zig_llvm.h"21#include "zig_llvm.h"
22#include "userland.h"22#include "userland.h"
23#include "dump_analysis.hpp"
2324
24#include <stdio.h>25#include <stdio.h>
25#include <errno.h>26#include <errno.h>
...@@ -1724,7 +1725,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -1724,7 +1725,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
1724}1725}
17251726
1726ATTRIBUTE_NORETURN1727ATTRIBUTE_NORETURN
1727static void report_errors_and_exit(CodeGen *g) {1728void codegen_report_errors_and_exit(CodeGen *g) {
1728 assert(g->errors.length != 0);1729 assert(g->errors.length != 0);
1729 for (size_t i = 0; i < g->errors.length; i += 1) {1730 for (size_t i = 0; i < g->errors.length; i += 1) {
1730 ErrorMsg *err = g->errors.at(i);1731 ErrorMsg *err = g->errors.at(i);
...@@ -1735,7 +1736,7 @@ static void report_errors_and_exit(CodeGen *g) {...@@ -1735,7 +1736,7 @@ static void report_errors_and_exit(CodeGen *g) {
17351736
1736static void report_errors_and_maybe_exit(CodeGen *g) {1737static void report_errors_and_maybe_exit(CodeGen *g) {
1737 if (g->errors.length != 0) {1738 if (g->errors.length != 0) {
1738 report_errors_and_exit(g);1739 codegen_report_errors_and_exit(g);
1739 }1740 }
1740}1741}
17411742
...@@ -1745,7 +1746,7 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {...@@ -1745,7 +1746,7 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
1745 buf_sprintf("TODO: support C ABI for more targets. https://github.com/ziglang/zig/issues/1481"));1746 buf_sprintf("TODO: support C ABI for more targets. https://github.com/ziglang/zig/issues/1481"));
1746 add_error_note(g, msg, source_node,1747 add_error_note(g, msg, source_node,
1747 buf_sprintf("pointers, integers, floats, bools, and enums work on all targets"));1748 buf_sprintf("pointers, integers, floats, bools, and enums work on all targets"));
1748 report_errors_and_exit(g);1749 codegen_report_errors_and_exit(g);
1749}1750}
17501751
1751static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {1752static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
...@@ -3456,7 +3457,7 @@ static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val) {...@@ -3456,7 +3457,7 @@ static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val) {
3456 Error err;3457 Error err;
3457 if (const_val->special == ConstValSpecialLazy &&3458 if (const_val->special == ConstValSpecialLazy &&
3458 (err = ir_resolve_lazy(g, nullptr, const_val)))3459 (err = ir_resolve_lazy(g, nullptr, const_val)))
3459 report_errors_and_exit(g);3460 codegen_report_errors_and_exit(g);
34603461
3461 switch (const_val->special) {3462 switch (const_val->special) {
3462 case ConstValSpecialLazy:3463 case ConstValSpecialLazy:
...@@ -4253,7 +4254,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4253,7 +4254,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4253 ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?4254 ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?
4254 struct_ptr_type->data.pointer.child_type : struct_ptr_type;4255 struct_ptr_type->data.pointer.child_type : struct_ptr_type;
4255 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))4256 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4256 report_errors_and_exit(g);4257 codegen_report_errors_and_exit(g);
42574258
4258 assert(field->gen_index != SIZE_MAX);4259 assert(field->gen_index != SIZE_MAX);
4259 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");4260 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
...@@ -6625,7 +6626,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -6625,7 +6626,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
6625check: switch (const_val->special) {6626check: switch (const_val->special) {
6626 case ConstValSpecialLazy:6627 case ConstValSpecialLazy:
6627 if ((err = ir_resolve_lazy(g, nullptr, const_val))) {6628 if ((err = ir_resolve_lazy(g, nullptr, const_val))) {
6628 report_errors_and_exit(g);6629 codegen_report_errors_and_exit(g);
6629 }6630 }
6630 goto check;6631 goto check;
6631 case ConstValSpecialRuntime:6632 case ConstValSpecialRuntime:
...@@ -10157,6 +10158,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10157,6 +10158,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10157 cache_bool(ch, g->have_stack_probing);10158 cache_bool(ch, g->have_stack_probing);
10158 cache_bool(ch, g->is_dummy_so);10159 cache_bool(ch, g->is_dummy_so);
10159 cache_bool(ch, g->function_sections);10160 cache_bool(ch, g->function_sections);
10161 cache_bool(ch, g->enable_dump_analysis);
10160 cache_buf_opt(ch, g->mmacosx_version_min);10162 cache_buf_opt(ch, g->mmacosx_version_min);
10161 cache_buf_opt(ch, g->mios_version_min);10163 cache_buf_opt(ch, g->mios_version_min);
10162 cache_usize(ch, g->version_major);10164 cache_usize(ch, g->version_major);
...@@ -10338,6 +10340,21 @@ void codegen_build_and_link(CodeGen *g) {...@@ -10338,6 +10340,21 @@ void codegen_build_and_link(CodeGen *g) {
10338 gen_h_file(g);10340 gen_h_file(g);
10339 }10341 }
10340 }10342 }
10343 if (g->enable_dump_analysis) {
10344 const char *analysis_json_filename = buf_ptr(buf_sprintf("%s" OS_SEP "%s-analysis.json",
10345 buf_ptr(g->output_dir), buf_ptr(g->root_out_name)));
10346 FILE *f = fopen(analysis_json_filename, "wb");
10347 if (f == nullptr) {
10348 fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno));
10349 exit(1);
10350 }
10351 zig_print_analysis_dump(g, f);
10352 if (fclose(f) != 0) {
10353 fprintf(stderr, "Unable to write '%s': %s\n", analysis_json_filename, strerror(errno));
10354 exit(1);
10355 }
10356
10357 }
1034110358
10342 // If we're outputting assembly or llvm IR we skip linking.10359 // If we're outputting assembly or llvm IR we skip linking.
10343 // If we're making a library or executable we must link.10360 // If we're making a library or executable we must link.
src/codegen.hpp+2
...@@ -64,4 +64,6 @@ void codegen_release_caches(CodeGen *codegen);...@@ -64,4 +64,6 @@ void codegen_release_caches(CodeGen *codegen);
64bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type);64bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type);
65bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async);65bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async);
6666
67void codegen_report_errors_and_exit(CodeGen *g);
68
67#endif69#endif
src/dump_analysis.cpp created+771
...@@ -0,0 +1,771 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "dump_analysis.hpp"
9#include "compiler.hpp"
10#include "analyze.hpp"
11#include "config.h"
12#include "ir.hpp"
13#include "codegen.hpp"
14
15enum JsonWriterState {
16 JsonWriterStateInvalid,
17 JsonWriterStateValue,
18 JsonWriterStateArrayStart,
19 JsonWriterStateArray,
20 JsonWriterStateObjectStart,
21 JsonWriterStateObject,
22};
23
24#define JSON_MAX_DEPTH 10
25
26struct JsonWriter {
27 size_t state_index;
28 FILE *f;
29 const char *one_indent;
30 const char *nl;
31 JsonWriterState state[JSON_MAX_DEPTH];
32};
33
34static void jw_init(JsonWriter *jw, FILE *f, const char *one_indent, const char *nl) {
35 jw->state_index = 1;
36 jw->f = f;
37 jw->one_indent = one_indent;
38 jw->nl = nl;
39 jw->state[0] = JsonWriterStateInvalid;
40 jw->state[1] = JsonWriterStateValue;
41}
42
43static void jw_nl_indent(JsonWriter *jw) {
44 assert(jw->state_index >= 1);
45 fprintf(jw->f, "%s", jw->nl);
46 for (size_t i = 0; i < jw->state_index - 1; i += 1) {
47 fprintf(jw->f, jw->one_indent);
48 }
49}
50
51static void jw_push_state(JsonWriter *jw, JsonWriterState state) {
52 jw->state_index += 1;
53 assert(jw->state_index < JSON_MAX_DEPTH);
54 jw->state[jw->state_index] = state;
55}
56
57static void jw_pop_state(JsonWriter *jw) {
58 assert(jw->state_index != 0);
59 jw->state_index -= 1;
60}
61
62static void jw_begin_array(JsonWriter *jw) {
63 assert(jw->state[jw->state_index] == JsonWriterStateValue);
64 fprintf(jw->f, "[");
65 jw->state[jw->state_index] = JsonWriterStateArrayStart;
66}
67
68static void jw_begin_object(JsonWriter *jw) {
69 assert(jw->state[jw->state_index] == JsonWriterStateValue);
70 fprintf(jw->f, "{");
71 jw->state[jw->state_index] = JsonWriterStateObjectStart;
72}
73
74static void jw_array_elem(JsonWriter *jw) {
75 switch (jw->state[jw->state_index]) {
76 case JsonWriterStateInvalid:
77 case JsonWriterStateValue:
78 case JsonWriterStateObjectStart:
79 case JsonWriterStateObject:
80 zig_unreachable();
81 case JsonWriterStateArray:
82 fprintf(jw->f, ",");
83 // fallthrough
84 case JsonWriterStateArrayStart:
85 jw->state[jw->state_index] = JsonWriterStateArray;
86 jw_push_state(jw, JsonWriterStateValue);
87 jw_nl_indent(jw);
88 return;
89 }
90 zig_unreachable();
91}
92
93static void jw_write_escaped_string(JsonWriter *jw, const char *s) {
94 fprintf(jw->f, "\"");
95 for (;; s += 1) {
96 switch (*s) {
97 case 0:
98 fprintf(jw->f, "\"");
99 return;
100 case '"':
101 fprintf(jw->f, "\\\"");
102 continue;
103 case '\t':
104 fprintf(jw->f, "\\t");
105 continue;
106 case '\r':
107 fprintf(jw->f, "\\r");
108 continue;
109 case '\n':
110 fprintf(jw->f, "\\n");
111 continue;
112 case '\b':
113 fprintf(jw->f, "\\b");
114 continue;
115 case '\f':
116 fprintf(jw->f, "\\f");
117 continue;
118 case '\\':
119 fprintf(jw->f, "\\\\");
120 continue;
121 default:
122 fprintf(jw->f, "%c", *s);
123 continue;
124 }
125 }
126}
127
128static void jw_object_field(JsonWriter *jw, const char *name) {
129 switch (jw->state[jw->state_index]) {
130 case JsonWriterStateInvalid:
131 case JsonWriterStateValue:
132 case JsonWriterStateArray:
133 case JsonWriterStateArrayStart:
134 zig_unreachable();
135 case JsonWriterStateObject:
136 fprintf(jw->f, ",");
137 // fallthrough
138 case JsonWriterStateObjectStart:
139 jw->state[jw->state_index] = JsonWriterStateObject;
140 jw_push_state(jw, JsonWriterStateValue);
141 jw_nl_indent(jw);
142 jw_write_escaped_string(jw, name);
143 fprintf(jw->f, ": ");
144 return;
145 }
146 zig_unreachable();
147}
148
149static void jw_end_array(JsonWriter *jw) {
150 switch (jw->state[jw->state_index]) {
151 case JsonWriterStateInvalid:
152 case JsonWriterStateValue:
153 case JsonWriterStateObjectStart:
154 case JsonWriterStateObject:
155 zig_unreachable();
156 case JsonWriterStateArrayStart:
157 fprintf(jw->f, "]");
158 jw_pop_state(jw);
159 return;
160 case JsonWriterStateArray:
161 jw_nl_indent(jw);
162 jw_pop_state(jw);
163 fprintf(jw->f, "]");
164 return;
165 }
166 zig_unreachable();
167}
168
169
170static void jw_end_object(JsonWriter *jw) {
171 switch (jw->state[jw->state_index]) {
172 case JsonWriterStateInvalid:
173 zig_unreachable();
174 case JsonWriterStateValue:
175 zig_unreachable();
176 case JsonWriterStateArray:
177 zig_unreachable();
178 case JsonWriterStateArrayStart:
179 zig_unreachable();
180 case JsonWriterStateObjectStart:
181 fprintf(jw->f, "}");
182 jw_pop_state(jw);
183 return;
184 case JsonWriterStateObject:
185 jw_nl_indent(jw);
186 jw_pop_state(jw);
187 fprintf(jw->f, "}");
188 return;
189 }
190 zig_unreachable();
191}
192
193static void jw_null(JsonWriter *jw) {
194 assert(jw->state[jw->state_index] == JsonWriterStateValue);
195 fprintf(jw->f, "null");
196 jw_pop_state(jw);
197}
198
199static void jw_bool(JsonWriter *jw, bool x) {
200 assert(jw->state[jw->state_index] == JsonWriterStateValue);
201 if (x) {
202 fprintf(jw->f, "true");
203 } else {
204 fprintf(jw->f, "false");
205 }
206 jw_pop_state(jw);
207}
208
209static void jw_int(JsonWriter *jw, int64_t x) {
210 assert(jw->state[jw->state_index] == JsonWriterStateValue);
211 if (x > 4503599627370496 || x < -4503599627370496) {
212 fprintf(jw->f, "\"%" ZIG_PRI_i64 "\"", x);
213 } else {
214 fprintf(jw->f, "%" ZIG_PRI_i64, x);
215 }
216 jw_pop_state(jw);
217}
218
219static void jw_string(JsonWriter *jw, const char *s) {
220 assert(jw->state[jw->state_index] == JsonWriterStateValue);
221 jw_write_escaped_string(jw, s);
222 jw_pop_state(jw);
223}
224
225
226static void tree_print(FILE *f, ZigType *ty, size_t indent);
227
228static void pretty_print_bytes(FILE *f, double n) {
229 if (n > 1024.0 * 1024.0 * 1024.0) {
230 fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0);
231 return;
232 }
233 if (n > 1024.0 * 1024.0) {
234 fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0);
235 return;
236 }
237 if (n > 1024.0) {
238 fprintf(f, "%.02f KiB", n / 1024.0);
239 return;
240 }
241 fprintf(f, "%.02f bytes", n );
242 return;
243}
244
245static int compare_type_abi_sizes_desc(const void *a, const void *b) {
246 uint64_t size_a = (*(ZigType * const*)(a))->abi_size;
247 uint64_t size_b = (*(ZigType * const*)(b))->abi_size;
248 if (size_a > size_b)
249 return -1;
250 if (size_a < size_b)
251 return 1;
252 return 0;
253}
254
255static void start_child(FILE *f, size_t indent) {
256 fprintf(f, "\n");
257 for (size_t i = 0; i < indent; i += 1) {
258 fprintf(f, " ");
259 }
260}
261
262static void start_peer(FILE *f, size_t indent) {
263 fprintf(f, ",\n");
264 for (size_t i = 0; i < indent; i += 1) {
265 fprintf(f, " ");
266 }
267}
268
269static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) {
270 ZigList<ZigType *> children = {};
271 uint64_t sum_from_fields = 0;
272 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
273 TypeStructField *field = &struct_type->data.structure.fields[i];
274 children.append(field->type_entry);
275 sum_from_fields += field->type_entry->abi_size;
276 }
277 qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc);
278
279 start_peer(f, indent);
280 fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields);
281
282 start_peer(f, indent);
283 fprintf(f, "\"fields\": [");
284
285 for (size_t i = 0; i < children.length; i += 1) {
286 if (i == 0) {
287 start_child(f, indent + 1);
288 } else {
289 start_peer(f, indent + 1);
290 }
291 fprintf(f, "{");
292
293 ZigType *child_type = children.at(i);
294 tree_print(f, child_type, indent + 2);
295
296 start_child(f, indent + 1);
297 fprintf(f, "}");
298 }
299
300 start_child(f, indent);
301 fprintf(f, "]");
302}
303
304static void tree_print(FILE *f, ZigType *ty, size_t indent) {
305 start_child(f, indent);
306 fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name));
307
308 start_peer(f, indent);
309 fprintf(f, "\"sizef\": \"");
310 pretty_print_bytes(f, ty->abi_size);
311 fprintf(f, "\"");
312
313 start_peer(f, indent);
314 fprintf(f, "\"size\": \"%" ZIG_PRI_usize "\"", ty->abi_size);
315
316 switch (ty->id) {
317 case ZigTypeIdFnFrame:
318 return tree_print_struct(f, ty->data.frame.locals_struct, indent);
319 case ZigTypeIdStruct:
320 return tree_print_struct(f, ty, indent);
321 default:
322 start_child(f, indent);
323 return;
324 }
325}
326
327void zig_print_stack_report(CodeGen *g, FILE *f) {
328 if (g->largest_frame_fn == nullptr) {
329 fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n");
330 return;
331 }
332 fprintf(f, "{");
333 tree_print(f, g->largest_frame_fn->frame_type, 1);
334
335 start_child(f, 0);
336 fprintf(f, "}\n");
337}
338
339struct AnalDumpCtx {
340 CodeGen *g;
341 JsonWriter jw;
342
343 ZigList<ZigType *> type_list;
344 HashMap<const ZigType *, uint32_t, type_ptr_hash, type_ptr_eql> type_map;
345
346 ZigList<ZigPackage *> pkg_list;
347 HashMap<const ZigPackage *, uint32_t, pkg_ptr_hash, pkg_ptr_eql> pkg_map;
348
349 ZigList<Buf *> file_list;
350 HashMap<Buf *, uint32_t, buf_hash, buf_eql_buf> file_map;
351
352 ZigList<Tld *> decl_list;
353 HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map;
354};
355
356static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty);
357static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ConstExprValue *value);
358
359static void anal_dump_poke_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ConstExprValue *value) {
360 Error err;
361 if (value->type != ty) {
362 return;
363 }
364 if ((err = ir_resolve_lazy(ctx->g, source_node, value))) {
365 codegen_report_errors_and_exit(ctx->g);
366 }
367 if (value->special == ConstValSpecialUndef) {
368 return;
369 }
370 if (value->special == ConstValSpecialRuntime) {
371 return;
372 }
373 switch (ty->id) {
374 case ZigTypeIdMetaType: {
375 ZigType *val_ty = value->data.x_type;
376 (void)anal_dump_get_type_id(ctx, val_ty);
377 return;
378 }
379 default:
380 return;
381 }
382 zig_unreachable();
383}
384
385static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty) {
386 uint32_t type_id = ctx->type_list.length;
387 auto existing_entry = ctx->type_map.put_unique(ty, type_id);
388 if (existing_entry == nullptr) {
389 ctx->type_list.append(ty);
390 } else {
391 type_id = existing_entry->value;
392 }
393 return type_id;
394}
395
396static uint32_t anal_dump_get_pkg_id(AnalDumpCtx *ctx, ZigPackage *pkg) {
397 assert(pkg != nullptr);
398 uint32_t pkg_id = ctx->pkg_list.length;
399 auto existing_entry = ctx->pkg_map.put_unique(pkg, pkg_id);
400 if (existing_entry == nullptr) {
401 ctx->pkg_list.append(pkg);
402 } else {
403 pkg_id = existing_entry->value;
404 }
405 return pkg_id;
406}
407
408static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) {
409 uint32_t file_id = ctx->file_list.length;
410 auto existing_entry = ctx->file_map.put_unique(file, file_id);
411 if (existing_entry == nullptr) {
412 ctx->file_list.append(file);
413 } else {
414 file_id = existing_entry->value;
415 }
416 return file_id;
417}
418
419static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) {
420 uint32_t decl_id = ctx->decl_list.length;
421 auto existing_entry = ctx->decl_map.put_unique(tld, decl_id);
422 if (existing_entry == nullptr) {
423 ctx->decl_list.append(tld);
424
425 if (tld->import != nullptr) {
426 (void)anal_dump_get_type_id(ctx, tld->import);
427 }
428
429 // poke the types
430 switch (tld->id) {
431 case TldIdVar: {
432 TldVar *tld_var = reinterpret_cast<TldVar *>(tld);
433 ZigVar *var = tld_var->var;
434
435 if (var != nullptr) {
436 (void)anal_dump_get_type_id(ctx, var->var_type);
437
438 if (var->const_value != nullptr) {
439 anal_dump_poke_value(ctx, var->decl_node, var->var_type, var->const_value);
440 }
441 }
442 break;
443 }
444 case TldIdFn: {
445 TldFn *tld_fn = reinterpret_cast<TldFn *>(tld);
446 ZigFn *fn = tld_fn->fn_entry;
447
448 if (fn != nullptr) {
449 (void)anal_dump_get_type_id(ctx, fn->type_entry);
450 }
451 break;
452 }
453 default:
454 break;
455 }
456
457 } else {
458 decl_id = existing_entry->value;
459 }
460 return decl_id;
461}
462
463static void anal_dump_type_ref(AnalDumpCtx *ctx, ZigType *ty) {
464 uint32_t type_id = anal_dump_get_type_id(ctx, ty);
465 jw_int(&ctx->jw, type_id);
466}
467
468static void anal_dump_pkg_ref(AnalDumpCtx *ctx, ZigPackage *pkg) {
469 uint32_t pkg_id = anal_dump_get_pkg_id(ctx, pkg);
470 jw_int(&ctx->jw, pkg_id);
471}
472
473static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) {
474 uint32_t file_id = anal_dump_get_file_id(ctx, file);
475 jw_int(&ctx->jw, file_id);
476}
477
478static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) {
479 uint32_t decl_id = anal_dump_get_decl_id(ctx, tld);
480 jw_int(&ctx->jw, decl_id);
481}
482
483static void anal_dump_pkg(AnalDumpCtx *ctx, ZigPackage *pkg) {
484 JsonWriter *jw = &ctx->jw;
485
486 Buf full_path_buf = BUF_INIT;
487 os_path_join(&pkg->root_src_dir, &pkg->root_src_path, &full_path_buf);
488 Buf *resolve_paths[] = { &full_path_buf, };
489 Buf *resolved_path = buf_alloc();
490 *resolved_path = os_path_resolve(resolve_paths, 1);
491
492 auto import_entry = ctx->g->import_table.maybe_get(resolved_path);
493 if (!import_entry) {
494 return;
495 }
496
497 jw_array_elem(jw);
498 jw_begin_object(jw);
499
500 jw_object_field(jw, "name");
501 jw_string(jw, buf_ptr(&pkg->pkg_path));
502
503 jw_object_field(jw, "file");
504 anal_dump_file_ref(ctx, resolved_path);
505
506 jw_object_field(jw, "main");
507 anal_dump_type_ref(ctx, import_entry->value);
508
509 jw_object_field(jw, "table");
510 jw_begin_object(jw);
511 auto it = pkg->package_table.entry_iterator();
512 for (;;) {
513 auto *entry = it.next();
514 if (!entry)
515 break;
516
517 ZigPackage *child_pkg = entry->value;
518 if (child_pkg != nullptr) {
519 jw_object_field(jw, buf_ptr(entry->key));
520 anal_dump_pkg_ref(ctx, child_pkg);
521 }
522 }
523 jw_end_object(jw);
524
525 jw_end_object(jw);
526}
527
528static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
529 JsonWriter *jw = &ctx->jw;
530
531 bool make_obj = tld->id == TldIdVar || tld->id == TldIdFn;
532 if (make_obj) {
533 jw_array_elem(jw);
534 jw_begin_object(jw);
535
536 jw_object_field(jw, "import");
537 anal_dump_type_ref(ctx, tld->import);
538
539 jw_object_field(jw, "line");
540 jw_int(jw, tld->source_node->line);
541
542 jw_object_field(jw, "col");
543 jw_int(jw, tld->source_node->column);
544
545 jw_object_field(jw, "name");
546 jw_string(jw, buf_ptr(tld->name));
547 }
548
549 switch (tld->id) {
550 case TldIdVar: {
551 TldVar *tld_var = reinterpret_cast<TldVar *>(tld);
552 ZigVar *var = tld_var->var;
553
554 if (var != nullptr) {
555 jw_object_field(jw, "kind");
556 if (var->src_is_const) {
557 jw_string(jw, "const");
558 } else {
559 jw_string(jw, "var");
560 }
561
562 if (var->is_thread_local) {
563 jw_object_field(jw, "threadlocal");
564 jw_bool(jw, true);
565 }
566
567 jw_object_field(jw, "type");
568 anal_dump_type_ref(ctx, var->var_type);
569
570 if (var->const_value != nullptr) {
571 jw_object_field(jw, "value");
572 anal_dump_value(ctx, var->decl_node, var->var_type, var->const_value);
573 }
574 }
575 break;
576 }
577 case TldIdFn: {
578 TldFn *tld_fn = reinterpret_cast<TldFn *>(tld);
579 ZigFn *fn = tld_fn->fn_entry;
580
581 if (fn != nullptr) {
582 jw_object_field(jw, "kind");
583 jw_string(jw, "const");
584
585 jw_object_field(jw, "type");
586 anal_dump_type_ref(ctx, fn->type_entry);
587 }
588
589 break;
590 }
591 default:
592 break;
593 }
594
595 if (make_obj) {
596 jw_end_object(jw);
597 }
598}
599
600static void anal_dump_file(AnalDumpCtx *ctx, Buf *file) {
601 JsonWriter *jw = &ctx->jw;
602 jw_string(jw, buf_ptr(file));
603}
604
605static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ConstExprValue *value) {
606 Error err;
607
608 if (value->type != ty) {
609 jw_null(&ctx->jw);
610 return;
611 }
612 if ((err = ir_resolve_lazy(ctx->g, source_node, value))) {
613 codegen_report_errors_and_exit(ctx->g);
614 }
615 if (value->special == ConstValSpecialUndef) {
616 jw_string(&ctx->jw, "undefined");
617 return;
618 }
619 if (value->special == ConstValSpecialRuntime) {
620 jw_null(&ctx->jw);
621 return;
622 }
623 switch (ty->id) {
624 case ZigTypeIdMetaType: {
625 ZigType *val_ty = value->data.x_type;
626 anal_dump_type_ref(ctx, val_ty);
627 return;
628 }
629 default:
630 jw_null(&ctx->jw);
631 return;
632 }
633 zig_unreachable();
634}
635
636static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
637 JsonWriter *jw = &ctx->jw;
638 jw_array_elem(jw);
639 jw_begin_object(jw);
640
641 jw_object_field(jw, "name");
642 jw_string(jw, buf_ptr(&ty->name));
643
644 jw_object_field(jw, "kind");
645 jw_int(jw, type_id_index(ty));
646
647 switch (ty->id) {
648 case ZigTypeIdStruct: {
649 if (ty->data.structure.is_slice) {
650 // TODO
651 break;
652 }
653 jw_object_field(jw, "decls");
654 jw_begin_array(jw);
655
656 ScopeDecls *decls_scope = ty->data.structure.decls_scope;
657 auto it = decls_scope->decl_table.entry_iterator();
658 for (;;) {
659 auto *entry = it.next();
660 if (!entry)
661 break;
662
663 Tld *tld = entry->value;
664
665 jw_array_elem(jw);
666 anal_dump_decl_ref(ctx, tld);
667 }
668 jw_end_array(jw);
669
670 if (ty->data.structure.root_struct != nullptr) {
671 Buf *path_buf = ty->data.structure.root_struct->path;
672
673 jw_object_field(jw, "file");
674 anal_dump_file_ref(ctx, path_buf);
675
676 }
677 break;
678 }
679 case ZigTypeIdFloat: {
680 jw_object_field(jw, "bits");
681 jw_int(jw, ty->data.floating.bit_count);
682 break;
683 }
684 default:
685 // TODO
686 break;
687 }
688 jw_end_object(jw);
689}
690
691void zig_print_analysis_dump(CodeGen *g, FILE *f) {
692 Error err;
693 AnalDumpCtx ctx = {};
694 ctx.g = g;
695 JsonWriter *jw = &ctx.jw;
696 jw_init(jw, f, " ", "\n");
697 ctx.type_map.init(16);
698 ctx.pkg_map.init(16);
699 ctx.file_map.init(16);
700 ctx.decl_map.init(16);
701
702 jw_begin_object(jw);
703
704 jw_object_field(jw, "typeKinds");
705 jw_begin_array(jw);
706 for (size_t i = 0; i < type_id_len(); i += 1) {
707 jw_array_elem(jw);
708 jw_string(jw, type_id_name(type_id_at_index(i)));
709 }
710 jw_end_array(jw);
711
712 jw_object_field(jw, "params");
713 jw_begin_object(jw);
714 {
715 jw_object_field(jw, "zigId");
716
717 Buf *compiler_id;
718 if ((err = get_compiler_id(&compiler_id))) {
719 fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
720 exit(1);
721 }
722 jw_string(jw, buf_ptr(compiler_id));
723
724 jw_object_field(jw, "zigVersion");
725 jw_string(jw, ZIG_VERSION_STRING);
726
727 jw_object_field(jw, "target");
728 Buf triple_buf = BUF_INIT;
729 target_triple_zig(&triple_buf, g->zig_target);
730 jw_string(jw, buf_ptr(&triple_buf));
731 }
732 jw_end_object(jw);
733
734 jw_object_field(jw, "rootPkg");
735 anal_dump_pkg_ref(&ctx, g->root_package);
736
737 jw_object_field(jw, "packages");
738 jw_begin_array(jw);
739 for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) {
740 anal_dump_pkg(&ctx, ctx.pkg_list.at(i));
741 }
742 jw_end_array(jw);
743
744 jw_object_field(jw, "types");
745 jw_begin_array(jw);
746
747 for (uint32_t i = 0; i < ctx.type_list.length; i += 1) {
748 ZigType *ty = ctx.type_list.at(i);
749 anal_dump_type(&ctx, ty);
750 }
751 jw_end_array(jw);
752
753 jw_object_field(jw, "decls");
754 jw_begin_array(jw);
755 for (uint32_t i = 0; i < ctx.decl_list.length; i += 1) {
756 Tld *decl = ctx.decl_list.at(i);
757 anal_dump_decl(&ctx, decl);
758 }
759 jw_end_array(jw);
760
761 jw_object_field(jw, "files");
762 jw_begin_array(jw);
763 for (uint32_t i = 0; i < ctx.file_list.length; i += 1) {
764 Buf *file = ctx.file_list.at(i);
765 jw_array_elem(jw);
766 anal_dump_file(&ctx, file);
767 }
768 jw_end_array(jw);
769
770 jw_end_object(jw);
771}
src/dump_analysis.hpp created+17
...@@ -0,0 +1,17 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_DUMP_ANALYSIS_HPP
9#define ZIG_DUMP_ANALYSIS_HPP
10
11#include "all_types.hpp"
12#include <stdio.h>
13
14void zig_print_stack_report(CodeGen *g, FILE *f);
15void zig_print_analysis_dump(CodeGen *g, FILE *f);
16
17#endif
src/main.cpp+6-1
...@@ -16,7 +16,7 @@...@@ -16,7 +16,7 @@
16#include "libc_installation.hpp"16#include "libc_installation.hpp"
17#include "userland.h"17#include "userland.h"
18#include "glibc.hpp"18#include "glibc.hpp"
19#include "stack_report.hpp"19#include "dump_analysis.hpp"
2020
21#include <stdio.h>21#include <stdio.h>
2222
...@@ -64,6 +64,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -64,6 +64,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
64 " -fno-PIC disable Position Independent Code\n"64 " -fno-PIC disable Position Independent Code\n"
65 " -ftime-report print timing diagnostics\n"65 " -ftime-report print timing diagnostics\n"
66 " -fstack-report print stack size diagnostics\n"66 " -fstack-report print stack size diagnostics\n"
67 " -fdump-analysis write analysis.json file for use with zig docs\n"
67 " --libc [file] Provide a file which specifies libc paths\n"68 " --libc [file] Provide a file which specifies libc paths\n"
68 " --name [name] override output name\n"69 " --name [name] override output name\n"
69 " --output-dir [dir] override output directory (defaults to cwd)\n"70 " --output-dir [dir] override output directory (defaults to cwd)\n"
...@@ -479,6 +480,7 @@ int main(int argc, char **argv) {...@@ -479,6 +480,7 @@ int main(int argc, char **argv) {
479 size_t ver_patch = 0;480 size_t ver_patch = 0;
480 bool timing_info = false;481 bool timing_info = false;
481 bool stack_report = false;482 bool stack_report = false;
483 bool enable_dump_analysis = false;
482 const char *cache_dir = nullptr;484 const char *cache_dir = nullptr;
483 CliPkg *cur_pkg = allocate<CliPkg>(1);485 CliPkg *cur_pkg = allocate<CliPkg>(1);
484 BuildMode build_mode = BuildModeDebug;486 BuildMode build_mode = BuildModeDebug;
...@@ -662,6 +664,8 @@ int main(int argc, char **argv) {...@@ -662,6 +664,8 @@ int main(int argc, char **argv) {
662 timing_info = true;664 timing_info = true;
663 } else if (strcmp(arg, "-fstack-report") == 0) {665 } else if (strcmp(arg, "-fstack-report") == 0) {
664 stack_report = true;666 stack_report = true;
667 } else if (strcmp(arg, "-fdump-analysis") == 0) {
668 enable_dump_analysis = true;
665 } else if (strcmp(arg, "--enable-valgrind") == 0) {669 } else if (strcmp(arg, "--enable-valgrind") == 0) {
666 valgrind_support = ValgrindSupportEnabled;670 valgrind_support = ValgrindSupportEnabled;
667 } else if (strcmp(arg, "--disable-valgrind") == 0) {671 } else if (strcmp(arg, "--disable-valgrind") == 0) {
...@@ -1138,6 +1142,7 @@ int main(int argc, char **argv) {...@@ -1138,6 +1142,7 @@ int main(int argc, char **argv) {
11381142
1139 g->enable_time_report = timing_info;1143 g->enable_time_report = timing_info;
1140 g->enable_stack_report = stack_report;1144 g->enable_stack_report = stack_report;
1145 g->enable_dump_analysis = enable_dump_analysis;
1141 codegen_set_out_name(g, buf_out_name);1146 codegen_set_out_name(g, buf_out_name);
1142 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);1147 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
1143 g->want_single_threaded = want_single_threaded;1148 g->want_single_threaded = want_single_threaded;
src/os.hpp+2
...@@ -47,6 +47,7 @@ extern const char *possible_ld_names[];...@@ -47,6 +47,7 @@ extern const char *possible_ld_names[];
4747
48#if defined(ZIG_OS_WINDOWS)48#if defined(ZIG_OS_WINDOWS)
49#define ZIG_PRI_usize "I64u"49#define ZIG_PRI_usize "I64u"
50#define ZIG_PRI_i64 "I64d"
50#define ZIG_PRI_u64 "I64u"51#define ZIG_PRI_u64 "I64u"
51#define ZIG_PRI_llu "I64u"52#define ZIG_PRI_llu "I64u"
52#define ZIG_PRI_x64 "I64x"53#define ZIG_PRI_x64 "I64x"
...@@ -54,6 +55,7 @@ extern const char *possible_ld_names[];...@@ -54,6 +55,7 @@ extern const char *possible_ld_names[];
54#define ZIG_OS_SEP_CHAR '\\'55#define ZIG_OS_SEP_CHAR '\\'
55#else56#else
56#define ZIG_PRI_usize "zu"57#define ZIG_PRI_usize "zu"
58#define ZIG_PRI_i64 PRId64
57#define ZIG_PRI_u64 PRIu6459#define ZIG_PRI_u64 PRIu64
58#define ZIG_PRI_llu "llu"60#define ZIG_PRI_llu "llu"
59#define ZIG_PRI_x64 PRIx6461#define ZIG_PRI_x64 PRIx64
src/stack_report.cpp deleted-121
...@@ -1,121 +0,0 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "stack_report.hpp"
9
10static void tree_print(FILE *f, ZigType *ty, size_t indent);
11
12static void pretty_print_bytes(FILE *f, double n) {
13 if (n > 1024.0 * 1024.0 * 1024.0) {
14 fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0);
15 return;
16 }
17 if (n > 1024.0 * 1024.0) {
18 fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0);
19 return;
20 }
21 if (n > 1024.0) {
22 fprintf(f, "%.02f KiB", n / 1024.0);
23 return;
24 }
25 fprintf(f, "%.02f bytes", n );
26 return;
27}
28
29static int compare_type_abi_sizes_desc(const void *a, const void *b) {
30 uint64_t size_a = (*(ZigType * const*)(a))->abi_size;
31 uint64_t size_b = (*(ZigType * const*)(b))->abi_size;
32 if (size_a > size_b)
33 return -1;
34 if (size_a < size_b)
35 return 1;
36 return 0;
37}
38
39static void start_child(FILE *f, size_t indent) {
40 fprintf(f, "\n");
41 for (size_t i = 0; i < indent; i += 1) {
42 fprintf(f, " ");
43 }
44}
45
46static void start_peer(FILE *f, size_t indent) {
47 fprintf(f, ",\n");
48 for (size_t i = 0; i < indent; i += 1) {
49 fprintf(f, " ");
50 }
51}
52
53static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) {
54 ZigList<ZigType *> children = {};
55 uint64_t sum_from_fields = 0;
56 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
57 TypeStructField *field = &struct_type->data.structure.fields[i];
58 children.append(field->type_entry);
59 sum_from_fields += field->type_entry->abi_size;
60 }
61 qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc);
62
63 start_peer(f, indent);
64 fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields);
65
66 start_peer(f, indent);
67 fprintf(f, "\"fields\": [");
68
69 for (size_t i = 0; i < children.length; i += 1) {
70 if (i == 0) {
71 start_child(f, indent + 1);
72 } else {
73 start_peer(f, indent + 1);
74 }
75 fprintf(f, "{");
76
77 ZigType *child_type = children.at(i);
78 tree_print(f, child_type, indent + 2);
79
80 start_child(f, indent + 1);
81 fprintf(f, "}");
82 }
83
84 start_child(f, indent);
85 fprintf(f, "]");
86}
87
88static void tree_print(FILE *f, ZigType *ty, size_t indent) {
89 start_child(f, indent);
90 fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name));
91
92 start_peer(f, indent);
93 fprintf(f, "\"sizef\": \"");
94 pretty_print_bytes(f, ty->abi_size);
95 fprintf(f, "\"");
96
97 start_peer(f, indent);
98 fprintf(f, "\"size\": \"%" ZIG_PRI_usize "\"", ty->abi_size);
99
100 switch (ty->id) {
101 case ZigTypeIdFnFrame:
102 return tree_print_struct(f, ty->data.frame.locals_struct, indent);
103 case ZigTypeIdStruct:
104 return tree_print_struct(f, ty, indent);
105 default:
106 start_child(f, indent);
107 return;
108 }
109}
110
111void zig_print_stack_report(CodeGen *g, FILE *f) {
112 if (g->largest_frame_fn == nullptr) {
113 fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n");
114 return;
115 }
116 fprintf(f, "{");
117 tree_print(f, g->largest_frame_fn->frame_type, 1);
118
119 start_child(f, 0);
120 fprintf(f, "}\n");
121}
src/stack_report.hpp deleted-16
...@@ -1,16 +0,0 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_STACK_REPORT_HPP
9#define ZIG_STACK_REPORT_HPP
10
11#include "all_types.hpp"
12#include <stdio.h>
13
14void zig_print_stack_report(CodeGen *g, FILE *f);
15
16#endif