authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-18 14:01:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:12-07:00
log7d636f0f9da49337ae3a54af25e6465af033bd89
treee08e242a1f3f1f29b521758930bcd538713324d5
parent8df1b91d17dcc81a15458d5c73351bca3106922a

delete the stage1 implementation of autodoc


10 files changed, 0 insertions(+), 1975 deletions(-)

CMakeLists.txt-1
......@@ -340,7 +340,6 @@ set(STAGE1_SOURCES
340340 "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp"
341341 "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp"
342342 "${CMAKE_SOURCE_DIR}/src/stage1/codegen.cpp"
343 "${CMAKE_SOURCE_DIR}/src/stage1/dump_analysis.cpp"
344343 "${CMAKE_SOURCE_DIR}/src/stage1/errmsg.cpp"
345344 "${CMAKE_SOURCE_DIR}/src/stage1/error.cpp"
346345 "${CMAKE_SOURCE_DIR}/src/stage1/heap.cpp"
src/Compilation.zig-6
......@@ -5169,8 +5169,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
51695169 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
51705170 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);
51715171 const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory);
5172 const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory);
5173 const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory);
51745172 const stage1_pkg = try createStage1Pkg(arena, "root", mod.main_pkg, null);
51755173 const test_filter = comp.test_filter orelse ""[0..0];
51765174 const test_name_prefix = comp.test_name_prefix orelse ""[0..0];
......@@ -5191,10 +5189,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
51915189 .emit_llvm_ir_len = emit_llvm_ir_path.len,
51925190 .emit_bitcode_ptr = emit_llvm_bc_path.ptr,
51935191 .emit_bitcode_len = emit_llvm_bc_path.len,
5194 .emit_analysis_json_ptr = emit_analysis_path.ptr,
5195 .emit_analysis_json_len = emit_analysis_path.len,
5196 .emit_docs_ptr = emit_docs_path.ptr,
5197 .emit_docs_len = emit_docs_path.len,
51985192 .builtin_zig_path_ptr = builtin_zig_path.ptr,
51995193 .builtin_zig_path_len = builtin_zig_path.len,
52005194 .test_filter_ptr = test_filter.ptr,
src/stage1.zig-4
......@@ -96,10 +96,6 @@ pub const Module = extern struct {
9696 emit_llvm_ir_len: usize,
9797 emit_bitcode_ptr: [*]const u8,
9898 emit_bitcode_len: usize,
99 emit_analysis_json_ptr: [*]const u8,
100 emit_analysis_json_len: usize,
101 emit_docs_ptr: [*]const u8,
102 emit_docs_len: usize,
10399 builtin_zig_path_ptr: [*]const u8,
104100 builtin_zig_path_len: usize,
105101 test_filter_ptr: [*]const u8,
src/stage1/all_types.hpp-2
......@@ -2141,8 +2141,6 @@ struct CodeGen {
21412141 Buf asm_file_output_path;
21422142 Buf llvm_ir_file_output_path;
21432143 Buf bitcode_file_output_path;
2144 Buf analysis_json_output_path;
2145 Buf docs_output_path;
21462144
21472145 Buf *builtin_zig_path;
21482146
src/stage1/codegen.cpp-52
......@@ -16,7 +16,6 @@
1616#include "util.hpp"
1717#include "zig_llvm.h"
1818#include "stage2.h"
19#include "dump_analysis.hpp"
2019#include "softfloat.hpp"
2120#include "zigendian.h"
2221
......@@ -10546,57 +10545,6 @@ void codegen_build_object(CodeGen *g) {
1054610545
1054710546 gen_root_source(g);
1054810547
10549 if (buf_len(&g->analysis_json_output_path) != 0) {
10550 const char *analysis_json_filename = buf_ptr(&g->analysis_json_output_path);
10551 FILE *f = fopen(analysis_json_filename, "wb");
10552 if (f == nullptr) {
10553 fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno));
10554 exit(1);
10555 }
10556 zig_print_analysis_dump(g, f, " ", "\n");
10557 if (fclose(f) != 0) {
10558 fprintf(stderr, "Unable to write '%s': %s\n", analysis_json_filename, strerror(errno));
10559 exit(1);
10560 }
10561 }
10562 if (buf_len(&g->docs_output_path) != 0) {
10563 Error err;
10564 Buf *doc_dir_path = &g->docs_output_path;
10565 if ((err = os_make_path(doc_dir_path))) {
10566 fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err));
10567 exit(1);
10568 }
10569 Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "docs" OS_SEP "index.html",
10570 buf_ptr(g->zig_lib_dir));
10571 Buf *index_html_dest_path = buf_sprintf("%s" OS_SEP "index.html", buf_ptr(doc_dir_path));
10572 Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "docs" OS_SEP "main.js",
10573 buf_ptr(g->zig_lib_dir));
10574 Buf *main_js_dest_path = buf_sprintf("%s" OS_SEP "main.js", buf_ptr(doc_dir_path));
10575
10576 if ((err = os_copy_file(index_html_src_path, index_html_dest_path))) {
10577 fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(index_html_src_path),
10578 buf_ptr(index_html_dest_path), err_str(err));
10579 exit(1);
10580 }
10581 if ((err = os_copy_file(main_js_src_path, main_js_dest_path))) {
10582 fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(main_js_src_path),
10583 buf_ptr(main_js_dest_path), err_str(err));
10584 exit(1);
10585 }
10586 const char *data_js_filename = buf_ptr(buf_sprintf("%s" OS_SEP "data.js", buf_ptr(doc_dir_path)));
10587 FILE *f = fopen(data_js_filename, "wb");
10588 if (f == nullptr) {
10589 fprintf(stderr, "Unable to open '%s': %s\n", data_js_filename, strerror(errno));
10590 exit(1);
10591 }
10592 fprintf(f, "zigAnalysis=");
10593 zig_print_analysis_dump(g, f, "", "");
10594 fprintf(f, ";");
10595 if (fclose(f) != 0) {
10596 fprintf(stderr, "Unable to write '%s': %s\n", data_js_filename, strerror(errno));
10597 exit(1);
10598 }
10599 }
1060010548
1060110549 codegen_add_time_event(g, "Code Generation");
1060210550 {
src/stage1/dump_analysis.cpp deleted-1431
......@@ -1,1431 +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 "dump_analysis.hpp"
9#include "analyze.hpp"
10#include "ir.hpp"
11#include "codegen.hpp"
12#include "os.hpp"
13
14enum JsonWriterState {
15 JsonWriterStateInvalid,
16 JsonWriterStateValue,
17 JsonWriterStateArrayStart,
18 JsonWriterStateArray,
19 JsonWriterStateObjectStart,
20 JsonWriterStateObject,
21};
22
23#define JSON_MAX_DEPTH 10
24
25struct JsonWriter {
26 size_t state_index;
27 FILE *f;
28 const char *one_indent;
29 const char *nl;
30 JsonWriterState state[JSON_MAX_DEPTH];
31};
32
33static void jw_init(JsonWriter *jw, FILE *f, const char *one_indent, const char *nl) {
34 jw->state_index = 1;
35 jw->f = f;
36 jw->one_indent = one_indent;
37 jw->nl = nl;
38 jw->state[0] = JsonWriterStateInvalid;
39 jw->state[1] = JsonWriterStateValue;
40}
41
42static void jw_nl_indent(JsonWriter *jw) {
43 assert(jw->state_index >= 1);
44 fprintf(jw->f, "%s", jw->nl);
45 for (size_t i = 0; i < jw->state_index - 1; i += 1) {
46 fprintf(jw->f, "%s", jw->one_indent);
47 }
48}
49
50static void jw_push_state(JsonWriter *jw, JsonWriterState state) {
51 jw->state_index += 1;
52 assert(jw->state_index < JSON_MAX_DEPTH);
53 jw->state[jw->state_index] = state;
54}
55
56static void jw_pop_state(JsonWriter *jw) {
57 assert(jw->state_index != 0);
58 jw->state_index -= 1;
59}
60
61static void jw_begin_array(JsonWriter *jw) {
62 assert(jw->state[jw->state_index] == JsonWriterStateValue);
63 fprintf(jw->f, "[");
64 jw->state[jw->state_index] = JsonWriterStateArrayStart;
65}
66
67static void jw_begin_object(JsonWriter *jw) {
68 assert(jw->state[jw->state_index] == JsonWriterStateValue);
69 fprintf(jw->f, "{");
70 jw->state[jw->state_index] = JsonWriterStateObjectStart;
71}
72
73static void jw_array_elem(JsonWriter *jw) {
74 switch (jw->state[jw->state_index]) {
75 case JsonWriterStateInvalid:
76 case JsonWriterStateValue:
77 case JsonWriterStateObjectStart:
78 case JsonWriterStateObject:
79 zig_unreachable();
80 case JsonWriterStateArray:
81 fprintf(jw->f, ",");
82 ZIG_FALLTHROUGH;
83 case JsonWriterStateArrayStart:
84 jw->state[jw->state_index] = JsonWriterStateArray;
85 jw_push_state(jw, JsonWriterStateValue);
86 jw_nl_indent(jw);
87 return;
88 }
89 zig_unreachable();
90}
91
92static void jw_write_escaped_string(JsonWriter *jw, const char *s) {
93 fprintf(jw->f, "\"");
94 for (;; s += 1) {
95 switch (*s) {
96 case 0:
97 fprintf(jw->f, "\"");
98 return;
99 case '"':
100 fprintf(jw->f, "\\\"");
101 continue;
102 case '\t':
103 fprintf(jw->f, "\\t");
104 continue;
105 case '\r':
106 fprintf(jw->f, "\\r");
107 continue;
108 case '\n':
109 fprintf(jw->f, "\\n");
110 continue;
111 case '\b':
112 fprintf(jw->f, "\\b");
113 continue;
114 case '\f':
115 fprintf(jw->f, "\\f");
116 continue;
117 case '\\':
118 fprintf(jw->f, "\\\\");
119 continue;
120 default:
121 fprintf(jw->f, "%c", *s);
122 continue;
123 }
124 }
125}
126
127static void jw_object_field(JsonWriter *jw, const char *name) {
128 switch (jw->state[jw->state_index]) {
129 case JsonWriterStateInvalid:
130 case JsonWriterStateValue:
131 case JsonWriterStateArray:
132 case JsonWriterStateArrayStart:
133 zig_unreachable();
134 case JsonWriterStateObject:
135 fprintf(jw->f, ",");
136 ZIG_FALLTHROUGH;
137 case JsonWriterStateObjectStart:
138 jw->state[jw->state_index] = JsonWriterStateObject;
139 jw_push_state(jw, JsonWriterStateValue);
140 jw_nl_indent(jw);
141 jw_write_escaped_string(jw, name);
142 fprintf(jw->f, ": ");
143 return;
144 }
145 zig_unreachable();
146}
147
148static void jw_end_array(JsonWriter *jw) {
149 switch (jw->state[jw->state_index]) {
150 case JsonWriterStateInvalid:
151 case JsonWriterStateValue:
152 case JsonWriterStateObjectStart:
153 case JsonWriterStateObject:
154 zig_unreachable();
155 case JsonWriterStateArrayStart:
156 fprintf(jw->f, "]");
157 jw_pop_state(jw);
158 return;
159 case JsonWriterStateArray:
160 jw_nl_indent(jw);
161 jw_pop_state(jw);
162 fprintf(jw->f, "]");
163 return;
164 }
165 zig_unreachable();
166}
167
168
169static void jw_end_object(JsonWriter *jw) {
170 switch (jw->state[jw->state_index]) {
171 case JsonWriterStateInvalid:
172 zig_unreachable();
173 case JsonWriterStateValue:
174 zig_unreachable();
175 case JsonWriterStateArray:
176 zig_unreachable();
177 case JsonWriterStateArrayStart:
178 zig_unreachable();
179 case JsonWriterStateObjectStart:
180 fprintf(jw->f, "}");
181 jw_pop_state(jw);
182 return;
183 case JsonWriterStateObject:
184 jw_nl_indent(jw);
185 jw_pop_state(jw);
186 fprintf(jw->f, "}");
187 return;
188 }
189 zig_unreachable();
190}
191
192static void jw_null(JsonWriter *jw) {
193 assert(jw->state[jw->state_index] == JsonWriterStateValue);
194 fprintf(jw->f, "null");
195 jw_pop_state(jw);
196}
197
198static void jw_bool(JsonWriter *jw, bool x) {
199 assert(jw->state[jw->state_index] == JsonWriterStateValue);
200 if (x) {
201 fprintf(jw->f, "true");
202 } else {
203 fprintf(jw->f, "false");
204 }
205 jw_pop_state(jw);
206}
207
208static void jw_int(JsonWriter *jw, int64_t x) {
209 assert(jw->state[jw->state_index] == JsonWriterStateValue);
210 if (x > 4503599627370496 || x < -4503599627370496) {
211 fprintf(jw->f, "\"%" ZIG_PRI_i64 "\"", x);
212 } else {
213 fprintf(jw->f, "%" ZIG_PRI_i64, x);
214 }
215 jw_pop_state(jw);
216}
217
218static void jw_bigint(JsonWriter *jw, const BigInt *x) {
219 assert(jw->state[jw->state_index] == JsonWriterStateValue);
220 Buf *str = buf_alloc();
221 bigint_append_buf(str, x, 10);
222
223 if (bigint_fits_in_bits(x, 52, true)) {
224 fprintf(jw->f, "%s", buf_ptr(str));
225 } else {
226 fprintf(jw->f, "\"%s\"", buf_ptr(str));
227 }
228 jw_pop_state(jw);
229
230 buf_destroy(str);
231}
232
233static void jw_string(JsonWriter *jw, const char *s) {
234 assert(jw->state[jw->state_index] == JsonWriterStateValue);
235 jw_write_escaped_string(jw, s);
236 jw_pop_state(jw);
237}
238
239
240static void tree_print(FILE *f, ZigType *ty, size_t indent);
241
242static int compare_type_abi_sizes_desc(const void *a, const void *b) {
243 uint64_t size_a = (*(ZigType * const*)(a))->abi_size;
244 uint64_t size_b = (*(ZigType * const*)(b))->abi_size;
245 if (size_a > size_b)
246 return -1;
247 if (size_a < size_b)
248 return 1;
249 return 0;
250}
251
252static void start_child(FILE *f, size_t indent) {
253 fprintf(f, "\n");
254 for (size_t i = 0; i < indent; i += 1) {
255 fprintf(f, " ");
256 }
257}
258
259static void start_peer(FILE *f, size_t indent) {
260 fprintf(f, ",\n");
261 for (size_t i = 0; i < indent; i += 1) {
262 fprintf(f, " ");
263 }
264}
265
266static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) {
267 ZigList<ZigType *> children = {};
268 uint64_t sum_from_fields = 0;
269 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
270 TypeStructField *field = struct_type->data.structure.fields[i];
271 children.append(field->type_entry);
272 sum_from_fields += field->type_entry->abi_size;
273 }
274 qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc);
275
276 start_peer(f, indent);
277 fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields);
278
279 start_peer(f, indent);
280 fprintf(f, "\"fields\": [");
281
282 for (size_t i = 0; i < children.length; i += 1) {
283 if (i == 0) {
284 start_child(f, indent + 1);
285 } else {
286 start_peer(f, indent + 1);
287 }
288 fprintf(f, "{");
289
290 ZigType *child_type = children.at(i);
291 tree_print(f, child_type, indent + 2);
292
293 start_child(f, indent + 1);
294 fprintf(f, "}");
295 }
296
297 start_child(f, indent);
298 fprintf(f, "]");
299}
300
301static void tree_print(FILE *f, ZigType *ty, size_t indent) {
302 start_child(f, indent);
303 fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name));
304
305 start_peer(f, indent);
306 fprintf(f, "\"sizef\": \"");
307 zig_pretty_print_bytes(f, ty->abi_size);
308 fprintf(f, "\"");
309
310 start_peer(f, indent);
311 fprintf(f, "\"size\": \"%" ZIG_PRI_usize "\"", ty->abi_size);
312
313 switch (ty->id) {
314 case ZigTypeIdFnFrame:
315 return tree_print_struct(f, ty->data.frame.locals_struct, indent);
316 case ZigTypeIdStruct:
317 return tree_print_struct(f, ty, indent);
318 default:
319 start_child(f, indent);
320 return;
321 }
322}
323
324void zig_print_stack_report(CodeGen *g, FILE *f) {
325 if (g->largest_frame_fn == nullptr) {
326 fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n");
327 return;
328 }
329 fprintf(f, "{");
330 tree_print(f, g->largest_frame_fn->frame_type, 1);
331
332 start_child(f, 0);
333 fprintf(f, "}\n");
334}
335
336struct AnalDumpCtx {
337 CodeGen *g;
338 JsonWriter jw;
339
340 ZigList<ZigType *> type_list;
341 HashMap<const ZigType *, uint32_t, type_ptr_hash, type_ptr_eql> type_map;
342
343 ZigList<ZigPackage *> pkg_list;
344 HashMap<const ZigPackage *, uint32_t, pkg_ptr_hash, pkg_ptr_eql> pkg_map;
345
346 ZigList<Buf *> file_list;
347 HashMap<Buf *, uint32_t, buf_hash, buf_eql_buf> file_map;
348
349 ZigList<Tld *> decl_list;
350 HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map;
351
352 ZigList<ZigFn *> fn_list;
353 HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_map;
354 HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_decl_map;
355
356 ZigList<AstNode *> node_list;
357 HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map;
358
359 ZigList<ErrorTableEntry *> err_list;
360 HashMap<const ErrorTableEntry *, uint32_t, err_ptr_hash, err_ptr_eql> err_map;
361};
362
363static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty);
364static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value);
365
366static void anal_dump_poke_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value) {
367 Error err;
368 if (value->type != ty) {
369 return;
370 }
371 if ((err = ir_resolve_lazy(ctx->g, source_node, value))) {
372 codegen_report_errors_and_exit(ctx->g);
373 }
374 if (value->special == ConstValSpecialUndef) {
375 return;
376 }
377 if (value->special == ConstValSpecialRuntime) {
378 return;
379 }
380 switch (ty->id) {
381 case ZigTypeIdMetaType: {
382 ZigType *val_ty = value->data.x_type;
383 (void)anal_dump_get_type_id(ctx, val_ty);
384 return;
385 }
386 default:
387 return;
388 }
389 zig_unreachable();
390}
391
392static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty) {
393 uint32_t type_id = ctx->type_list.length;
394 auto existing_entry = ctx->type_map.put_unique(ty, type_id);
395 if (existing_entry == nullptr) {
396 ctx->type_list.append(ty);
397 } else {
398 type_id = existing_entry->value;
399 }
400 return type_id;
401}
402
403static uint32_t anal_dump_get_pkg_id(AnalDumpCtx *ctx, ZigPackage *pkg) {
404 assert(pkg != nullptr);
405 uint32_t pkg_id = ctx->pkg_list.length;
406 auto existing_entry = ctx->pkg_map.put_unique(pkg, pkg_id);
407 if (existing_entry == nullptr) {
408 ctx->pkg_list.append(pkg);
409 } else {
410 pkg_id = existing_entry->value;
411 }
412 return pkg_id;
413}
414
415static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) {
416 uint32_t file_id = ctx->file_list.length;
417 auto existing_entry = ctx->file_map.put_unique(file, file_id);
418 if (existing_entry == nullptr) {
419 ctx->file_list.append(file);
420 } else {
421 file_id = existing_entry->value;
422 }
423 return file_id;
424}
425
426static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) {
427 uint32_t node_id = ctx->node_list.length;
428 auto existing_entry = ctx->node_map.put_unique(node, node_id);
429 if (existing_entry == nullptr) {
430 ctx->node_list.append(node);
431 } else {
432 node_id = existing_entry->value;
433 }
434 return node_id;
435}
436
437static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
438 uint32_t fn_id = ctx->fn_list.length;
439 auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);
440 if (existing_entry == nullptr) {
441 ctx->fn_list.append(fn);
442
443 // poke the fn
444 (void)anal_dump_get_type_id(ctx, fn->type_entry);
445 (void)anal_dump_get_node_id(ctx, fn->proto_node);
446 } else {
447 fn_id = existing_entry->value;
448 }
449 return fn_id;
450}
451
452static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) {
453 uint32_t err_id = ctx->err_list.length;
454 auto existing_entry = ctx->err_map.put_unique(err, err_id);
455 if (existing_entry == nullptr) {
456 ctx->err_list.append(err);
457 } else {
458 err_id = existing_entry->value;
459 }
460 return err_id;
461}
462
463static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) {
464 uint32_t decl_id = ctx->decl_list.length;
465 auto existing_entry = ctx->decl_map.put_unique(tld, decl_id);
466 if (existing_entry == nullptr) {
467 ctx->decl_list.append(tld);
468
469 if (tld->import != nullptr) {
470 (void)anal_dump_get_type_id(ctx, tld->import);
471 }
472
473 // poke the types
474 switch (tld->id) {
475 case TldIdVar: {
476 TldVar *tld_var = reinterpret_cast<TldVar *>(tld);
477 ZigVar *var = tld_var->var;
478
479 if (var != nullptr) {
480 (void)anal_dump_get_type_id(ctx, var->var_type);
481
482 if (var->const_value != nullptr) {
483 anal_dump_poke_value(ctx, var->decl_node, var->var_type, var->const_value);
484 }
485 }
486 break;
487 }
488 case TldIdFn: {
489 TldFn *tld_fn = reinterpret_cast<TldFn *>(tld);
490 ZigFn *fn = tld_fn->fn_entry;
491
492 if (fn != nullptr) {
493 (void)anal_dump_get_type_id(ctx, fn->type_entry);
494 ctx->fn_decl_map.put_unique(fn, decl_id);
495 }
496 break;
497 }
498 default:
499 break;
500 }
501
502 } else {
503 decl_id = existing_entry->value;
504 }
505 return decl_id;
506}
507
508static void anal_dump_type_ref(AnalDumpCtx *ctx, ZigType *ty) {
509 uint32_t type_id = anal_dump_get_type_id(ctx, ty);
510 jw_int(&ctx->jw, type_id);
511}
512
513static void anal_dump_pkg_ref(AnalDumpCtx *ctx, ZigPackage *pkg) {
514 uint32_t pkg_id = anal_dump_get_pkg_id(ctx, pkg);
515 jw_int(&ctx->jw, pkg_id);
516}
517
518static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) {
519 uint32_t file_id = anal_dump_get_file_id(ctx, file);
520 jw_int(&ctx->jw, file_id);
521}
522
523static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) {
524 uint32_t node_id = anal_dump_get_node_id(ctx, node);
525 jw_int(&ctx->jw, node_id);
526}
527
528static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) {
529 uint32_t fn_id = anal_dump_get_fn_id(ctx, fn);
530 jw_int(&ctx->jw, fn_id);
531}
532
533static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) {
534 uint32_t err_id = anal_dump_get_err_id(ctx, err);
535 jw_int(&ctx->jw, err_id);
536}
537
538static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) {
539 uint32_t decl_id = anal_dump_get_decl_id(ctx, tld);
540 jw_int(&ctx->jw, decl_id);
541}
542
543static void anal_dump_pkg(AnalDumpCtx *ctx, ZigPackage *pkg) {
544 JsonWriter *jw = &ctx->jw;
545
546 Buf full_path_buf = BUF_INIT;
547 os_path_join(&pkg->root_src_dir, &pkg->root_src_path, &full_path_buf);
548 Buf *resolve_paths[] = { &full_path_buf, };
549 Buf *resolved_path = buf_alloc();
550 *resolved_path = os_path_resolve(resolve_paths, 1);
551
552 auto import_entry = ctx->g->import_table.maybe_get(resolved_path);
553 if (!import_entry) {
554 return;
555 }
556
557 jw_array_elem(jw);
558 jw_begin_object(jw);
559
560 jw_object_field(jw, "name");
561 jw_string(jw, buf_ptr(&pkg->pkg_path));
562
563 jw_object_field(jw, "file");
564 anal_dump_file_ref(ctx, resolved_path);
565
566 jw_object_field(jw, "main");
567 anal_dump_type_ref(ctx, import_entry->value);
568
569 jw_object_field(jw, "table");
570 jw_begin_object(jw);
571 auto it = pkg->package_table.entry_iterator();
572 for (;;) {
573 auto *entry = it.next();
574 if (!entry)
575 break;
576
577 ZigPackage *child_pkg = entry->value;
578 if (child_pkg != nullptr) {
579 jw_object_field(jw, buf_ptr(entry->key));
580 anal_dump_pkg_ref(ctx, child_pkg);
581 }
582 }
583 jw_end_object(jw);
584
585 jw_end_object(jw);
586}
587
588static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
589 JsonWriter *jw = &ctx->jw;
590
591 bool make_obj = tld->id == TldIdVar || tld->id == TldIdFn;
592 if (make_obj) {
593 jw_array_elem(jw);
594 jw_begin_object(jw);
595
596 jw_object_field(jw, "import");
597 anal_dump_type_ref(ctx, tld->import);
598
599 jw_object_field(jw, "src");
600 anal_dump_node_ref(ctx, tld->source_node);
601
602 jw_object_field(jw, "name");
603 jw_string(jw, buf_ptr(tld->name));
604 }
605
606 switch (tld->id) {
607 case TldIdVar: {
608 TldVar *tld_var = reinterpret_cast<TldVar *>(tld);
609 ZigVar *var = tld_var->var;
610
611 if (var != nullptr) {
612 jw_object_field(jw, "kind");
613 if (var->src_is_const) {
614 jw_string(jw, "const");
615 } else {
616 jw_string(jw, "var");
617 }
618
619 if (var->is_thread_local) {
620 jw_object_field(jw, "threadlocal");
621 jw_bool(jw, true);
622 }
623
624 jw_object_field(jw, "type");
625 anal_dump_type_ref(ctx, var->var_type);
626
627 if (var->const_value != nullptr) {
628 jw_object_field(jw, "value");
629 anal_dump_value(ctx, var->decl_node, var->var_type, var->const_value);
630 }
631 }
632 break;
633 }
634 case TldIdFn: {
635 TldFn *tld_fn = reinterpret_cast<TldFn *>(tld);
636 ZigFn *fn = tld_fn->fn_entry;
637
638 if (fn != nullptr) {
639 jw_object_field(jw, "kind");
640 jw_string(jw, "const");
641
642 jw_object_field(jw, "type");
643 anal_dump_type_ref(ctx, fn->type_entry);
644
645 jw_object_field(jw, "value");
646 anal_dump_fn_ref(ctx, fn);
647 }
648 break;
649 }
650 default:
651 break;
652 }
653
654 if (make_obj) {
655 jw_end_object(jw);
656 }
657}
658
659static void anal_dump_file(AnalDumpCtx *ctx, Buf *file) {
660 JsonWriter *jw = &ctx->jw;
661 jw_string(jw, buf_ptr(file));
662}
663
664static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value) {
665 Error err;
666
667 if (value->type != ty) {
668 jw_null(&ctx->jw);
669 return;
670 }
671 if ((err = ir_resolve_lazy(ctx->g, source_node, value))) {
672 codegen_report_errors_and_exit(ctx->g);
673 }
674 if (value->special == ConstValSpecialUndef) {
675 jw_string(&ctx->jw, "undefined");
676 return;
677 }
678 if (value->special == ConstValSpecialRuntime) {
679 jw_null(&ctx->jw);
680 return;
681 }
682 switch (ty->id) {
683 case ZigTypeIdMetaType: {
684 ZigType *val_ty = value->data.x_type;
685 anal_dump_type_ref(ctx, val_ty);
686 return;
687 }
688 case ZigTypeIdFn: {
689 if (value->data.x_ptr.special == ConstPtrSpecialFunction) {
690 ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;
691 anal_dump_fn_ref(ctx, val_fn);
692 } else {
693 jw_null(&ctx->jw);
694 }
695 return;
696 }
697 case ZigTypeIdOptional: {
698 if(optional_value_is_null(value)){
699 jw_string(&ctx->jw, "null");
700 } else {
701 jw_null(&ctx->jw);
702 }
703 return;
704 }
705 case ZigTypeIdBool: {
706 jw_string(&ctx->jw, value->data.x_bool ? "true" : "false");
707 return;
708 }
709 case ZigTypeIdInt: {
710 jw_bigint(&ctx->jw, &value->data.x_bigint);
711 return;
712 }
713 default:
714 jw_null(&ctx->jw);
715 return;
716 }
717 zig_unreachable();
718}
719
720static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) {
721 JsonWriter *jw = &ctx->jw;
722 if (ty->data.pointer.explicit_alignment != 0) {
723 jw_object_field(jw, "align");
724 jw_int(jw, ty->data.pointer.explicit_alignment);
725 }
726 if (ty->data.pointer.is_const) {
727 jw_object_field(jw, "const");
728 jw_bool(jw, true);
729 }
730 if (ty->data.pointer.is_volatile) {
731 jw_object_field(jw, "volatile");
732 jw_bool(jw, true);
733 }
734 if (ty->data.pointer.allow_zero) {
735 jw_object_field(jw, "allowZero");
736 jw_bool(jw, true);
737 }
738 if (ty->data.pointer.host_int_bytes != 0) {
739 jw_object_field(jw, "hostIntBytes");
740 jw_int(jw, ty->data.pointer.host_int_bytes);
741
742 jw_object_field(jw, "bitOffsetInHost");
743 jw_int(jw, ty->data.pointer.bit_offset_in_host);
744 }
745
746 jw_object_field(jw, "elem");
747 anal_dump_type_ref(ctx, ty->data.pointer.child_type);
748}
749
750static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
751 JsonWriter *jw = &ctx->jw;
752 jw_array_elem(jw);
753 jw_begin_object(jw);
754
755 jw_object_field(jw, "kind");
756 jw_int(jw, type_id_index(ty));
757
758 switch (ty->id) {
759 case ZigTypeIdMetaType:
760 case ZigTypeIdBool:
761 case ZigTypeIdEnumLiteral:
762 break;
763 case ZigTypeIdStruct: {
764 if (ty->data.structure.special == StructSpecialSlice) {
765 jw_object_field(jw, "len");
766 jw_int(jw, 2);
767 anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index]->type_entry);
768 break;
769 }
770
771 jw_object_field(jw, "name");
772 jw_string(jw, buf_ptr(&ty->name));
773
774 jw_object_field(jw, "src");
775 anal_dump_node_ref(ctx, ty->data.structure.decl_node);
776
777 {
778 jw_object_field(jw, "pubDecls");
779 jw_begin_array(jw);
780
781 ScopeDecls *decls_scope = ty->data.structure.decls_scope;
782 auto it = decls_scope->decl_table.entry_iterator();
783 for (;;) {
784 auto *entry = it.next();
785 if (!entry)
786 break;
787
788 Tld *tld = entry->value;
789 if (tld->visib_mod == VisibModPub) {
790 jw_array_elem(jw);
791 anal_dump_decl_ref(ctx, tld);
792 }
793 }
794 jw_end_array(jw);
795 }
796
797 {
798 jw_object_field(jw, "privDecls");
799 jw_begin_array(jw);
800
801 ScopeDecls *decls_scope = ty->data.structure.decls_scope;
802 auto it = decls_scope->decl_table.entry_iterator();
803 for (;;) {
804 auto *entry = it.next();
805 if (!entry)
806 break;
807
808 Tld *tld = entry->value;
809 if (tld->visib_mod == VisibModPrivate) {
810 jw_array_elem(jw);
811 anal_dump_decl_ref(ctx, tld);
812 }
813 }
814 jw_end_array(jw);
815 }
816
817 if (ty->data.structure.src_field_count != 0) {
818 jw_object_field(jw, "fields");
819 jw_begin_array(jw);
820
821 for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
822 jw_array_elem(jw);
823 anal_dump_type_ref(ctx, ty->data.structure.fields[i]->type_entry);
824 }
825 jw_end_array(jw);
826 }
827
828 if (ty->data.structure.root_struct != nullptr) {
829 Buf *path_buf = ty->data.structure.root_struct->path;
830
831 jw_object_field(jw, "file");
832 anal_dump_file_ref(ctx, path_buf);
833 }
834 break;
835 }
836 case ZigTypeIdUnion: {
837 jw_object_field(jw, "name");
838 jw_string(jw, buf_ptr(&ty->name));
839
840 jw_object_field(jw, "src");
841 anal_dump_node_ref(ctx, ty->data.unionation.decl_node);
842
843 {
844 jw_object_field(jw, "pubDecls");
845 jw_begin_array(jw);
846
847 ScopeDecls *decls_scope = ty->data.unionation.decls_scope;
848 auto it = decls_scope->decl_table.entry_iterator();
849 for (;;) {
850 auto *entry = it.next();
851 if (!entry)
852 break;
853
854 Tld *tld = entry->value;
855 if (tld->visib_mod == VisibModPub) {
856 jw_array_elem(jw);
857 anal_dump_decl_ref(ctx, tld);
858 }
859 }
860 jw_end_array(jw);
861 }
862
863 {
864 jw_object_field(jw, "privDecls");
865 jw_begin_array(jw);
866
867 ScopeDecls *decls_scope = ty->data.unionation.decls_scope;
868 auto it = decls_scope->decl_table.entry_iterator();
869 for (;;) {
870 auto *entry = it.next();
871 if (!entry)
872 break;
873
874 Tld *tld = entry->value;
875 if (tld->visib_mod == VisibModPrivate) {
876 jw_array_elem(jw);
877 anal_dump_decl_ref(ctx, tld);
878 }
879 }
880 jw_end_array(jw);
881 }
882
883 if (ty->data.unionation.src_field_count != 0) {
884 jw_object_field(jw, "fields");
885 jw_begin_array(jw);
886
887 for(size_t i = 0; i < ty->data.unionation.src_field_count; i += 1) {
888 jw_array_elem(jw);
889 anal_dump_type_ref(ctx, ty->data.unionation.fields[i].type_entry);
890 }
891 jw_end_array(jw);
892 }
893 break;
894 }
895 case ZigTypeIdEnum: {
896 jw_object_field(jw, "name");
897 jw_string(jw, buf_ptr(&ty->name));
898
899 jw_object_field(jw, "src");
900 anal_dump_node_ref(ctx, ty->data.enumeration.decl_node);
901
902 {
903 jw_object_field(jw, "pubDecls");
904 jw_begin_array(jw);
905
906 ScopeDecls *decls_scope = ty->data.enumeration.decls_scope;
907 auto it = decls_scope->decl_table.entry_iterator();
908 for (;;) {
909 auto *entry = it.next();
910 if (!entry)
911 break;
912
913 Tld *tld = entry->value;
914 if (tld->visib_mod == VisibModPub) {
915 jw_array_elem(jw);
916 anal_dump_decl_ref(ctx, tld);
917 }
918 }
919 jw_end_array(jw);
920 }
921
922 {
923 jw_object_field(jw, "privDecls");
924 jw_begin_array(jw);
925
926 ScopeDecls *decls_scope = ty->data.enumeration.decls_scope;
927 auto it = decls_scope->decl_table.entry_iterator();
928 for (;;) {
929 auto *entry = it.next();
930 if (!entry)
931 break;
932
933 Tld *tld = entry->value;
934 if (tld->visib_mod == VisibModPrivate) {
935 jw_array_elem(jw);
936 anal_dump_decl_ref(ctx, tld);
937 }
938 }
939 jw_end_array(jw);
940 }
941
942 if (ty->data.enumeration.src_field_count != 0) {
943 jw_object_field(jw, "fields");
944 jw_begin_array(jw);
945
946 for(size_t i = 0; i < ty->data.enumeration.src_field_count; i += 1) {
947 jw_array_elem(jw);
948 jw_bigint(jw, &ty->data.enumeration.fields[i].value);
949 }
950 jw_end_array(jw);
951 }
952 break;
953 }
954 case ZigTypeIdFloat: {
955 jw_object_field(jw, "bits");
956 jw_int(jw, ty->data.floating.bit_count);
957 break;
958 }
959 case ZigTypeIdInt: {
960 if (ty->data.integral.is_signed) {
961 jw_object_field(jw, "i");
962 } else {
963 jw_object_field(jw, "u");
964 }
965 jw_int(jw, ty->data.integral.bit_count);
966 break;
967 }
968 case ZigTypeIdFn: {
969 jw_object_field(jw, "name");
970 jw_string(jw, buf_ptr(&ty->name));
971
972 jw_object_field(jw, "generic");
973 jw_bool(jw, ty->data.fn.is_generic);
974
975 if (ty->data.fn.fn_type_id.return_type != nullptr) {
976 jw_object_field(jw, "ret");
977 anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type);
978 }
979
980 if (ty->data.fn.fn_type_id.param_count != 0) {
981 jw_object_field(jw, "args");
982 jw_begin_array(jw);
983 for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) {
984 jw_array_elem(jw);
985 if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) {
986 anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type);
987 } else {
988 jw_null(jw);
989 }
990 }
991 jw_end_array(jw);
992 }
993 break;
994 }
995 case ZigTypeIdOptional: {
996 jw_object_field(jw, "child");
997 anal_dump_type_ref(ctx, ty->data.maybe.child_type);
998 break;
999 }
1000 case ZigTypeIdPointer: {
1001 switch (ty->data.pointer.ptr_len) {
1002 case PtrLenSingle:
1003 break;
1004 case PtrLenUnknown:
1005 jw_object_field(jw, "len");
1006 jw_int(jw, 1);
1007 break;
1008 case PtrLenC:
1009 jw_object_field(jw, "len");
1010 jw_int(jw, 3);
1011 break;
1012 }
1013 anal_dump_pointer_attrs(ctx, ty);
1014 break;
1015 }
1016 case ZigTypeIdErrorSet: {
1017 if (type_is_global_error_set(ty)) {
1018 break;
1019 }
1020 jw_object_field(jw, "name");
1021 jw_string(jw, buf_ptr(&ty->name));
1022
1023 if (ty->data.error_set.infer_fn != nullptr) {
1024 jw_object_field(jw, "fn");
1025 anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn);
1026 }
1027 jw_object_field(jw, "errors");
1028 jw_begin_array(jw);
1029 for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) {
1030 jw_array_elem(jw);
1031 ErrorTableEntry *err = ty->data.error_set.errors[i];
1032 anal_dump_err_ref(ctx, err);
1033 }
1034 jw_end_array(jw);
1035 break;
1036 }
1037 case ZigTypeIdErrorUnion: {
1038 jw_object_field(jw, "err");
1039 anal_dump_type_ref(ctx, ty->data.error_union.err_set_type);
1040
1041 jw_object_field(jw, "payload");
1042 anal_dump_type_ref(ctx, ty->data.error_union.payload_type);
1043
1044 break;
1045 }
1046 case ZigTypeIdArray: {
1047 jw_object_field(jw, "len");
1048 jw_int(jw, ty->data.array.len);
1049
1050 jw_object_field(jw, "elem");
1051 anal_dump_type_ref(ctx, ty->data.array.child_type);
1052 break;
1053 }
1054 case ZigTypeIdVector: {
1055 jw_object_field(jw, "len");
1056 jw_int(jw, ty->data.vector.len);
1057
1058 jw_object_field(jw, "elem");
1059 anal_dump_type_ref(ctx, ty->data.vector.elem_type);
1060 break;
1061 }
1062 case ZigTypeIdAnyFrame: {
1063 if (ty->data.any_frame.result_type != nullptr) {
1064 jw_object_field(jw, "result");
1065 anal_dump_type_ref(ctx, ty->data.any_frame.result_type);
1066 }
1067 break;
1068 }
1069 case ZigTypeIdFnFrame: {
1070 jw_object_field(jw, "fnName");
1071 jw_string(jw, buf_ptr(&ty->data.frame.fn->symbol_name));
1072
1073 jw_object_field(jw, "fn");
1074 anal_dump_fn_ref(ctx, ty->data.frame.fn);
1075 break;
1076 }
1077 case ZigTypeIdInvalid:
1078 zig_unreachable();
1079 default:
1080 jw_object_field(jw, "name");
1081 jw_string(jw, buf_ptr(&ty->name));
1082 break;
1083 }
1084 jw_end_object(jw);
1085}
1086
1087static Buf *collect_doc_comments(RootStruct *root_struct, TokenIndex first_token) {
1088 if (first_token == 0)
1089 return nullptr;
1090
1091 TokenId *token_ids = root_struct->token_ids;
1092 TokenLoc *token_locs = root_struct->token_locs;
1093 Buf *str = buf_alloc();
1094 const char *source = buf_ptr(root_struct->source_code);
1095 TokenIndex doc_token = first_token;
1096 for (;token_ids[doc_token] == TokenIdDocComment; doc_token += 1) {
1097 // chops off '///' but leaves '\n'
1098 uint32_t start_pos = token_locs[doc_token].offset;
1099 uint32_t token_len = 0;
1100 while (source[start_pos + token_len] != '\n' &&
1101 source[start_pos + token_len] != 0)
1102 {
1103 token_len += 1;
1104 }
1105 buf_append_mem(str, source + start_pos + 3, token_len - 3);
1106 }
1107 return str;
1108}
1109
1110static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
1111 JsonWriter *jw = &ctx->jw;
1112
1113 jw_begin_object(jw);
1114
1115 jw_object_field(jw, "file");
1116 RootStruct *root_struct = node->owner->data.structure.root_struct;
1117 anal_dump_file_ref(ctx, root_struct->path);
1118
1119 jw_object_field(jw, "line");
1120 jw_int(jw, root_struct->token_locs[node->main_token].line);
1121
1122 jw_object_field(jw, "col");
1123 jw_int(jw, root_struct->token_locs[node->main_token].column);
1124
1125 const Buf *doc_comments_buf = nullptr;
1126 const Buf *name_buf = nullptr;
1127 const ZigList<AstNode *> *field_nodes = nullptr;
1128 bool is_var_args = false;
1129 bool is_noalias = false;
1130 bool is_comptime = false;
1131
1132 switch (node->type) {
1133 case NodeTypeParamDecl:
1134 doc_comments_buf = collect_doc_comments(root_struct, node->data.param_decl.doc_comments);
1135 name_buf = node->data.param_decl.name;
1136 is_var_args = node->data.param_decl.is_var_args;
1137 is_noalias = node->data.param_decl.is_noalias;
1138 is_comptime = node->data.param_decl.is_comptime;
1139 break;
1140 case NodeTypeFnProto:
1141 doc_comments_buf = collect_doc_comments(root_struct, node->data.fn_proto.doc_comments);
1142 field_nodes = &node->data.fn_proto.params;
1143 is_var_args = node->data.fn_proto.is_var_args;
1144 break;
1145 case NodeTypeVariableDeclaration:
1146 doc_comments_buf = collect_doc_comments(root_struct, node->data.variable_declaration.doc_comments);
1147 break;
1148 case NodeTypeErrorSetField:
1149 doc_comments_buf = collect_doc_comments(root_struct, node->data.err_set_field.doc_comments);
1150 break;
1151 case NodeTypeStructField:
1152 doc_comments_buf = collect_doc_comments(root_struct, node->data.struct_field.doc_comments);
1153 name_buf = node->data.struct_field.name;
1154 break;
1155 case NodeTypeContainerDecl:
1156 field_nodes = &node->data.container_decl.fields;
1157 doc_comments_buf = collect_doc_comments(root_struct, node->data.container_decl.doc_comments);
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {
1164 jw_object_field(jw, "docs");
1165 jw_string(jw, buf_ptr(doc_comments_buf));
1166 }
1167
1168 if (name_buf != nullptr) {
1169 jw_object_field(jw, "name");
1170 jw_string(jw, buf_ptr(name_buf));
1171 }
1172
1173 if (field_nodes != nullptr) {
1174 jw_object_field(jw, "fields");
1175 jw_begin_array(jw);
1176 for (size_t i = 0; i < field_nodes->length; i += 1) {
1177 jw_array_elem(jw);
1178 anal_dump_node_ref(ctx, field_nodes->at(i));
1179 }
1180 jw_end_array(jw);
1181 }
1182
1183 if (is_var_args) {
1184 jw_object_field(jw, "varArgs");
1185 jw_bool(jw, true);
1186 }
1187
1188 if (is_comptime) {
1189 jw_object_field(jw, "comptime");
1190 jw_bool(jw, true);
1191 }
1192
1193 if (is_noalias) {
1194 jw_object_field(jw, "noalias");
1195 jw_bool(jw, true);
1196 }
1197
1198 jw_end_object(jw);
1199}
1200
1201static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) {
1202 JsonWriter *jw = &ctx->jw;
1203
1204 jw_begin_object(jw);
1205
1206 jw_object_field(jw, "src");
1207 anal_dump_node_ref(ctx, err->decl_node);
1208
1209 jw_object_field(jw, "name");
1210 jw_string(jw, buf_ptr(&err->name));
1211
1212 jw_end_object(jw);
1213}
1214
1215static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) {
1216 JsonWriter *jw = &ctx->jw;
1217
1218 jw_begin_object(jw);
1219
1220 jw_object_field(jw, "src");
1221 anal_dump_node_ref(ctx, fn->proto_node);
1222
1223 jw_object_field(jw, "type");
1224 anal_dump_type_ref(ctx, fn->type_entry);
1225
1226 auto entry = ctx->fn_decl_map.maybe_get(fn);
1227 if (entry != nullptr) {
1228 jw_object_field(jw, "decl");
1229 jw_int(jw, entry->value);
1230 }
1231
1232 jw_end_object(jw);
1233}
1234
1235void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) {
1236 AnalDumpCtx ctx = {};
1237 ctx.g = g;
1238 JsonWriter *jw = &ctx.jw;
1239 jw_init(jw, f, one_indent, nl);
1240 ctx.type_map.init(16);
1241 ctx.pkg_map.init(16);
1242 ctx.file_map.init(16);
1243 ctx.decl_map.init(16);
1244 ctx.node_map.init(16);
1245 ctx.fn_map.init(16);
1246 ctx.fn_decl_map.init(16);
1247 ctx.err_map.init(16);
1248
1249 jw_begin_object(jw);
1250
1251 jw_object_field(jw, "typeKinds");
1252 jw_begin_array(jw);
1253 for (size_t i = 0; i < type_id_len(); i += 1) {
1254 jw_array_elem(jw);
1255 jw_string(jw, type_id_name(type_id_at_index(i)));
1256 }
1257 jw_end_array(jw);
1258
1259 jw_object_field(jw, "params");
1260 jw_begin_object(jw);
1261 {
1262 jw_object_field(jw, "zigVersion");
1263 jw_string(jw, stage2_version_string());
1264
1265 jw_object_field(jw, "builds");
1266 jw_begin_array(jw);
1267 jw_array_elem(jw);
1268 jw_begin_object(jw);
1269 jw_object_field(jw, "target");
1270 Buf triple_buf = BUF_INIT;
1271 target_triple_zig(&triple_buf, g->zig_target);
1272 jw_string(jw, buf_ptr(&triple_buf));
1273 jw_end_object(jw);
1274 jw_end_array(jw);
1275
1276 jw_object_field(jw, "rootName");
1277 jw_string(jw, buf_ptr(g->root_out_name));
1278 }
1279 jw_end_object(jw);
1280
1281 jw_object_field(jw, "rootPkg");
1282 anal_dump_pkg_ref(&ctx, g->main_pkg);
1283
1284 // FIXME: Remove this ugly workaround.
1285 // Right now the code in docs/main.js relies on the root of the main package being itself.
1286 g->main_pkg->package_table.put(buf_create_from_str("root"), g->main_pkg);
1287
1288 // Poke the functions
1289 for (size_t i = 0; i < g->fn_defs.length; i += 1) {
1290 ZigFn *fn = g->fn_defs.at(i);
1291 (void)anal_dump_get_fn_id(&ctx, fn);
1292 }
1293
1294 jw_object_field(jw, "calls");
1295 jw_begin_array(jw);
1296 {
1297 ZigList<ZigVar *> var_stack = {};
1298
1299 auto it = g->memoized_fn_eval_table.entry_iterator();
1300 for (;;) {
1301 auto *entry = it.next();
1302 if (!entry)
1303 break;
1304
1305 var_stack.resize(0);
1306 ZigFn *fn = nullptr;
1307
1308 Scope *scope = entry->key;
1309 while (scope != nullptr) {
1310 if (scope->id == ScopeIdVarDecl) {
1311 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
1312 var_stack.append(var);
1313 } else if (scope->id == ScopeIdFnDef) {
1314 fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;
1315 break;
1316 }
1317 scope = scope->parent;
1318 }
1319 ZigValue *result = entry->value;
1320
1321 assert(fn != nullptr);
1322
1323 jw_array_elem(jw);
1324 jw_begin_object(jw);
1325
1326 jw_object_field(jw, "fn");
1327 anal_dump_fn_ref(&ctx, fn);
1328
1329 jw_object_field(jw, "result");
1330 {
1331 jw_begin_object(jw);
1332
1333 jw_object_field(jw, "type");
1334 anal_dump_type_ref(&ctx, result->type);
1335
1336 jw_object_field(jw, "value");
1337 anal_dump_value(&ctx, scope->source_node, result->type, result);
1338
1339 jw_end_object(jw);
1340 }
1341
1342 if (var_stack.length != 0) {
1343 jw_object_field(jw, "args");
1344 jw_begin_array(jw);
1345
1346 while (var_stack.length != 0) {
1347 ZigVar *var = var_stack.pop();
1348
1349 jw_array_elem(jw);
1350 jw_begin_object(jw);
1351
1352 jw_object_field(jw, "type");
1353 anal_dump_type_ref(&ctx, var->var_type);
1354
1355 jw_object_field(jw, "value");
1356 anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value);
1357
1358 jw_end_object(jw);
1359 }
1360 jw_end_array(jw);
1361 }
1362
1363 jw_end_object(jw);
1364 }
1365
1366 var_stack.deinit();
1367 }
1368 jw_end_array(jw);
1369
1370 jw_object_field(jw, "packages");
1371 jw_begin_array(jw);
1372 for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) {
1373 anal_dump_pkg(&ctx, ctx.pkg_list.at(i));
1374 }
1375 jw_end_array(jw);
1376
1377 jw_object_field(jw, "types");
1378 jw_begin_array(jw);
1379
1380 for (uint32_t i = 0; i < ctx.type_list.length; i += 1) {
1381 ZigType *ty = ctx.type_list.at(i);
1382 anal_dump_type(&ctx, ty);
1383 }
1384 jw_end_array(jw);
1385
1386 jw_object_field(jw, "decls");
1387 jw_begin_array(jw);
1388 for (uint32_t i = 0; i < ctx.decl_list.length; i += 1) {
1389 Tld *decl = ctx.decl_list.at(i);
1390 anal_dump_decl(&ctx, decl);
1391 }
1392 jw_end_array(jw);
1393
1394 jw_object_field(jw, "fns");
1395 jw_begin_array(jw);
1396 for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) {
1397 ZigFn *fn = ctx.fn_list.at(i);
1398 jw_array_elem(jw);
1399 anal_dump_fn(&ctx, fn);
1400 }
1401 jw_end_array(jw);
1402
1403 jw_object_field(jw, "errors");
1404 jw_begin_array(jw);
1405 for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {
1406 const ErrorTableEntry *err = ctx.err_list.at(i);
1407 jw_array_elem(jw);
1408 anal_dump_err(&ctx, err);
1409 }
1410 jw_end_array(jw);
1411
1412 jw_object_field(jw, "astNodes");
1413 jw_begin_array(jw);
1414 for (uint32_t i = 0; i < ctx.node_list.length; i += 1) {
1415 const AstNode *node = ctx.node_list.at(i);
1416 jw_array_elem(jw);
1417 anal_dump_node(&ctx, node);
1418 }
1419 jw_end_array(jw);
1420
1421 jw_object_field(jw, "files");
1422 jw_begin_array(jw);
1423 for (uint32_t i = 0; i < ctx.file_list.length; i += 1) {
1424 Buf *file = ctx.file_list.at(i);
1425 jw_array_elem(jw);
1426 anal_dump_file(&ctx, file);
1427 }
1428 jw_end_array(jw);
1429
1430 jw_end_object(jw);
1431}
src/stage1/dump_analysis.hpp deleted-17
......@@ -1,17 +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_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, const char *one_indent, const char *nl);
16
17#endif
src/stage1/stage1.cpp-2
......@@ -74,8 +74,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
7474 buf_init_from_mem(&g->asm_file_output_path, stage1->emit_asm_ptr, stage1->emit_asm_len);
7575 buf_init_from_mem(&g->llvm_ir_file_output_path, stage1->emit_llvm_ir_ptr, stage1->emit_llvm_ir_len);
7676 buf_init_from_mem(&g->bitcode_file_output_path, stage1->emit_bitcode_ptr, stage1->emit_bitcode_len);
77 buf_init_from_mem(&g->analysis_json_output_path, stage1->emit_analysis_json_ptr, stage1->emit_analysis_json_len);
78 buf_init_from_mem(&g->docs_output_path, stage1->emit_docs_ptr, stage1->emit_docs_len);
7977
8078 if (stage1->builtin_zig_path_len != 0) {
8179 g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);
src/stage1/stage1.h-6
......@@ -161,12 +161,6 @@ struct ZigStage1 {
161161 const char *emit_bitcode_ptr;
162162 size_t emit_bitcode_len;
163163
164 const char *emit_analysis_json_ptr;
165 size_t emit_analysis_json_len;
166
167 const char *emit_docs_ptr;
168 size_t emit_docs_len;
169
170164 const char *builtin_zig_path_ptr;
171165 size_t builtin_zig_path_len;
172166
tools/merge_anal_dumps.zig deleted-454
......@@ -1,454 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const json = std.json;
4const mem = std.mem;
5const fieldIndex = std.meta.fieldIndex;
6const TypeId = builtin.TypeId;
7
8pub fn main() anyerror!void {
9 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena.deinit();
11
12 const allocator = arena.allocator();
13
14 const args = try std.process.argsAlloc(allocator);
15
16 var parser: json.Parser = undefined;
17 var dump = Dump.init(allocator);
18 for (args[1..]) |arg| {
19 parser = json.Parser.init(allocator, false);
20 const json_text = try std.fs.cwd().readFileAlloc(allocator, arg, std.math.maxInt(usize));
21 const tree = try parser.parse(json_text);
22 try dump.mergeJson(tree.root);
23 }
24
25 const stdout = try std.io.getStdOut();
26 try dump.render(stdout.writer());
27}
28
29/// AST source node
30const Node = struct {
31 file: usize,
32 line: usize,
33 col: usize,
34 fields: []usize,
35
36 fn hash(n: Node) u64 {
37 var hasher = std.hash.Wyhash.init(0);
38 std.hash.autoHash(&hasher, n.file);
39 std.hash.autoHash(&hasher, n.line);
40 std.hash.autoHash(&hasher, n.col);
41 return hasher.final();
42 }
43
44 fn eql(a: Node, b: Node) bool {
45 return a.file == b.file and
46 a.line == b.line and
47 a.col == b.col;
48 }
49};
50
51const Error = struct {
52 src: usize,
53 name: []const u8,
54
55 fn hash(n: Error) u64 {
56 var hasher = std.hash.Wyhash.init(0);
57 std.hash.autoHash(&hasher, n.src);
58 return hasher.final();
59 }
60
61 fn eql(a: Error, b: Error) bool {
62 return a.src == b.src;
63 }
64};
65
66const simple_types = [_][]const u8{
67 "Type",
68 "Void",
69 "Bool",
70 "NoReturn",
71 "ComptimeFloat",
72 "ComptimeInt",
73 "Undefined",
74 "Null",
75 "AnyFrame",
76 "EnumLiteral",
77};
78
79const Type = union(builtin.TypeId) {
80 Type,
81 Void,
82 Bool,
83 NoReturn,
84 ComptimeFloat,
85 ComptimeInt,
86 Undefined,
87 Null,
88 AnyFrame,
89 EnumLiteral,
90
91 Int: Int,
92 Float: usize, // bits
93
94 Vector: Array,
95 Optional: usize, // payload type index
96 Pointer: Pointer,
97 Array: Array,
98
99 Struct, // TODO
100 ErrorUnion, // TODO
101 ErrorSet, // TODO
102 Enum, // TODO
103 Union, // TODO
104 Fn, // TODO
105 BoundFn, // TODO
106 Opaque, // TODO
107 Frame, // TODO
108
109 const Int = struct {
110 bits: usize,
111 signed: bool,
112 };
113
114 const Pointer = struct {
115 elem: usize,
116 alignment: usize,
117 is_const: bool,
118 is_volatile: bool,
119 allow_zero: bool,
120 host_int_bytes: usize,
121 bit_offset_in_host: usize,
122 };
123
124 const Array = struct {
125 elem: usize,
126 len: usize,
127 };
128
129 fn hash(t: Type) u64 {
130 var hasher = std.hash.Wyhash.init(0);
131 std.hash.autoHash(&hasher, t);
132 return hasher.final();
133 }
134
135 fn eql(a: Type, b: Type) bool {
136 return std.meta.eql(a, b);
137 }
138};
139
140const Dump = struct {
141 zig_id: ?[]const u8 = null,
142 zig_version: ?[]const u8 = null,
143 root_name: ?[]const u8 = null,
144 targets: std.ArrayList([]const u8),
145
146 file_list: std.ArrayList([]const u8),
147 file_map: FileMap,
148
149 node_list: std.ArrayList(Node),
150 node_map: NodeMap,
151
152 error_list: std.ArrayList(Error),
153 error_map: ErrorMap,
154
155 type_list: std.ArrayList(Type),
156 type_map: TypeMap,
157
158 const FileMap = std.StringHashMap(usize);
159 const NodeMap = std.HashMap(Node, usize, Node.hash, Node.eql, 80);
160 const ErrorMap = std.HashMap(Error, usize, Error.hash, Error.eql, 80);
161 const TypeMap = std.HashMap(Type, usize, Type.hash, Type.eql, 80);
162
163 fn init(allocator: mem.Allocator) Dump {
164 return Dump{
165 .targets = std.ArrayList([]const u8).init(allocator),
166 .file_list = std.ArrayList([]const u8).init(allocator),
167 .file_map = FileMap.init(allocator),
168 .node_list = std.ArrayList(Node).init(allocator),
169 .node_map = NodeMap.init(allocator),
170 .error_list = std.ArrayList(Error).init(allocator),
171 .error_map = ErrorMap.init(allocator),
172 .type_list = std.ArrayList(Type).init(allocator),
173 .type_map = TypeMap.init(allocator),
174 };
175 }
176
177 fn mergeJson(self: *Dump, root: json.Value) !void {
178 const params = &root.Object.get("params").?.value.Object;
179 const zig_id = params.get("zigId").?.value.String;
180 const zig_version = params.get("zigVersion").?.value.String;
181 const root_name = params.get("rootName").?.value.String;
182 try mergeSameStrings(&self.zig_id, zig_id);
183 try mergeSameStrings(&self.zig_version, zig_version);
184 try mergeSameStrings(&self.root_name, root_name);
185
186 for (params.get("builds").?.value.Array.items) |json_build| {
187 const target = json_build.Object.get("target").?.value.String;
188 try self.targets.append(target);
189 }
190
191 // Merge files. If the string matches, it's the same file.
192 const other_files = root.Object.get("files").?.value.Array.items;
193 var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a());
194 for (other_files) |other_file, i| {
195 const gop = try self.file_map.getOrPut(other_file.String);
196 if (!gop.found_existing) {
197 gop.kv.value = self.file_list.items.len;
198 try self.file_list.append(other_file.String);
199 }
200 try other_file_to_mine.putNoClobber(i, gop.kv.value);
201 }
202
203 // Merge AST nodes. If the file id, line, and column all match, it's the same AST node.
204 const other_ast_nodes = root.Object.get("astNodes").?.value.Array.items;
205 var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a());
206 for (other_ast_nodes) |other_ast_node_json, i| {
207 const other_file_id = jsonObjInt(other_ast_node_json, "file");
208 const other_node = Node{
209 .line = jsonObjInt(other_ast_node_json, "line"),
210 .col = jsonObjInt(other_ast_node_json, "col"),
211 .file = other_file_to_mine.getValue(other_file_id).?,
212 .fields = ([*]usize)(undefined)[0..0],
213 };
214 const gop = try self.node_map.getOrPut(other_node);
215 if (!gop.found_existing) {
216 gop.kv.value = self.node_list.items.len;
217 try self.node_list.append(other_node);
218 }
219 try other_ast_node_to_mine.putNoClobber(i, gop.kv.value);
220 }
221 // convert fields lists
222 for (other_ast_nodes) |other_ast_node_json, i| {
223 const my_node_index = other_ast_node_to_mine.get(i).?.value;
224 const my_node = &self.node_list.items[my_node_index];
225 if (other_ast_node_json.Object.get("fields")) |fields_json_kv| {
226 const other_fields = fields_json_kv.value.Array.items;
227 my_node.fields = try self.a().alloc(usize, other_fields.len);
228 for (other_fields) |other_field_index, field_i| {
229 const other_index = @intCast(usize, other_field_index.Integer);
230 my_node.fields[field_i] = other_ast_node_to_mine.get(other_index).?.value;
231 }
232 }
233 }
234
235 // Merge errors. If the AST Node matches, it's the same error value.
236 const other_errors = root.Object.get("errors").?.value.Array.items;
237 var other_error_to_mine = std.AutoHashMap(usize, usize).init(self.a());
238 for (other_errors) |other_error_json, i| {
239 const other_src_id = jsonObjInt(other_error_json, "src");
240 const other_error = Error{
241 .src = other_ast_node_to_mine.getValue(other_src_id).?,
242 .name = other_error_json.Object.get("name").?.value.String,
243 };
244 const gop = try self.error_map.getOrPut(other_error);
245 if (!gop.found_existing) {
246 gop.kv.value = self.error_list.items.len;
247 try self.error_list.append(other_error);
248 }
249 try other_error_to_mine.putNoClobber(i, gop.kv.value);
250 }
251
252 // Merge types. Now it starts to get advanced.
253 // First we identify all the simple types and merge those.
254 // Example: void, type, noreturn
255 // We can also do integers and floats.
256 const other_types = root.Object.get("types").?.value.Array.items;
257 var other_types_to_mine = std.AutoHashMap(usize, usize).init(self.a());
258 for (other_types) |other_type_json, i| {
259 const type_kind = jsonObjInt(other_type_json, "kind");
260 switch (type_kind) {
261 fieldIndex(TypeId, "Int").? => {
262 var signed: bool = undefined;
263 var bits: usize = undefined;
264 if (other_type_json.Object.get("i")) |kv| {
265 signed = true;
266 bits = @intCast(usize, kv.value.Integer);
267 } else if (other_type_json.Object.get("u")) |kv| {
268 signed = false;
269 bits = @intCast(usize, kv.value.Integer);
270 } else {
271 unreachable;
272 }
273 const other_type = Type{
274 .Int = Type.Int{
275 .bits = bits,
276 .signed = signed,
277 },
278 };
279 try self.mergeOtherType(other_type, i, &other_types_to_mine);
280 },
281 fieldIndex(TypeId, "Float").? => {
282 const other_type = Type{
283 .Float = jsonObjInt(other_type_json, "bits"),
284 };
285 try self.mergeOtherType(other_type, i, &other_types_to_mine);
286 },
287 else => {},
288 }
289
290 inline for (simple_types) |simple_type_name| {
291 if (type_kind == std.meta.fieldIndex(builtin.TypeId, simple_type_name).?) {
292 const other_type = @unionInit(Type, simple_type_name, {});
293 try self.mergeOtherType(other_type, i, &other_types_to_mine);
294 }
295 }
296 }
297 }
298
299 fn mergeOtherType(
300 self: *Dump,
301 other_type: Type,
302 other_type_index: usize,
303 other_types_to_mine: *std.AutoHashMap(usize, usize),
304 ) !void {
305 const gop = try self.type_map.getOrPut(other_type);
306 if (!gop.found_existing) {
307 gop.kv.value = self.type_list.items.len;
308 try self.type_list.append(other_type);
309 }
310 try other_types_to_mine.putNoClobber(other_type_index, gop.kv.value);
311 }
312
313 fn render(self: *Dump, stream: anytype) !void {
314 var jw = json.WriteStream(@TypeOf(stream).Child, 10).init(stream);
315 try jw.beginObject();
316
317 try jw.objectField("typeKinds");
318 try jw.beginArray();
319 inline for (@typeInfo(builtin.TypeId).Enum.fields) |field| {
320 try jw.arrayElem();
321 try jw.emitString(field.name);
322 }
323 try jw.endArray();
324
325 try jw.objectField("params");
326 try jw.beginObject();
327
328 try jw.objectField("zigId");
329 try jw.emitString(self.zig_id.?);
330
331 try jw.objectField("zigVersion");
332 try jw.emitString(self.zig_version.?);
333
334 try jw.objectField("rootName");
335 try jw.emitString(self.root_name.?);
336
337 try jw.objectField("builds");
338 try jw.beginArray();
339 for (self.targets.items) |target| {
340 try jw.arrayElem();
341 try jw.beginObject();
342 try jw.objectField("target");
343 try jw.emitString(target);
344 try jw.endObject();
345 }
346 try jw.endArray();
347
348 try jw.endObject();
349
350 try jw.objectField("types");
351 try jw.beginArray();
352 for (self.type_list.items) |t| {
353 try jw.arrayElem();
354 try jw.beginObject();
355
356 try jw.objectField("kind");
357 try jw.emitNumber(@enumToInt(builtin.TypeId(t)));
358
359 switch (t) {
360 .Int => |int| {
361 if (int.signed) {
362 try jw.objectField("i");
363 } else {
364 try jw.objectField("u");
365 }
366 try jw.emitNumber(int.bits);
367 },
368 .Float => |bits| {
369 try jw.objectField("bits");
370 try jw.emitNumber(bits);
371 },
372
373 else => {},
374 }
375
376 try jw.endObject();
377 }
378 try jw.endArray();
379
380 try jw.objectField("errors");
381 try jw.beginArray();
382 for (self.error_list.items) |zig_error| {
383 try jw.arrayElem();
384 try jw.beginObject();
385
386 try jw.objectField("src");
387 try jw.emitNumber(zig_error.src);
388
389 try jw.objectField("name");
390 try jw.emitString(zig_error.name);
391
392 try jw.endObject();
393 }
394 try jw.endArray();
395
396 try jw.objectField("astNodes");
397 try jw.beginArray();
398 for (self.node_list.items) |node| {
399 try jw.arrayElem();
400 try jw.beginObject();
401
402 try jw.objectField("file");
403 try jw.emitNumber(node.file);
404
405 try jw.objectField("line");
406 try jw.emitNumber(node.line);
407
408 try jw.objectField("col");
409 try jw.emitNumber(node.col);
410
411 if (node.fields.len != 0) {
412 try jw.objectField("fields");
413 try jw.beginArray();
414
415 for (node.fields) |field_node_index| {
416 try jw.arrayElem();
417 try jw.emitNumber(field_node_index);
418 }
419 try jw.endArray();
420 }
421
422 try jw.endObject();
423 }
424 try jw.endArray();
425
426 try jw.objectField("files");
427 try jw.beginArray();
428 for (self.file_list.items) |file| {
429 try jw.arrayElem();
430 try jw.emitString(file);
431 }
432 try jw.endArray();
433
434 try jw.endObject();
435 }
436
437 fn a(self: Dump) mem.Allocator {
438 return self.targets.allocator;
439 }
440
441 fn mergeSameStrings(opt_dest: *?[]const u8, src: []const u8) !void {
442 if (opt_dest.*) |dest| {
443 if (!mem.eql(u8, dest, src))
444 return error.MismatchedDumps;
445 } else {
446 opt_dest.* = src;
447 }
448 }
449};
450
451fn jsonObjInt(json_val: json.Value, field: []const u8) usize {
452 const uncasted = json_val.Object.get(field).?.value.Integer;
453 return @intCast(usize, uncasted);
454}