authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-11 17:08:08-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-11 18:13:24-04:00
log30a555eed4d48b602b2c92a05c443e03c4660d48
tree00c94859ba91bd12419aa48b5bee66306d10070b
parent8aa20227ed45294da9606222d0b20eb922cecb2e
signaturelock-open Commit is signed but in an unrecognized format.

merge dumps tool: merging ast nodes

-fgenerate-docs is replaced ith -femit-docs -fno-emit-bin is added to prevent outputting binary

8 files changed, 154 insertions(+), 27 deletions(-)

lib/std/hash.zig+2
......@@ -3,6 +3,8 @@ pub const Adler32 = adler.Adler32;
33
44const auto_hash = @import("hash/auto_hash.zig");
55pub const autoHash = auto_hash.autoHash;
6pub const autoHashStrat = auto_hash.hash;
7pub const Strategy = auto_hash.HashStrategy;
68
79// pub for polynomials + generic crc32 construction
810pub const crc = @import("hash/crc.zig");
lib/std/hash_map.zig+10
......@@ -550,3 +550,13 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {
550550 }
551551 }.eql;
552552}
553
554pub fn getAutoHashStratFn(comptime K: type, comptime strategy: std.hash.Strategy) (fn (K) u32) {
555 return struct {
556 fn hash(key: K) u32 {
557 var hasher = Wyhash.init(0);
558 std.hash.autoHashStrat(&hasher, key, strategy);
559 return @truncate(u32, hasher.final());
560 }
561 }.hash;
562}
lib/std/json/write_stream.zig+11-4
......@@ -152,10 +152,17 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
152152 ) !void {
153153 assert(self.state[self.state_index] == State.Value);
154154 switch (@typeInfo(@typeOf(value))) {
155 .Int => |info| if (info.bits < 53 or (value < 4503599627370496 and value > -4503599627370496)) {
156 try self.stream.print("{}", value);
157 self.popState();
158 return;
155 .Int => |info| {
156 if (info.bits < 53) {
157 try self.stream.print("{}", value);
158 self.popState();
159 return;
160 }
161 if (value < 4503599627370496 and (!info.is_signed or value > -4503599627370496)) {
162 try self.stream.print("{}", value);
163 self.popState();
164 return;
165 }
159166 },
160167 .Float => if (@floatCast(f64, value) == value) {
161168 try self.stream.print("{}", value);
src/all_types.hpp+1
......@@ -2091,6 +2091,7 @@ struct CodeGen {
20912091 bool function_sections;
20922092 bool enable_dump_analysis;
20932093 bool enable_doc_generation;
2094 bool disable_bin_generation;
20942095
20952096 Buf *mmacosx_version_min;
20962097 Buf *mios_version_min;
src/codegen.cpp+5-1
......@@ -7586,6 +7586,8 @@ static void zig_llvm_emit_output(CodeGen *g) {
75867586 char *err_msg = nullptr;
75877587 switch (g->emit_file_type) {
75887588 case EmitFileTypeBinary:
7589 if (g->disable_bin_generation)
7590 return;
75897591 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
75907592 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
75917593 g->enable_time_report))
......@@ -10158,6 +10160,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1015810160 cache_bool(ch, g->function_sections);
1015910161 cache_bool(ch, g->enable_dump_analysis);
1016010162 cache_bool(ch, g->enable_doc_generation);
10163 cache_bool(ch, g->disable_bin_generation);
1016110164 cache_buf_opt(ch, g->mmacosx_version_min);
1016210165 cache_buf_opt(ch, g->mios_version_min);
1016310166 cache_usize(ch, g->version_major);
......@@ -10396,7 +10399,8 @@ void codegen_build_and_link(CodeGen *g) {
1039610399 // If there is more than one object, we have to link them (with -r).
1039710400 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,
1039810401 // then we have an object from C source that we must copy to the output dir which we do with a -r link.
10399 if (g->emit_file_type == EmitFileTypeBinary && (g->out_type != OutTypeObj || g->link_objects.length > 1 ||
10402 if (!g->disable_bin_generation && g->emit_file_type == EmitFileTypeBinary &&
10403 (g->out_type != OutTypeObj || g->link_objects.length > 1 ||
1040010404 (!need_llvm_module(g) && !g->enable_cache)))
1040110405 {
1040210406 codegen_link(g);
src/dump_analysis.cpp+9-9
......@@ -1309,15 +1309,6 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
13091309 }
13101310 jw_end_array(jw);
13111311
1312 jw_object_field(jw, "files");
1313 jw_begin_array(jw);
1314 for (uint32_t i = 0; i < ctx.file_list.length; i += 1) {
1315 Buf *file = ctx.file_list.at(i);
1316 jw_array_elem(jw);
1317 anal_dump_file(&ctx, file);
1318 }
1319 jw_end_array(jw);
1320
13211312 jw_object_field(jw, "errors");
13221313 jw_begin_array(jw);
13231314 for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {
......@@ -1336,5 +1327,14 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
13361327 }
13371328 jw_end_array(jw);
13381329
1330 jw_object_field(jw, "files");
1331 jw_begin_array(jw);
1332 for (uint32_t i = 0; i < ctx.file_list.length; i += 1) {
1333 Buf *file = ctx.file_list.at(i);
1334 jw_array_elem(jw);
1335 anal_dump_file(&ctx, file);
1336 }
1337 jw_end_array(jw);
1338
13391339 jw_end_object(jw);
13401340}
src/main.cpp+12-2
......@@ -65,7 +65,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
6565 " -ftime-report print timing diagnostics\n"
6666 " -fstack-report print stack size diagnostics\n"
6767 " -fdump-analysis write analysis.json file with type information\n"
68 " -fgenerate-docs create a docs/ dir with html documentation\n"
68 " -femit-docs create a docs/ dir with html documentation\n"
69 " -fno-emit-bin skip emitting machine code\n"
6970 " --libc [file] Provide a file which specifies libc paths\n"
7071 " --name [name] override output name\n"
7172 " --output-dir [dir] override output directory (defaults to cwd)\n"
......@@ -483,6 +484,7 @@ int main(int argc, char **argv) {
483484 bool stack_report = false;
484485 bool enable_dump_analysis = false;
485486 bool enable_doc_generation = false;
487 bool disable_bin_generation = false;
486488 const char *cache_dir = nullptr;
487489 CliPkg *cur_pkg = allocate<CliPkg>(1);
488490 BuildMode build_mode = BuildModeDebug;
......@@ -668,8 +670,10 @@ int main(int argc, char **argv) {
668670 stack_report = true;
669671 } else if (strcmp(arg, "-fdump-analysis") == 0) {
670672 enable_dump_analysis = true;
671 } else if (strcmp(arg, "-fgenerate-docs") == 0) {
673 } else if (strcmp(arg, "-femit-docs") == 0) {
672674 enable_doc_generation = true;
675 } else if (strcmp(arg, "-fno-emit-bin") == 0) {
676 disable_bin_generation = true;
673677 } else if (strcmp(arg, "--enable-valgrind") == 0) {
674678 valgrind_support = ValgrindSupportEnabled;
675679 } else if (strcmp(arg, "--disable-valgrind") == 0) {
......@@ -1148,6 +1152,7 @@ int main(int argc, char **argv) {
11481152 g->enable_stack_report = stack_report;
11491153 g->enable_dump_analysis = enable_dump_analysis;
11501154 g->enable_doc_generation = enable_doc_generation;
1155 g->disable_bin_generation = disable_bin_generation;
11511156 codegen_set_out_name(g, buf_out_name);
11521157 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
11531158 g->want_single_threaded = want_single_threaded;
......@@ -1290,6 +1295,11 @@ int main(int argc, char **argv) {
12901295 zig_print_stack_report(g, stdout);
12911296 }
12921297
1298 if (g->disable_bin_generation) {
1299 fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");
1300 return 0;
1301 }
1302
12931303 Buf *test_exe_path_unresolved = &g->output_file_path;
12941304 Buf *test_exe_path = buf_alloc();
12951305 *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
tools/merge_anal_dumps.zig+104-11
......@@ -24,19 +24,49 @@ pub fn main() anyerror!void {
2424 try dump.render(&stdout.outStream().stream);
2525}
2626
27/// AST source node
28const Node = struct {
29 file: usize,
30 line: usize,
31 col: usize,
32 fields: []usize,
33
34 fn hash(n: Node) u32 {
35 var hasher = std.hash.Wyhash.init(0);
36 std.hash.autoHash(&hasher, n.file);
37 std.hash.autoHash(&hasher, n.line);
38 std.hash.autoHash(&hasher, n.col);
39 return @truncate(u32, hasher.final());
40 }
41
42 fn eql(a: Node, b: Node) bool {
43 return a.file == b.file and
44 a.line == b.line and
45 a.col == b.col;
46 }
47};
48
2749const Dump = struct {
2850 zig_id: ?[]const u8 = null,
2951 zig_version: ?[]const u8 = null,
3052 root_name: ?[]const u8 = null,
3153 targets: std.ArrayList([]const u8),
32 files_list: std.ArrayList([]const u8),
33 files_map: std.StringHashMap(usize),
54
55 const FileMap = std.StringHashMap(usize);
56 file_list: std.ArrayList([]const u8),
57 file_map: FileMap,
58
59 const NodeMap = std.HashMap(Node, usize, Node.hash, Node.eql);
60 node_list: std.ArrayList(Node),
61 node_map: NodeMap,
3462
3563 fn init(allocator: *mem.Allocator) Dump {
3664 return Dump{
3765 .targets = std.ArrayList([]const u8).init(allocator),
38 .files_list = std.ArrayList([]const u8).init(allocator),
39 .files_map = std.StringHashMap(usize).init(allocator),
66 .file_list = std.ArrayList([]const u8).init(allocator),
67 .file_map = FileMap.init(allocator),
68 .node_list = std.ArrayList(Node).init(allocator),
69 .node_map = NodeMap.init(allocator),
4070 };
4171 }
4272
......@@ -56,17 +86,45 @@ const Dump = struct {
5686 const other_files = root.Object.get("files").?.value.Array.toSliceConst();
5787 var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a());
5888 for (other_files) |other_file, i| {
59 const gop = try self.files_map.getOrPut(other_file.String);
60 if (gop.found_existing) {
61 try other_file_to_mine.putNoClobber(i, gop.kv.value);
62 } else {
63 gop.kv.value = self.files_list.len;
64 try self.files_list.append(other_file.String);
89 const gop = try self.file_map.getOrPut(other_file.String);
90 if (!gop.found_existing) {
91 gop.kv.value = self.file_list.len;
92 try self.file_list.append(other_file.String);
6593 }
94 try other_file_to_mine.putNoClobber(i, gop.kv.value);
6695 }
6796
97 // Merge ast nodes
6898 const other_ast_nodes = root.Object.get("astNodes").?.value.Array.toSliceConst();
6999 var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a());
100 for (other_ast_nodes) |other_ast_node_json, i| {
101 const other_file_id = jsonObjInt(other_ast_node_json, "file");
102 const other_node = Node{
103 .line = jsonObjInt(other_ast_node_json, "line"),
104 .col = jsonObjInt(other_ast_node_json, "col"),
105 .file = other_file_to_mine.getValue(other_file_id).?,
106 .fields = ([*]usize)(undefined)[0..0],
107 };
108 const gop = try self.node_map.getOrPut(other_node);
109 if (!gop.found_existing) {
110 gop.kv.value = self.node_list.len;
111 try self.node_list.append(other_node);
112 }
113 try other_ast_node_to_mine.putNoClobber(i, gop.kv.value);
114 }
115 // convert fields lists
116 for (other_ast_nodes) |other_ast_node_json, i| {
117 const my_node_index = other_ast_node_to_mine.get(i).?.value;
118 const my_node = &self.node_list.toSlice()[my_node_index];
119 if (other_ast_node_json.Object.get("fields")) |fields_json_kv| {
120 const other_fields = fields_json_kv.value.Array.toSliceConst();
121 my_node.fields = try self.a().alloc(usize, other_fields.len);
122 for (other_fields) |other_field_index, field_i| {
123 const other_index = @intCast(usize, other_field_index.Integer);
124 my_node.fields[field_i] = other_ast_node_to_mine.get(other_index).?.value;
125 }
126 }
127 }
70128 }
71129
72130 fn render(self: *Dump, stream: var) !void {
......@@ -81,9 +139,39 @@ const Dump = struct {
81139 }
82140 try jw.endArray();
83141
142 try jw.objectField("astNodes");
143 try jw.beginArray();
144 for (self.node_list.toSliceConst()) |node| {
145 try jw.arrayElem();
146 try jw.beginObject();
147
148 try jw.objectField("file");
149 try jw.emitNumber(node.file);
150
151 try jw.objectField("line");
152 try jw.emitNumber(node.line);
153
154 try jw.objectField("col");
155 try jw.emitNumber(node.col);
156
157 if (node.fields.len != 0) {
158 try jw.objectField("fields");
159 try jw.beginArray();
160
161 for (node.fields) |field_node_index| {
162 try jw.arrayElem();
163 try jw.emitNumber(field_node_index);
164 }
165 try jw.endArray();
166 }
167
168 try jw.endObject();
169 }
170 try jw.endArray();
171
84172 try jw.objectField("files");
85173 try jw.beginArray();
86 for (self.files_list.toSliceConst()) |file| {
174 for (self.file_list.toSliceConst()) |file| {
87175 try jw.arrayElem();
88176 try jw.emitString(file);
89177 }
......@@ -105,3 +193,8 @@ const Dump = struct {
105193 }
106194 }
107195};
196
197fn jsonObjInt(json_val: json.Value, field: []const u8) usize {
198 const uncasted = json_val.Object.get(field).?.value.Integer;
199 return @intCast(usize, uncasted);
200}