From 652e13e7c06db318d88a93db24a8fb2c2f8d249b Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 28 Jan 2022 22:50:03 +0100 Subject: autodoc: init work --- src/Compilation.zig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 659fa5e972..cadc665598 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -34,6 +34,7 @@ const ThreadPool = @import("ThreadPool.zig"); const WaitGroup = @import("WaitGroup.zig"); const libtsan = @import("libtsan.zig"); const Zir = @import("Zir.zig"); +const Autodoc = @import("Autodoc.zig"); const Color = @import("main.zig").Color; /// General-purpose allocator. Used for both temporary and long-term storage. @@ -2866,6 +2867,13 @@ pub fn performAllTheWork( } } + if (comp.emit_docs) |doc_location| { + if (comp.bin_file.options.module) |module| { + var autodoc = Autodoc.init(module, doc_location); + try autodoc.generateZirData(); + } + } + if (!use_stage1) { const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls"); defer outdated_and_deleted_decls_frame.end(); -- cgit v1.2.3 From 0135d2271600db92d1ae727b2a5935d0fc711c13 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sun, 30 Jan 2022 19:12:56 +0100 Subject: autodocs: add support for indirect decl references --- lib/docs/main.js | 74 ++++++++++++++++++++++++++++++++++------------------- src/Autodoc.zig | 59 ++++++++++++++++++++++++++++++++++-------- src/Compilation.zig | 1 + 3 files changed, 97 insertions(+), 37 deletions(-) (limited to 'src/Compilation.zig') diff --git a/lib/docs/main.js b/lib/docs/main.js index 15e0d7567e..44f003a569 100644 --- a/lib/docs/main.js +++ b/lib/docs/main.js @@ -147,10 +147,10 @@ curNav.pkgObjs.push(pkg); } - var decl = zigAnalysis.types[pkg.main]; - curNav.declObjs = [decl]; + var currentType = zigAnalysis.types[pkg.main]; + curNav.declObjs = [currentType]; for (var i = 0; i < curNav.declNames.length; i += 1) { - var childDecl = findSubDecl(decl, curNav.declNames[i]); + var childDecl = findSubDecl(currentType, curNav.declNames[i]); if (childDecl == null) { return render404(); } @@ -163,29 +163,29 @@ return render404(); } } - decl = container; - curNav.declObjs.push(decl); + currentType = container; + curNav.declObjs.push(currentType); } renderNav(); - var lastDecl = curNav.declObjs[curNav.declObjs.length - 1]; - if (lastDecl.pubDecls != null) { - renderContainer(lastDecl); + var lastDeclType = curNav.declObjs[curNav.declObjs.length - 1]; + if (lastDeclType.pubDecls != null) { + renderContainer(lastDeclType); } - if (lastDecl.kind == null) { - return renderUnknownDecl(lastDecl); - } else if (lastDecl.kind === 'var') { - return renderVar(lastDecl); - } else if (lastDecl.kind === 'const' && lastDecl.type != null) { - var typeObj = zigAnalysis.types[lastDecl.type]; + if (lastDeclType.kind == null) { + return renderUnknownDecl(lastDeclType); + } else if (lastDeclType.kind === 'var') { + return renderVar(lastDeclType); + } else if (lastDeclType.kind === 'const' && lastDeclType.type != null) { + var typeObj = zigAnalysis.types[lastDeclType.type]; if (typeObj.kind === typeKinds.Fn) { - return renderFn(lastDecl); + return renderFn(lastDeclType); } else { - return renderValue(lastDecl); + return renderValue(lastDeclType); } } else { - renderType(lastDecl); + renderType(lastDeclType); } } @@ -994,15 +994,18 @@ for (var i = 0; i < container.pubDecls.length; i += 1) { var decl = zigAnalysis.decls[container.pubDecls[i]]; + var declValTypeId = getDeclValTypeId(decl); if (decl.kind === 'var') { varsList.push(decl); continue; } else if (decl.kind === 'const' && decl.type != null) { if (decl.type === typeTypeId) { - if (typeIsErrSet(decl.value)) { + // todo: this actually makes sense for decl_vals too + // the problem is, how should we get to the final type though? + if (typeIsErrSet(declValTypeId)) { errSetsList.push(decl); - } else if (typeIsStructWithNoFields(decl.value)) { + } else if (typeIsStructWithNoFields(declValTypeId)) { namespacesList.push(decl); } else { typesList.push(decl); @@ -1010,7 +1013,7 @@ } else { var typeKind = zigAnalysis.types[decl.type].kind; if (typeKind === typeKinds.Fn) { - if (allCompTimeFnCallsHaveTypeResult(decl.type, decl.value)) { + if (allCompTimeFnCallsHaveTypeResult(decl.type, declValTypeId)) { typesList.push(decl); } else { fnsList.push(decl); @@ -1111,10 +1114,20 @@ if (field.failure === true) { html += '#FAILURE#'; } else if ("decl_ref" in field) { - var name = zigAnalysis.decls[field.decl_ref].name; - html += ''; - html += ''+ name +''; + var decl = zigAnalysis.decls[field.decl_ref]; + var valType = zigAnalysis.types[getDeclValTypeId(decl)]; + var valTypeName = valType.name; + if (valType.kind === typeKinds.Struct) { + valTypeName = "struct"; + } + + html += ''; + html += '' + decl.name + ''; html += ''; + html += ' ('+ valTypeName +')'; + } else if ("type" in field) { + var name = zigAnalysis.types[field.type].name; + html += '' + name + ''; } else { html += 'var'; } @@ -1291,7 +1304,7 @@ function getDeclContainerType(decl) { if (decl.type === typeTypeId) { - return zigAnalysis.types[decl.value]; + return zigAnalysis.types[getDeclValTypeId(decl)]; } return null; } @@ -1334,6 +1347,14 @@ return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind); } + function getDeclValTypeId(decl) { + while ( "decl_ref" in decl.value) { + decl = zigAnalysis.decls[decl.value.decl_ref]; + } + console.assert("type" in decl.value); + return decl.value.type; + } + function computeCanonDeclPaths() { var list = new Array(zigAnalysis.decls.length); canonTypeDecls = new Array(zigAnalysis.types.length); @@ -1355,10 +1376,11 @@ if (list[mainDeclIndex] != null) continue; var decl = zigAnalysis.decls[mainDeclIndex]; + var declValTypeId = getDeclValTypeId(decl); if (decl.type === typeTypeId && - declCanRepresentTypeKind(zigAnalysis.types[decl.value].kind)) + declCanRepresentTypeKind(zigAnalysis.types[declValTypeId].kind)) { - canonTypeDecls[decl.value] = mainDeclIndex; + canonTypeDecls[declValTypeId] = mainDeclIndex; } var declNames = item.declNames.concat([decl.name]); list[mainDeclIndex] = { diff --git a/src/Autodoc.zig b/src/Autodoc.zig index bd9398a82e..b45682f381 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -21,6 +21,10 @@ pub fn init(m: *Module, doc_location: ?Compilation.EmitLoc) Autodoc { }; } +pub fn deinit(_: *Autodoc) void { + arena_allocator.deinit(); +} + pub fn generateZirData(self: *Autodoc) !void { if (self.doc_location) |loc| { if (loc.directory) |dir| { @@ -48,13 +52,51 @@ pub fn generateZirData(self: *Autodoc) !void { { // TODO: we don't want to add .none, but the index math has to check out - var i: u32 = 1; + var i: u32 = 0; while (i <= @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type)) : (i += 1) { var tmpbuf = std.ArrayList(u8).init(self.arena); try Zir.Inst.Ref.typed_value_map[i].val.format("", .{}, tmpbuf.writer()); try self.types.append(self.arena, .{ - .kind = 0, .name = tmpbuf.toOwnedSlice(), + .kind = switch (@intToEnum(Zir.Inst.Ref, i)) { + else => |t| blk: { + std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{ + @tagName(t), + }); + break :blk 7; + }, + .u1_type, + .u8_type, + .i8_type, + .u16_type, + .i16_type, + .u32_type, + .i32_type, + .u64_type, + .i64_type, + .u128_type, + .i128_type, + .usize_type, + .isize_type, + .c_short_type, + .c_ushort_type, + .c_int_type, + .c_uint_type, + .c_long_type, + .c_ulong_type, + .c_longlong_type, + .c_ulonglong_type, + .c_longdouble_type, + => @enumToInt(std.builtin.TypeId.Int), + .f16_type, + .f32_type, + .f64_type, + .f128_type, + => @enumToInt(std.builtin.TypeId.Float), + .bool_type => @enumToInt(std.builtin.TypeId.Bool), + .void_type => @enumToInt(std.builtin.TypeId.Void), + .type_type => @enumToInt(std.builtin.TypeId.Type), + }, }); } } @@ -167,7 +209,7 @@ const DocData = struct { kind: []const u8, // TODO: where do we find this info? src: usize, // index into astNodes type: usize, // index into types - value: usize, + value: WalkResult, }; const AstNode = struct { @@ -476,7 +518,6 @@ fn walkDecls( }; const walk_result = try self.walkInstruction(zir, scope, decl_index); - const type_index = walk_result.type; if (is_pub) { try decl_indexes.append(self.arena, decls_slot_index); @@ -487,8 +528,8 @@ fn walkDecls( self.decls.items[decls_slot_index] = .{ .name = name, .src = ast_node_index, - .type = 0, - .value = type_index, + .type = @enumToInt(Zir.Inst.Ref.type_type), + .value = walk_result, .kind = "const", // find where this information can be found }; } @@ -561,13 +602,9 @@ fn collectFieldInfo( else => { const enum_value = @enumToInt(field_type); if (enum_value < Zir.Inst.Ref.typed_value_map.len) { - std.debug.print( - "TODO: handle ref type: {s}", - .{@tagName(field_type)}, - ); try field_type_indexes.append( self.arena, - DocData.WalkResult{ .failure = true }, + DocData.WalkResult{ .type = enum_value }, ); } else { const zir_index = enum_value - Zir.Inst.Ref.typed_value_map.len; diff --git a/src/Compilation.zig b/src/Compilation.zig index cadc665598..d4e3c13133 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2870,6 +2870,7 @@ pub fn performAllTheWork( if (comp.emit_docs) |doc_location| { if (comp.bin_file.options.module) |module| { var autodoc = Autodoc.init(module, doc_location); + defer autodoc.deinit(); try autodoc.generateZirData(); } } -- cgit v1.2.3 From e5d21e10bc6e652a72cf22ad1b1cf8ba8692abbf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Jul 2022 13:36:41 -0700 Subject: Autodoc: skip docs when compile errors occur --- src/Compilation.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index d4e3c13133..ee2ed6acca 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2288,6 +2288,14 @@ pub fn update(comp: *Compilation) !void { return; } + if (comp.emit_docs) |doc_location| { + if (comp.bin_file.options.module) |module| { + var autodoc = Autodoc.init(module, doc_location); + defer autodoc.deinit(); + try autodoc.generateZirData(); + } + } + // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and // -femit-asm to handle, in the case of C objects. comp.emitOthers(); @@ -2867,14 +2875,6 @@ pub fn performAllTheWork( } } - if (comp.emit_docs) |doc_location| { - if (comp.bin_file.options.module) |module| { - var autodoc = Autodoc.init(module, doc_location); - defer autodoc.deinit(); - try autodoc.generateZirData(); - } - } - if (!use_stage1) { const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls"); defer outdated_and_deleted_decls_frame.end(); -- cgit v1.2.3 From 7d636f0f9da49337ae3a54af25e6465af033bd89 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Jul 2022 14:01:36 -0700 Subject: delete the stage1 implementation of autodoc --- CMakeLists.txt | 1 - src/Compilation.zig | 6 - src/stage1.zig | 4 - src/stage1/all_types.hpp | 2 - src/stage1/codegen.cpp | 52 -- src/stage1/dump_analysis.cpp | 1431 ------------------------------------------ src/stage1/dump_analysis.hpp | 17 - src/stage1/stage1.cpp | 2 - src/stage1/stage1.h | 6 - tools/merge_anal_dumps.zig | 454 -------------- 10 files changed, 1975 deletions(-) delete mode 100644 src/stage1/dump_analysis.cpp delete mode 100644 src/stage1/dump_analysis.hpp delete mode 100644 tools/merge_anal_dumps.zig (limited to 'src/Compilation.zig') diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e34b6068..b046152bdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -340,7 +340,6 @@ set(STAGE1_SOURCES "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/codegen.cpp" - "${CMAKE_SOURCE_DIR}/src/stage1/dump_analysis.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/error.cpp" "${CMAKE_SOURCE_DIR}/src/stage1/heap.cpp" diff --git a/src/Compilation.zig b/src/Compilation.zig index ee2ed6acca..5204910193 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5169,8 +5169,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory); const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory); const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory); - const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory); - const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory); const stage1_pkg = try createStage1Pkg(arena, "root", mod.main_pkg, null); const test_filter = comp.test_filter orelse ""[0..0]; 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 .emit_llvm_ir_len = emit_llvm_ir_path.len, .emit_bitcode_ptr = emit_llvm_bc_path.ptr, .emit_bitcode_len = emit_llvm_bc_path.len, - .emit_analysis_json_ptr = emit_analysis_path.ptr, - .emit_analysis_json_len = emit_analysis_path.len, - .emit_docs_ptr = emit_docs_path.ptr, - .emit_docs_len = emit_docs_path.len, .builtin_zig_path_ptr = builtin_zig_path.ptr, .builtin_zig_path_len = builtin_zig_path.len, .test_filter_ptr = test_filter.ptr, diff --git a/src/stage1.zig b/src/stage1.zig index 005dc312ba..fd6f53c096 100644 --- a/src/stage1.zig +++ b/src/stage1.zig @@ -96,10 +96,6 @@ pub const Module = extern struct { emit_llvm_ir_len: usize, emit_bitcode_ptr: [*]const u8, emit_bitcode_len: usize, - emit_analysis_json_ptr: [*]const u8, - emit_analysis_json_len: usize, - emit_docs_ptr: [*]const u8, - emit_docs_len: usize, builtin_zig_path_ptr: [*]const u8, builtin_zig_path_len: usize, test_filter_ptr: [*]const u8, diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index ba5df49c59..4028c3872d 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -2141,8 +2141,6 @@ struct CodeGen { Buf asm_file_output_path; Buf llvm_ir_file_output_path; Buf bitcode_file_output_path; - Buf analysis_json_output_path; - Buf docs_output_path; Buf *builtin_zig_path; diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 81e5208e91..8b88446295 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -16,7 +16,6 @@ #include "util.hpp" #include "zig_llvm.h" #include "stage2.h" -#include "dump_analysis.hpp" #include "softfloat.hpp" #include "zigendian.h" @@ -10546,57 +10545,6 @@ void codegen_build_object(CodeGen *g) { gen_root_source(g); - if (buf_len(&g->analysis_json_output_path) != 0) { - const char *analysis_json_filename = buf_ptr(&g->analysis_json_output_path); - FILE *f = fopen(analysis_json_filename, "wb"); - if (f == nullptr) { - fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno)); - exit(1); - } - zig_print_analysis_dump(g, f, " ", "\n"); - if (fclose(f) != 0) { - fprintf(stderr, "Unable to write '%s': %s\n", analysis_json_filename, strerror(errno)); - exit(1); - } - } - if (buf_len(&g->docs_output_path) != 0) { - Error err; - Buf *doc_dir_path = &g->docs_output_path; - if ((err = os_make_path(doc_dir_path))) { - fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err)); - exit(1); - } - Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "docs" OS_SEP "index.html", - buf_ptr(g->zig_lib_dir)); - Buf *index_html_dest_path = buf_sprintf("%s" OS_SEP "index.html", buf_ptr(doc_dir_path)); - Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "docs" OS_SEP "main.js", - buf_ptr(g->zig_lib_dir)); - Buf *main_js_dest_path = buf_sprintf("%s" OS_SEP "main.js", buf_ptr(doc_dir_path)); - - if ((err = os_copy_file(index_html_src_path, index_html_dest_path))) { - fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(index_html_src_path), - buf_ptr(index_html_dest_path), err_str(err)); - exit(1); - } - if ((err = os_copy_file(main_js_src_path, main_js_dest_path))) { - fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(main_js_src_path), - buf_ptr(main_js_dest_path), err_str(err)); - exit(1); - } - const char *data_js_filename = buf_ptr(buf_sprintf("%s" OS_SEP "data.js", buf_ptr(doc_dir_path))); - FILE *f = fopen(data_js_filename, "wb"); - if (f == nullptr) { - fprintf(stderr, "Unable to open '%s': %s\n", data_js_filename, strerror(errno)); - exit(1); - } - fprintf(f, "zigAnalysis="); - zig_print_analysis_dump(g, f, "", ""); - fprintf(f, ";"); - if (fclose(f) != 0) { - fprintf(stderr, "Unable to write '%s': %s\n", data_js_filename, strerror(errno)); - exit(1); - } - } codegen_add_time_event(g, "Code Generation"); { diff --git a/src/stage1/dump_analysis.cpp b/src/stage1/dump_analysis.cpp deleted file mode 100644 index 15cd7c2874..0000000000 --- a/src/stage1/dump_analysis.cpp +++ /dev/null @@ -1,1431 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#include "dump_analysis.hpp" -#include "analyze.hpp" -#include "ir.hpp" -#include "codegen.hpp" -#include "os.hpp" - -enum JsonWriterState { - JsonWriterStateInvalid, - JsonWriterStateValue, - JsonWriterStateArrayStart, - JsonWriterStateArray, - JsonWriterStateObjectStart, - JsonWriterStateObject, -}; - -#define JSON_MAX_DEPTH 10 - -struct JsonWriter { - size_t state_index; - FILE *f; - const char *one_indent; - const char *nl; - JsonWriterState state[JSON_MAX_DEPTH]; -}; - -static void jw_init(JsonWriter *jw, FILE *f, const char *one_indent, const char *nl) { - jw->state_index = 1; - jw->f = f; - jw->one_indent = one_indent; - jw->nl = nl; - jw->state[0] = JsonWriterStateInvalid; - jw->state[1] = JsonWriterStateValue; -} - -static void jw_nl_indent(JsonWriter *jw) { - assert(jw->state_index >= 1); - fprintf(jw->f, "%s", jw->nl); - for (size_t i = 0; i < jw->state_index - 1; i += 1) { - fprintf(jw->f, "%s", jw->one_indent); - } -} - -static void jw_push_state(JsonWriter *jw, JsonWriterState state) { - jw->state_index += 1; - assert(jw->state_index < JSON_MAX_DEPTH); - jw->state[jw->state_index] = state; -} - -static void jw_pop_state(JsonWriter *jw) { - assert(jw->state_index != 0); - jw->state_index -= 1; -} - -static void jw_begin_array(JsonWriter *jw) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - fprintf(jw->f, "["); - jw->state[jw->state_index] = JsonWriterStateArrayStart; -} - -static void jw_begin_object(JsonWriter *jw) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - fprintf(jw->f, "{"); - jw->state[jw->state_index] = JsonWriterStateObjectStart; -} - -static void jw_array_elem(JsonWriter *jw) { - switch (jw->state[jw->state_index]) { - case JsonWriterStateInvalid: - case JsonWriterStateValue: - case JsonWriterStateObjectStart: - case JsonWriterStateObject: - zig_unreachable(); - case JsonWriterStateArray: - fprintf(jw->f, ","); - ZIG_FALLTHROUGH; - case JsonWriterStateArrayStart: - jw->state[jw->state_index] = JsonWriterStateArray; - jw_push_state(jw, JsonWriterStateValue); - jw_nl_indent(jw); - return; - } - zig_unreachable(); -} - -static void jw_write_escaped_string(JsonWriter *jw, const char *s) { - fprintf(jw->f, "\""); - for (;; s += 1) { - switch (*s) { - case 0: - fprintf(jw->f, "\""); - return; - case '"': - fprintf(jw->f, "\\\""); - continue; - case '\t': - fprintf(jw->f, "\\t"); - continue; - case '\r': - fprintf(jw->f, "\\r"); - continue; - case '\n': - fprintf(jw->f, "\\n"); - continue; - case '\b': - fprintf(jw->f, "\\b"); - continue; - case '\f': - fprintf(jw->f, "\\f"); - continue; - case '\\': - fprintf(jw->f, "\\\\"); - continue; - default: - fprintf(jw->f, "%c", *s); - continue; - } - } -} - -static void jw_object_field(JsonWriter *jw, const char *name) { - switch (jw->state[jw->state_index]) { - case JsonWriterStateInvalid: - case JsonWriterStateValue: - case JsonWriterStateArray: - case JsonWriterStateArrayStart: - zig_unreachable(); - case JsonWriterStateObject: - fprintf(jw->f, ","); - ZIG_FALLTHROUGH; - case JsonWriterStateObjectStart: - jw->state[jw->state_index] = JsonWriterStateObject; - jw_push_state(jw, JsonWriterStateValue); - jw_nl_indent(jw); - jw_write_escaped_string(jw, name); - fprintf(jw->f, ": "); - return; - } - zig_unreachable(); -} - -static void jw_end_array(JsonWriter *jw) { - switch (jw->state[jw->state_index]) { - case JsonWriterStateInvalid: - case JsonWriterStateValue: - case JsonWriterStateObjectStart: - case JsonWriterStateObject: - zig_unreachable(); - case JsonWriterStateArrayStart: - fprintf(jw->f, "]"); - jw_pop_state(jw); - return; - case JsonWriterStateArray: - jw_nl_indent(jw); - jw_pop_state(jw); - fprintf(jw->f, "]"); - return; - } - zig_unreachable(); -} - - -static void jw_end_object(JsonWriter *jw) { - switch (jw->state[jw->state_index]) { - case JsonWriterStateInvalid: - zig_unreachable(); - case JsonWriterStateValue: - zig_unreachable(); - case JsonWriterStateArray: - zig_unreachable(); - case JsonWriterStateArrayStart: - zig_unreachable(); - case JsonWriterStateObjectStart: - fprintf(jw->f, "}"); - jw_pop_state(jw); - return; - case JsonWriterStateObject: - jw_nl_indent(jw); - jw_pop_state(jw); - fprintf(jw->f, "}"); - return; - } - zig_unreachable(); -} - -static void jw_null(JsonWriter *jw) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - fprintf(jw->f, "null"); - jw_pop_state(jw); -} - -static void jw_bool(JsonWriter *jw, bool x) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - if (x) { - fprintf(jw->f, "true"); - } else { - fprintf(jw->f, "false"); - } - jw_pop_state(jw); -} - -static void jw_int(JsonWriter *jw, int64_t x) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - if (x > 4503599627370496 || x < -4503599627370496) { - fprintf(jw->f, "\"%" ZIG_PRI_i64 "\"", x); - } else { - fprintf(jw->f, "%" ZIG_PRI_i64, x); - } - jw_pop_state(jw); -} - -static void jw_bigint(JsonWriter *jw, const BigInt *x) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - Buf *str = buf_alloc(); - bigint_append_buf(str, x, 10); - - if (bigint_fits_in_bits(x, 52, true)) { - fprintf(jw->f, "%s", buf_ptr(str)); - } else { - fprintf(jw->f, "\"%s\"", buf_ptr(str)); - } - jw_pop_state(jw); - - buf_destroy(str); -} - -static void jw_string(JsonWriter *jw, const char *s) { - assert(jw->state[jw->state_index] == JsonWriterStateValue); - jw_write_escaped_string(jw, s); - jw_pop_state(jw); -} - - -static void tree_print(FILE *f, ZigType *ty, size_t indent); - -static int compare_type_abi_sizes_desc(const void *a, const void *b) { - uint64_t size_a = (*(ZigType * const*)(a))->abi_size; - uint64_t size_b = (*(ZigType * const*)(b))->abi_size; - if (size_a > size_b) - return -1; - if (size_a < size_b) - return 1; - return 0; -} - -static void start_child(FILE *f, size_t indent) { - fprintf(f, "\n"); - for (size_t i = 0; i < indent; i += 1) { - fprintf(f, " "); - } -} - -static void start_peer(FILE *f, size_t indent) { - fprintf(f, ",\n"); - for (size_t i = 0; i < indent; i += 1) { - fprintf(f, " "); - } -} - -static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { - ZigList children = {}; - uint64_t sum_from_fields = 0; - for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { - TypeStructField *field = struct_type->data.structure.fields[i]; - children.append(field->type_entry); - sum_from_fields += field->type_entry->abi_size; - } - qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc); - - start_peer(f, indent); - fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields); - - start_peer(f, indent); - fprintf(f, "\"fields\": ["); - - for (size_t i = 0; i < children.length; i += 1) { - if (i == 0) { - start_child(f, indent + 1); - } else { - start_peer(f, indent + 1); - } - fprintf(f, "{"); - - ZigType *child_type = children.at(i); - tree_print(f, child_type, indent + 2); - - start_child(f, indent + 1); - fprintf(f, "}"); - } - - start_child(f, indent); - fprintf(f, "]"); -} - -static void tree_print(FILE *f, ZigType *ty, size_t indent) { - start_child(f, indent); - fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name)); - - start_peer(f, indent); - fprintf(f, "\"sizef\": \""); - zig_pretty_print_bytes(f, ty->abi_size); - fprintf(f, "\""); - - start_peer(f, indent); - fprintf(f, "\"size\": \"%" ZIG_PRI_usize "\"", ty->abi_size); - - switch (ty->id) { - case ZigTypeIdFnFrame: - return tree_print_struct(f, ty->data.frame.locals_struct, indent); - case ZigTypeIdStruct: - return tree_print_struct(f, ty, indent); - default: - start_child(f, indent); - return; - } -} - -void zig_print_stack_report(CodeGen *g, FILE *f) { - if (g->largest_frame_fn == nullptr) { - fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n"); - return; - } - fprintf(f, "{"); - tree_print(f, g->largest_frame_fn->frame_type, 1); - - start_child(f, 0); - fprintf(f, "}\n"); -} - -struct AnalDumpCtx { - CodeGen *g; - JsonWriter jw; - - ZigList type_list; - HashMap type_map; - - ZigList pkg_list; - HashMap pkg_map; - - ZigList file_list; - HashMap file_map; - - ZigList decl_list; - HashMap decl_map; - - ZigList fn_list; - HashMap fn_map; - HashMap fn_decl_map; - - ZigList node_list; - HashMap node_map; - - ZigList err_list; - HashMap err_map; -}; - -static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty); -static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value); - -static void anal_dump_poke_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value) { - Error err; - if (value->type != ty) { - return; - } - if ((err = ir_resolve_lazy(ctx->g, source_node, value))) { - codegen_report_errors_and_exit(ctx->g); - } - if (value->special == ConstValSpecialUndef) { - return; - } - if (value->special == ConstValSpecialRuntime) { - return; - } - switch (ty->id) { - case ZigTypeIdMetaType: { - ZigType *val_ty = value->data.x_type; - (void)anal_dump_get_type_id(ctx, val_ty); - return; - } - default: - return; - } - zig_unreachable(); -} - -static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty) { - uint32_t type_id = ctx->type_list.length; - auto existing_entry = ctx->type_map.put_unique(ty, type_id); - if (existing_entry == nullptr) { - ctx->type_list.append(ty); - } else { - type_id = existing_entry->value; - } - return type_id; -} - -static uint32_t anal_dump_get_pkg_id(AnalDumpCtx *ctx, ZigPackage *pkg) { - assert(pkg != nullptr); - uint32_t pkg_id = ctx->pkg_list.length; - auto existing_entry = ctx->pkg_map.put_unique(pkg, pkg_id); - if (existing_entry == nullptr) { - ctx->pkg_list.append(pkg); - } else { - pkg_id = existing_entry->value; - } - return pkg_id; -} - -static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) { - uint32_t file_id = ctx->file_list.length; - auto existing_entry = ctx->file_map.put_unique(file, file_id); - if (existing_entry == nullptr) { - ctx->file_list.append(file); - } else { - file_id = existing_entry->value; - } - return file_id; -} - -static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) { - uint32_t node_id = ctx->node_list.length; - auto existing_entry = ctx->node_map.put_unique(node, node_id); - if (existing_entry == nullptr) { - ctx->node_list.append(node); - } else { - node_id = existing_entry->value; - } - return node_id; -} - -static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) { - uint32_t fn_id = ctx->fn_list.length; - auto existing_entry = ctx->fn_map.put_unique(fn, fn_id); - if (existing_entry == nullptr) { - ctx->fn_list.append(fn); - - // poke the fn - (void)anal_dump_get_type_id(ctx, fn->type_entry); - (void)anal_dump_get_node_id(ctx, fn->proto_node); - } else { - fn_id = existing_entry->value; - } - return fn_id; -} - -static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) { - uint32_t err_id = ctx->err_list.length; - auto existing_entry = ctx->err_map.put_unique(err, err_id); - if (existing_entry == nullptr) { - ctx->err_list.append(err); - } else { - err_id = existing_entry->value; - } - return err_id; -} - -static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) { - uint32_t decl_id = ctx->decl_list.length; - auto existing_entry = ctx->decl_map.put_unique(tld, decl_id); - if (existing_entry == nullptr) { - ctx->decl_list.append(tld); - - if (tld->import != nullptr) { - (void)anal_dump_get_type_id(ctx, tld->import); - } - - // poke the types - switch (tld->id) { - case TldIdVar: { - TldVar *tld_var = reinterpret_cast(tld); - ZigVar *var = tld_var->var; - - if (var != nullptr) { - (void)anal_dump_get_type_id(ctx, var->var_type); - - if (var->const_value != nullptr) { - anal_dump_poke_value(ctx, var->decl_node, var->var_type, var->const_value); - } - } - break; - } - case TldIdFn: { - TldFn *tld_fn = reinterpret_cast(tld); - ZigFn *fn = tld_fn->fn_entry; - - if (fn != nullptr) { - (void)anal_dump_get_type_id(ctx, fn->type_entry); - ctx->fn_decl_map.put_unique(fn, decl_id); - } - break; - } - default: - break; - } - - } else { - decl_id = existing_entry->value; - } - return decl_id; -} - -static void anal_dump_type_ref(AnalDumpCtx *ctx, ZigType *ty) { - uint32_t type_id = anal_dump_get_type_id(ctx, ty); - jw_int(&ctx->jw, type_id); -} - -static void anal_dump_pkg_ref(AnalDumpCtx *ctx, ZigPackage *pkg) { - uint32_t pkg_id = anal_dump_get_pkg_id(ctx, pkg); - jw_int(&ctx->jw, pkg_id); -} - -static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) { - uint32_t file_id = anal_dump_get_file_id(ctx, file); - jw_int(&ctx->jw, file_id); -} - -static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) { - uint32_t node_id = anal_dump_get_node_id(ctx, node); - jw_int(&ctx->jw, node_id); -} - -static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) { - uint32_t fn_id = anal_dump_get_fn_id(ctx, fn); - jw_int(&ctx->jw, fn_id); -} - -static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) { - uint32_t err_id = anal_dump_get_err_id(ctx, err); - jw_int(&ctx->jw, err_id); -} - -static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) { - uint32_t decl_id = anal_dump_get_decl_id(ctx, tld); - jw_int(&ctx->jw, decl_id); -} - -static void anal_dump_pkg(AnalDumpCtx *ctx, ZigPackage *pkg) { - JsonWriter *jw = &ctx->jw; - - Buf full_path_buf = BUF_INIT; - os_path_join(&pkg->root_src_dir, &pkg->root_src_path, &full_path_buf); - Buf *resolve_paths[] = { &full_path_buf, }; - Buf *resolved_path = buf_alloc(); - *resolved_path = os_path_resolve(resolve_paths, 1); - - auto import_entry = ctx->g->import_table.maybe_get(resolved_path); - if (!import_entry) { - return; - } - - jw_array_elem(jw); - jw_begin_object(jw); - - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&pkg->pkg_path)); - - jw_object_field(jw, "file"); - anal_dump_file_ref(ctx, resolved_path); - - jw_object_field(jw, "main"); - anal_dump_type_ref(ctx, import_entry->value); - - jw_object_field(jw, "table"); - jw_begin_object(jw); - auto it = pkg->package_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - ZigPackage *child_pkg = entry->value; - if (child_pkg != nullptr) { - jw_object_field(jw, buf_ptr(entry->key)); - anal_dump_pkg_ref(ctx, child_pkg); - } - } - jw_end_object(jw); - - jw_end_object(jw); -} - -static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) { - JsonWriter *jw = &ctx->jw; - - bool make_obj = tld->id == TldIdVar || tld->id == TldIdFn; - if (make_obj) { - jw_array_elem(jw); - jw_begin_object(jw); - - jw_object_field(jw, "import"); - anal_dump_type_ref(ctx, tld->import); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, tld->source_node); - - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(tld->name)); - } - - switch (tld->id) { - case TldIdVar: { - TldVar *tld_var = reinterpret_cast(tld); - ZigVar *var = tld_var->var; - - if (var != nullptr) { - jw_object_field(jw, "kind"); - if (var->src_is_const) { - jw_string(jw, "const"); - } else { - jw_string(jw, "var"); - } - - if (var->is_thread_local) { - jw_object_field(jw, "threadlocal"); - jw_bool(jw, true); - } - - jw_object_field(jw, "type"); - anal_dump_type_ref(ctx, var->var_type); - - if (var->const_value != nullptr) { - jw_object_field(jw, "value"); - anal_dump_value(ctx, var->decl_node, var->var_type, var->const_value); - } - } - break; - } - case TldIdFn: { - TldFn *tld_fn = reinterpret_cast(tld); - ZigFn *fn = tld_fn->fn_entry; - - if (fn != nullptr) { - jw_object_field(jw, "kind"); - jw_string(jw, "const"); - - jw_object_field(jw, "type"); - anal_dump_type_ref(ctx, fn->type_entry); - - jw_object_field(jw, "value"); - anal_dump_fn_ref(ctx, fn); - } - break; - } - default: - break; - } - - if (make_obj) { - jw_end_object(jw); - } -} - -static void anal_dump_file(AnalDumpCtx *ctx, Buf *file) { - JsonWriter *jw = &ctx->jw; - jw_string(jw, buf_ptr(file)); -} - -static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, ZigValue *value) { - Error err; - - if (value->type != ty) { - jw_null(&ctx->jw); - return; - } - if ((err = ir_resolve_lazy(ctx->g, source_node, value))) { - codegen_report_errors_and_exit(ctx->g); - } - if (value->special == ConstValSpecialUndef) { - jw_string(&ctx->jw, "undefined"); - return; - } - if (value->special == ConstValSpecialRuntime) { - jw_null(&ctx->jw); - return; - } - switch (ty->id) { - case ZigTypeIdMetaType: { - ZigType *val_ty = value->data.x_type; - anal_dump_type_ref(ctx, val_ty); - return; - } - case ZigTypeIdFn: { - if (value->data.x_ptr.special == ConstPtrSpecialFunction) { - ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry; - anal_dump_fn_ref(ctx, val_fn); - } else { - jw_null(&ctx->jw); - } - return; - } - case ZigTypeIdOptional: { - if(optional_value_is_null(value)){ - jw_string(&ctx->jw, "null"); - } else { - jw_null(&ctx->jw); - } - return; - } - case ZigTypeIdBool: { - jw_string(&ctx->jw, value->data.x_bool ? "true" : "false"); - return; - } - case ZigTypeIdInt: { - jw_bigint(&ctx->jw, &value->data.x_bigint); - return; - } - default: - jw_null(&ctx->jw); - return; - } - zig_unreachable(); -} - -static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) { - JsonWriter *jw = &ctx->jw; - if (ty->data.pointer.explicit_alignment != 0) { - jw_object_field(jw, "align"); - jw_int(jw, ty->data.pointer.explicit_alignment); - } - if (ty->data.pointer.is_const) { - jw_object_field(jw, "const"); - jw_bool(jw, true); - } - if (ty->data.pointer.is_volatile) { - jw_object_field(jw, "volatile"); - jw_bool(jw, true); - } - if (ty->data.pointer.allow_zero) { - jw_object_field(jw, "allowZero"); - jw_bool(jw, true); - } - if (ty->data.pointer.host_int_bytes != 0) { - jw_object_field(jw, "hostIntBytes"); - jw_int(jw, ty->data.pointer.host_int_bytes); - - jw_object_field(jw, "bitOffsetInHost"); - jw_int(jw, ty->data.pointer.bit_offset_in_host); - } - - jw_object_field(jw, "elem"); - anal_dump_type_ref(ctx, ty->data.pointer.child_type); -} - -static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { - JsonWriter *jw = &ctx->jw; - jw_array_elem(jw); - jw_begin_object(jw); - - jw_object_field(jw, "kind"); - jw_int(jw, type_id_index(ty)); - - switch (ty->id) { - case ZigTypeIdMetaType: - case ZigTypeIdBool: - case ZigTypeIdEnumLiteral: - break; - case ZigTypeIdStruct: { - if (ty->data.structure.special == StructSpecialSlice) { - jw_object_field(jw, "len"); - jw_int(jw, 2); - anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index]->type_entry); - break; - } - - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, ty->data.structure.decl_node); - - { - jw_object_field(jw, "pubDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.structure.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPub) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - { - jw_object_field(jw, "privDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.structure.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPrivate) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - if (ty->data.structure.src_field_count != 0) { - jw_object_field(jw, "fields"); - jw_begin_array(jw); - - for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { - jw_array_elem(jw); - anal_dump_type_ref(ctx, ty->data.structure.fields[i]->type_entry); - } - jw_end_array(jw); - } - - if (ty->data.structure.root_struct != nullptr) { - Buf *path_buf = ty->data.structure.root_struct->path; - - jw_object_field(jw, "file"); - anal_dump_file_ref(ctx, path_buf); - } - break; - } - case ZigTypeIdUnion: { - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, ty->data.unionation.decl_node); - - { - jw_object_field(jw, "pubDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.unionation.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPub) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - { - jw_object_field(jw, "privDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.unionation.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPrivate) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - if (ty->data.unionation.src_field_count != 0) { - jw_object_field(jw, "fields"); - jw_begin_array(jw); - - for(size_t i = 0; i < ty->data.unionation.src_field_count; i += 1) { - jw_array_elem(jw); - anal_dump_type_ref(ctx, ty->data.unionation.fields[i].type_entry); - } - jw_end_array(jw); - } - break; - } - case ZigTypeIdEnum: { - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, ty->data.enumeration.decl_node); - - { - jw_object_field(jw, "pubDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.enumeration.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPub) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - { - jw_object_field(jw, "privDecls"); - jw_begin_array(jw); - - ScopeDecls *decls_scope = ty->data.enumeration.decls_scope; - auto it = decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - if (tld->visib_mod == VisibModPrivate) { - jw_array_elem(jw); - anal_dump_decl_ref(ctx, tld); - } - } - jw_end_array(jw); - } - - if (ty->data.enumeration.src_field_count != 0) { - jw_object_field(jw, "fields"); - jw_begin_array(jw); - - for(size_t i = 0; i < ty->data.enumeration.src_field_count; i += 1) { - jw_array_elem(jw); - jw_bigint(jw, &ty->data.enumeration.fields[i].value); - } - jw_end_array(jw); - } - break; - } - case ZigTypeIdFloat: { - jw_object_field(jw, "bits"); - jw_int(jw, ty->data.floating.bit_count); - break; - } - case ZigTypeIdInt: { - if (ty->data.integral.is_signed) { - jw_object_field(jw, "i"); - } else { - jw_object_field(jw, "u"); - } - jw_int(jw, ty->data.integral.bit_count); - break; - } - case ZigTypeIdFn: { - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - - jw_object_field(jw, "generic"); - jw_bool(jw, ty->data.fn.is_generic); - - if (ty->data.fn.fn_type_id.return_type != nullptr) { - jw_object_field(jw, "ret"); - anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type); - } - - if (ty->data.fn.fn_type_id.param_count != 0) { - jw_object_field(jw, "args"); - jw_begin_array(jw); - for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) { - jw_array_elem(jw); - if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) { - anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type); - } else { - jw_null(jw); - } - } - jw_end_array(jw); - } - break; - } - case ZigTypeIdOptional: { - jw_object_field(jw, "child"); - anal_dump_type_ref(ctx, ty->data.maybe.child_type); - break; - } - case ZigTypeIdPointer: { - switch (ty->data.pointer.ptr_len) { - case PtrLenSingle: - break; - case PtrLenUnknown: - jw_object_field(jw, "len"); - jw_int(jw, 1); - break; - case PtrLenC: - jw_object_field(jw, "len"); - jw_int(jw, 3); - break; - } - anal_dump_pointer_attrs(ctx, ty); - break; - } - case ZigTypeIdErrorSet: { - if (type_is_global_error_set(ty)) { - break; - } - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - - if (ty->data.error_set.infer_fn != nullptr) { - jw_object_field(jw, "fn"); - anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn); - } - jw_object_field(jw, "errors"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) { - jw_array_elem(jw); - ErrorTableEntry *err = ty->data.error_set.errors[i]; - anal_dump_err_ref(ctx, err); - } - jw_end_array(jw); - break; - } - case ZigTypeIdErrorUnion: { - jw_object_field(jw, "err"); - anal_dump_type_ref(ctx, ty->data.error_union.err_set_type); - - jw_object_field(jw, "payload"); - anal_dump_type_ref(ctx, ty->data.error_union.payload_type); - - break; - } - case ZigTypeIdArray: { - jw_object_field(jw, "len"); - jw_int(jw, ty->data.array.len); - - jw_object_field(jw, "elem"); - anal_dump_type_ref(ctx, ty->data.array.child_type); - break; - } - case ZigTypeIdVector: { - jw_object_field(jw, "len"); - jw_int(jw, ty->data.vector.len); - - jw_object_field(jw, "elem"); - anal_dump_type_ref(ctx, ty->data.vector.elem_type); - break; - } - case ZigTypeIdAnyFrame: { - if (ty->data.any_frame.result_type != nullptr) { - jw_object_field(jw, "result"); - anal_dump_type_ref(ctx, ty->data.any_frame.result_type); - } - break; - } - case ZigTypeIdFnFrame: { - jw_object_field(jw, "fnName"); - jw_string(jw, buf_ptr(&ty->data.frame.fn->symbol_name)); - - jw_object_field(jw, "fn"); - anal_dump_fn_ref(ctx, ty->data.frame.fn); - break; - } - case ZigTypeIdInvalid: - zig_unreachable(); - default: - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); - break; - } - jw_end_object(jw); -} - -static Buf *collect_doc_comments(RootStruct *root_struct, TokenIndex first_token) { - if (first_token == 0) - return nullptr; - - TokenId *token_ids = root_struct->token_ids; - TokenLoc *token_locs = root_struct->token_locs; - Buf *str = buf_alloc(); - const char *source = buf_ptr(root_struct->source_code); - TokenIndex doc_token = first_token; - for (;token_ids[doc_token] == TokenIdDocComment; doc_token += 1) { - // chops off '///' but leaves '\n' - uint32_t start_pos = token_locs[doc_token].offset; - uint32_t token_len = 0; - while (source[start_pos + token_len] != '\n' && - source[start_pos + token_len] != 0) - { - token_len += 1; - } - buf_append_mem(str, source + start_pos + 3, token_len - 3); - } - return str; -} - -static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { - JsonWriter *jw = &ctx->jw; - - jw_begin_object(jw); - - jw_object_field(jw, "file"); - RootStruct *root_struct = node->owner->data.structure.root_struct; - anal_dump_file_ref(ctx, root_struct->path); - - jw_object_field(jw, "line"); - jw_int(jw, root_struct->token_locs[node->main_token].line); - - jw_object_field(jw, "col"); - jw_int(jw, root_struct->token_locs[node->main_token].column); - - const Buf *doc_comments_buf = nullptr; - const Buf *name_buf = nullptr; - const ZigList *field_nodes = nullptr; - bool is_var_args = false; - bool is_noalias = false; - bool is_comptime = false; - - switch (node->type) { - case NodeTypeParamDecl: - doc_comments_buf = collect_doc_comments(root_struct, node->data.param_decl.doc_comments); - name_buf = node->data.param_decl.name; - is_var_args = node->data.param_decl.is_var_args; - is_noalias = node->data.param_decl.is_noalias; - is_comptime = node->data.param_decl.is_comptime; - break; - case NodeTypeFnProto: - doc_comments_buf = collect_doc_comments(root_struct, node->data.fn_proto.doc_comments); - field_nodes = &node->data.fn_proto.params; - is_var_args = node->data.fn_proto.is_var_args; - break; - case NodeTypeVariableDeclaration: - doc_comments_buf = collect_doc_comments(root_struct, node->data.variable_declaration.doc_comments); - break; - case NodeTypeErrorSetField: - doc_comments_buf = collect_doc_comments(root_struct, node->data.err_set_field.doc_comments); - break; - case NodeTypeStructField: - doc_comments_buf = collect_doc_comments(root_struct, node->data.struct_field.doc_comments); - name_buf = node->data.struct_field.name; - break; - case NodeTypeContainerDecl: - field_nodes = &node->data.container_decl.fields; - doc_comments_buf = collect_doc_comments(root_struct, node->data.container_decl.doc_comments); - break; - default: - break; - } - - if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) { - jw_object_field(jw, "docs"); - jw_string(jw, buf_ptr(doc_comments_buf)); - } - - if (name_buf != nullptr) { - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(name_buf)); - } - - if (field_nodes != nullptr) { - jw_object_field(jw, "fields"); - jw_begin_array(jw); - for (size_t i = 0; i < field_nodes->length; i += 1) { - jw_array_elem(jw); - anal_dump_node_ref(ctx, field_nodes->at(i)); - } - jw_end_array(jw); - } - - if (is_var_args) { - jw_object_field(jw, "varArgs"); - jw_bool(jw, true); - } - - if (is_comptime) { - jw_object_field(jw, "comptime"); - jw_bool(jw, true); - } - - if (is_noalias) { - jw_object_field(jw, "noalias"); - jw_bool(jw, true); - } - - jw_end_object(jw); -} - -static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) { - JsonWriter *jw = &ctx->jw; - - jw_begin_object(jw); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, err->decl_node); - - jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&err->name)); - - jw_end_object(jw); -} - -static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) { - JsonWriter *jw = &ctx->jw; - - jw_begin_object(jw); - - jw_object_field(jw, "src"); - anal_dump_node_ref(ctx, fn->proto_node); - - jw_object_field(jw, "type"); - anal_dump_type_ref(ctx, fn->type_entry); - - auto entry = ctx->fn_decl_map.maybe_get(fn); - if (entry != nullptr) { - jw_object_field(jw, "decl"); - jw_int(jw, entry->value); - } - - jw_end_object(jw); -} - -void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) { - AnalDumpCtx ctx = {}; - ctx.g = g; - JsonWriter *jw = &ctx.jw; - jw_init(jw, f, one_indent, nl); - ctx.type_map.init(16); - ctx.pkg_map.init(16); - ctx.file_map.init(16); - ctx.decl_map.init(16); - ctx.node_map.init(16); - ctx.fn_map.init(16); - ctx.fn_decl_map.init(16); - ctx.err_map.init(16); - - jw_begin_object(jw); - - jw_object_field(jw, "typeKinds"); - jw_begin_array(jw); - for (size_t i = 0; i < type_id_len(); i += 1) { - jw_array_elem(jw); - jw_string(jw, type_id_name(type_id_at_index(i))); - } - jw_end_array(jw); - - jw_object_field(jw, "params"); - jw_begin_object(jw); - { - jw_object_field(jw, "zigVersion"); - jw_string(jw, stage2_version_string()); - - jw_object_field(jw, "builds"); - jw_begin_array(jw); - jw_array_elem(jw); - jw_begin_object(jw); - jw_object_field(jw, "target"); - Buf triple_buf = BUF_INIT; - target_triple_zig(&triple_buf, g->zig_target); - jw_string(jw, buf_ptr(&triple_buf)); - jw_end_object(jw); - jw_end_array(jw); - - jw_object_field(jw, "rootName"); - jw_string(jw, buf_ptr(g->root_out_name)); - } - jw_end_object(jw); - - jw_object_field(jw, "rootPkg"); - anal_dump_pkg_ref(&ctx, g->main_pkg); - - // FIXME: Remove this ugly workaround. - // Right now the code in docs/main.js relies on the root of the main package being itself. - g->main_pkg->package_table.put(buf_create_from_str("root"), g->main_pkg); - - // Poke the functions - for (size_t i = 0; i < g->fn_defs.length; i += 1) { - ZigFn *fn = g->fn_defs.at(i); - (void)anal_dump_get_fn_id(&ctx, fn); - } - - jw_object_field(jw, "calls"); - jw_begin_array(jw); - { - ZigList var_stack = {}; - - auto it = g->memoized_fn_eval_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - var_stack.resize(0); - ZigFn *fn = nullptr; - - Scope *scope = entry->key; - while (scope != nullptr) { - if (scope->id == ScopeIdVarDecl) { - ZigVar *var = reinterpret_cast(scope)->var; - var_stack.append(var); - } else if (scope->id == ScopeIdFnDef) { - fn = reinterpret_cast(scope)->fn_entry; - break; - } - scope = scope->parent; - } - ZigValue *result = entry->value; - - assert(fn != nullptr); - - jw_array_elem(jw); - jw_begin_object(jw); - - jw_object_field(jw, "fn"); - anal_dump_fn_ref(&ctx, fn); - - jw_object_field(jw, "result"); - { - jw_begin_object(jw); - - jw_object_field(jw, "type"); - anal_dump_type_ref(&ctx, result->type); - - jw_object_field(jw, "value"); - anal_dump_value(&ctx, scope->source_node, result->type, result); - - jw_end_object(jw); - } - - if (var_stack.length != 0) { - jw_object_field(jw, "args"); - jw_begin_array(jw); - - while (var_stack.length != 0) { - ZigVar *var = var_stack.pop(); - - jw_array_elem(jw); - jw_begin_object(jw); - - jw_object_field(jw, "type"); - anal_dump_type_ref(&ctx, var->var_type); - - jw_object_field(jw, "value"); - anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value); - - jw_end_object(jw); - } - jw_end_array(jw); - } - - jw_end_object(jw); - } - - var_stack.deinit(); - } - jw_end_array(jw); - - jw_object_field(jw, "packages"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) { - anal_dump_pkg(&ctx, ctx.pkg_list.at(i)); - } - jw_end_array(jw); - - jw_object_field(jw, "types"); - jw_begin_array(jw); - - for (uint32_t i = 0; i < ctx.type_list.length; i += 1) { - ZigType *ty = ctx.type_list.at(i); - anal_dump_type(&ctx, ty); - } - jw_end_array(jw); - - jw_object_field(jw, "decls"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.decl_list.length; i += 1) { - Tld *decl = ctx.decl_list.at(i); - anal_dump_decl(&ctx, decl); - } - jw_end_array(jw); - - jw_object_field(jw, "fns"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) { - ZigFn *fn = ctx.fn_list.at(i); - jw_array_elem(jw); - anal_dump_fn(&ctx, fn); - } - jw_end_array(jw); - - jw_object_field(jw, "errors"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.err_list.length; i += 1) { - const ErrorTableEntry *err = ctx.err_list.at(i); - jw_array_elem(jw); - anal_dump_err(&ctx, err); - } - jw_end_array(jw); - - jw_object_field(jw, "astNodes"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.node_list.length; i += 1) { - const AstNode *node = ctx.node_list.at(i); - jw_array_elem(jw); - anal_dump_node(&ctx, node); - } - jw_end_array(jw); - - jw_object_field(jw, "files"); - jw_begin_array(jw); - for (uint32_t i = 0; i < ctx.file_list.length; i += 1) { - Buf *file = ctx.file_list.at(i); - jw_array_elem(jw); - anal_dump_file(&ctx, file); - } - jw_end_array(jw); - - jw_end_object(jw); -} diff --git a/src/stage1/dump_analysis.hpp b/src/stage1/dump_analysis.hpp deleted file mode 100644 index 6d1c644ea2..0000000000 --- a/src/stage1/dump_analysis.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_DUMP_ANALYSIS_HPP -#define ZIG_DUMP_ANALYSIS_HPP - -#include "all_types.hpp" -#include - -void zig_print_stack_report(CodeGen *g, FILE *f); -void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl); - -#endif diff --git a/src/stage1/stage1.cpp b/src/stage1/stage1.cpp index 856bb61dcb..860d4ba4b1 100644 --- a/src/stage1/stage1.cpp +++ b/src/stage1/stage1.cpp @@ -74,8 +74,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { buf_init_from_mem(&g->asm_file_output_path, stage1->emit_asm_ptr, stage1->emit_asm_len); buf_init_from_mem(&g->llvm_ir_file_output_path, stage1->emit_llvm_ir_ptr, stage1->emit_llvm_ir_len); buf_init_from_mem(&g->bitcode_file_output_path, stage1->emit_bitcode_ptr, stage1->emit_bitcode_len); - buf_init_from_mem(&g->analysis_json_output_path, stage1->emit_analysis_json_ptr, stage1->emit_analysis_json_len); - buf_init_from_mem(&g->docs_output_path, stage1->emit_docs_ptr, stage1->emit_docs_len); if (stage1->builtin_zig_path_len != 0) { g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len); diff --git a/src/stage1/stage1.h b/src/stage1/stage1.h index 2b2e5a85b0..26b36db879 100644 --- a/src/stage1/stage1.h +++ b/src/stage1/stage1.h @@ -161,12 +161,6 @@ struct ZigStage1 { const char *emit_bitcode_ptr; size_t emit_bitcode_len; - const char *emit_analysis_json_ptr; - size_t emit_analysis_json_len; - - const char *emit_docs_ptr; - size_t emit_docs_len; - const char *builtin_zig_path_ptr; size_t builtin_zig_path_len; diff --git a/tools/merge_anal_dumps.zig b/tools/merge_anal_dumps.zig deleted file mode 100644 index 7c77e76a02..0000000000 --- a/tools/merge_anal_dumps.zig +++ /dev/null @@ -1,454 +0,0 @@ -const builtin = @import("builtin"); -const std = @import("std"); -const json = std.json; -const mem = std.mem; -const fieldIndex = std.meta.fieldIndex; -const TypeId = builtin.TypeId; - -pub fn main() anyerror!void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - - const allocator = arena.allocator(); - - const args = try std.process.argsAlloc(allocator); - - var parser: json.Parser = undefined; - var dump = Dump.init(allocator); - for (args[1..]) |arg| { - parser = json.Parser.init(allocator, false); - const json_text = try std.fs.cwd().readFileAlloc(allocator, arg, std.math.maxInt(usize)); - const tree = try parser.parse(json_text); - try dump.mergeJson(tree.root); - } - - const stdout = try std.io.getStdOut(); - try dump.render(stdout.writer()); -} - -/// AST source node -const Node = struct { - file: usize, - line: usize, - col: usize, - fields: []usize, - - fn hash(n: Node) u64 { - var hasher = std.hash.Wyhash.init(0); - std.hash.autoHash(&hasher, n.file); - std.hash.autoHash(&hasher, n.line); - std.hash.autoHash(&hasher, n.col); - return hasher.final(); - } - - fn eql(a: Node, b: Node) bool { - return a.file == b.file and - a.line == b.line and - a.col == b.col; - } -}; - -const Error = struct { - src: usize, - name: []const u8, - - fn hash(n: Error) u64 { - var hasher = std.hash.Wyhash.init(0); - std.hash.autoHash(&hasher, n.src); - return hasher.final(); - } - - fn eql(a: Error, b: Error) bool { - return a.src == b.src; - } -}; - -const simple_types = [_][]const u8{ - "Type", - "Void", - "Bool", - "NoReturn", - "ComptimeFloat", - "ComptimeInt", - "Undefined", - "Null", - "AnyFrame", - "EnumLiteral", -}; - -const Type = union(builtin.TypeId) { - Type, - Void, - Bool, - NoReturn, - ComptimeFloat, - ComptimeInt, - Undefined, - Null, - AnyFrame, - EnumLiteral, - - Int: Int, - Float: usize, // bits - - Vector: Array, - Optional: usize, // payload type index - Pointer: Pointer, - Array: Array, - - Struct, // TODO - ErrorUnion, // TODO - ErrorSet, // TODO - Enum, // TODO - Union, // TODO - Fn, // TODO - BoundFn, // TODO - Opaque, // TODO - Frame, // TODO - - const Int = struct { - bits: usize, - signed: bool, - }; - - const Pointer = struct { - elem: usize, - alignment: usize, - is_const: bool, - is_volatile: bool, - allow_zero: bool, - host_int_bytes: usize, - bit_offset_in_host: usize, - }; - - const Array = struct { - elem: usize, - len: usize, - }; - - fn hash(t: Type) u64 { - var hasher = std.hash.Wyhash.init(0); - std.hash.autoHash(&hasher, t); - return hasher.final(); - } - - fn eql(a: Type, b: Type) bool { - return std.meta.eql(a, b); - } -}; - -const Dump = struct { - zig_id: ?[]const u8 = null, - zig_version: ?[]const u8 = null, - root_name: ?[]const u8 = null, - targets: std.ArrayList([]const u8), - - file_list: std.ArrayList([]const u8), - file_map: FileMap, - - node_list: std.ArrayList(Node), - node_map: NodeMap, - - error_list: std.ArrayList(Error), - error_map: ErrorMap, - - type_list: std.ArrayList(Type), - type_map: TypeMap, - - const FileMap = std.StringHashMap(usize); - const NodeMap = std.HashMap(Node, usize, Node.hash, Node.eql, 80); - const ErrorMap = std.HashMap(Error, usize, Error.hash, Error.eql, 80); - const TypeMap = std.HashMap(Type, usize, Type.hash, Type.eql, 80); - - fn init(allocator: mem.Allocator) Dump { - return Dump{ - .targets = std.ArrayList([]const u8).init(allocator), - .file_list = std.ArrayList([]const u8).init(allocator), - .file_map = FileMap.init(allocator), - .node_list = std.ArrayList(Node).init(allocator), - .node_map = NodeMap.init(allocator), - .error_list = std.ArrayList(Error).init(allocator), - .error_map = ErrorMap.init(allocator), - .type_list = std.ArrayList(Type).init(allocator), - .type_map = TypeMap.init(allocator), - }; - } - - fn mergeJson(self: *Dump, root: json.Value) !void { - const params = &root.Object.get("params").?.value.Object; - const zig_id = params.get("zigId").?.value.String; - const zig_version = params.get("zigVersion").?.value.String; - const root_name = params.get("rootName").?.value.String; - try mergeSameStrings(&self.zig_id, zig_id); - try mergeSameStrings(&self.zig_version, zig_version); - try mergeSameStrings(&self.root_name, root_name); - - for (params.get("builds").?.value.Array.items) |json_build| { - const target = json_build.Object.get("target").?.value.String; - try self.targets.append(target); - } - - // Merge files. If the string matches, it's the same file. - const other_files = root.Object.get("files").?.value.Array.items; - var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a()); - for (other_files) |other_file, i| { - const gop = try self.file_map.getOrPut(other_file.String); - if (!gop.found_existing) { - gop.kv.value = self.file_list.items.len; - try self.file_list.append(other_file.String); - } - try other_file_to_mine.putNoClobber(i, gop.kv.value); - } - - // Merge AST nodes. If the file id, line, and column all match, it's the same AST node. - const other_ast_nodes = root.Object.get("astNodes").?.value.Array.items; - var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a()); - for (other_ast_nodes) |other_ast_node_json, i| { - const other_file_id = jsonObjInt(other_ast_node_json, "file"); - const other_node = Node{ - .line = jsonObjInt(other_ast_node_json, "line"), - .col = jsonObjInt(other_ast_node_json, "col"), - .file = other_file_to_mine.getValue(other_file_id).?, - .fields = ([*]usize)(undefined)[0..0], - }; - const gop = try self.node_map.getOrPut(other_node); - if (!gop.found_existing) { - gop.kv.value = self.node_list.items.len; - try self.node_list.append(other_node); - } - try other_ast_node_to_mine.putNoClobber(i, gop.kv.value); - } - // convert fields lists - for (other_ast_nodes) |other_ast_node_json, i| { - const my_node_index = other_ast_node_to_mine.get(i).?.value; - const my_node = &self.node_list.items[my_node_index]; - if (other_ast_node_json.Object.get("fields")) |fields_json_kv| { - const other_fields = fields_json_kv.value.Array.items; - my_node.fields = try self.a().alloc(usize, other_fields.len); - for (other_fields) |other_field_index, field_i| { - const other_index = @intCast(usize, other_field_index.Integer); - my_node.fields[field_i] = other_ast_node_to_mine.get(other_index).?.value; - } - } - } - - // Merge errors. If the AST Node matches, it's the same error value. - const other_errors = root.Object.get("errors").?.value.Array.items; - var other_error_to_mine = std.AutoHashMap(usize, usize).init(self.a()); - for (other_errors) |other_error_json, i| { - const other_src_id = jsonObjInt(other_error_json, "src"); - const other_error = Error{ - .src = other_ast_node_to_mine.getValue(other_src_id).?, - .name = other_error_json.Object.get("name").?.value.String, - }; - const gop = try self.error_map.getOrPut(other_error); - if (!gop.found_existing) { - gop.kv.value = self.error_list.items.len; - try self.error_list.append(other_error); - } - try other_error_to_mine.putNoClobber(i, gop.kv.value); - } - - // Merge types. Now it starts to get advanced. - // First we identify all the simple types and merge those. - // Example: void, type, noreturn - // We can also do integers and floats. - const other_types = root.Object.get("types").?.value.Array.items; - var other_types_to_mine = std.AutoHashMap(usize, usize).init(self.a()); - for (other_types) |other_type_json, i| { - const type_kind = jsonObjInt(other_type_json, "kind"); - switch (type_kind) { - fieldIndex(TypeId, "Int").? => { - var signed: bool = undefined; - var bits: usize = undefined; - if (other_type_json.Object.get("i")) |kv| { - signed = true; - bits = @intCast(usize, kv.value.Integer); - } else if (other_type_json.Object.get("u")) |kv| { - signed = false; - bits = @intCast(usize, kv.value.Integer); - } else { - unreachable; - } - const other_type = Type{ - .Int = Type.Int{ - .bits = bits, - .signed = signed, - }, - }; - try self.mergeOtherType(other_type, i, &other_types_to_mine); - }, - fieldIndex(TypeId, "Float").? => { - const other_type = Type{ - .Float = jsonObjInt(other_type_json, "bits"), - }; - try self.mergeOtherType(other_type, i, &other_types_to_mine); - }, - else => {}, - } - - inline for (simple_types) |simple_type_name| { - if (type_kind == std.meta.fieldIndex(builtin.TypeId, simple_type_name).?) { - const other_type = @unionInit(Type, simple_type_name, {}); - try self.mergeOtherType(other_type, i, &other_types_to_mine); - } - } - } - } - - fn mergeOtherType( - self: *Dump, - other_type: Type, - other_type_index: usize, - other_types_to_mine: *std.AutoHashMap(usize, usize), - ) !void { - const gop = try self.type_map.getOrPut(other_type); - if (!gop.found_existing) { - gop.kv.value = self.type_list.items.len; - try self.type_list.append(other_type); - } - try other_types_to_mine.putNoClobber(other_type_index, gop.kv.value); - } - - fn render(self: *Dump, stream: anytype) !void { - var jw = json.WriteStream(@TypeOf(stream).Child, 10).init(stream); - try jw.beginObject(); - - try jw.objectField("typeKinds"); - try jw.beginArray(); - inline for (@typeInfo(builtin.TypeId).Enum.fields) |field| { - try jw.arrayElem(); - try jw.emitString(field.name); - } - try jw.endArray(); - - try jw.objectField("params"); - try jw.beginObject(); - - try jw.objectField("zigId"); - try jw.emitString(self.zig_id.?); - - try jw.objectField("zigVersion"); - try jw.emitString(self.zig_version.?); - - try jw.objectField("rootName"); - try jw.emitString(self.root_name.?); - - try jw.objectField("builds"); - try jw.beginArray(); - for (self.targets.items) |target| { - try jw.arrayElem(); - try jw.beginObject(); - try jw.objectField("target"); - try jw.emitString(target); - try jw.endObject(); - } - try jw.endArray(); - - try jw.endObject(); - - try jw.objectField("types"); - try jw.beginArray(); - for (self.type_list.items) |t| { - try jw.arrayElem(); - try jw.beginObject(); - - try jw.objectField("kind"); - try jw.emitNumber(@enumToInt(builtin.TypeId(t))); - - switch (t) { - .Int => |int| { - if (int.signed) { - try jw.objectField("i"); - } else { - try jw.objectField("u"); - } - try jw.emitNumber(int.bits); - }, - .Float => |bits| { - try jw.objectField("bits"); - try jw.emitNumber(bits); - }, - - else => {}, - } - - try jw.endObject(); - } - try jw.endArray(); - - try jw.objectField("errors"); - try jw.beginArray(); - for (self.error_list.items) |zig_error| { - try jw.arrayElem(); - try jw.beginObject(); - - try jw.objectField("src"); - try jw.emitNumber(zig_error.src); - - try jw.objectField("name"); - try jw.emitString(zig_error.name); - - try jw.endObject(); - } - try jw.endArray(); - - try jw.objectField("astNodes"); - try jw.beginArray(); - for (self.node_list.items) |node| { - try jw.arrayElem(); - try jw.beginObject(); - - try jw.objectField("file"); - try jw.emitNumber(node.file); - - try jw.objectField("line"); - try jw.emitNumber(node.line); - - try jw.objectField("col"); - try jw.emitNumber(node.col); - - if (node.fields.len != 0) { - try jw.objectField("fields"); - try jw.beginArray(); - - for (node.fields) |field_node_index| { - try jw.arrayElem(); - try jw.emitNumber(field_node_index); - } - try jw.endArray(); - } - - try jw.endObject(); - } - try jw.endArray(); - - try jw.objectField("files"); - try jw.beginArray(); - for (self.file_list.items) |file| { - try jw.arrayElem(); - try jw.emitString(file); - } - try jw.endArray(); - - try jw.endObject(); - } - - fn a(self: Dump) mem.Allocator { - return self.targets.allocator; - } - - fn mergeSameStrings(opt_dest: *?[]const u8, src: []const u8) !void { - if (opt_dest.*) |dest| { - if (!mem.eql(u8, dest, src)) - return error.MismatchedDumps; - } else { - opt_dest.* = src; - } - } -}; - -fn jsonObjInt(json_val: json.Value, field: []const u8) usize { - const uncasted = json_val.Object.get(field).?.value.Integer; - return @intCast(usize, uncasted); -} -- cgit v1.2.3