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;...@@ -3,6 +3,8 @@ pub const Adler32 = adler.Adler32;
33
4const auto_hash = @import("hash/auto_hash.zig");4const auto_hash = @import("hash/auto_hash.zig");
5pub const autoHash = auto_hash.autoHash;5pub const autoHash = auto_hash.autoHash;
6pub const autoHashStrat = auto_hash.hash;
7pub const Strategy = auto_hash.HashStrategy;
68
7// pub for polynomials + generic crc32 construction9// pub for polynomials + generic crc32 construction
8pub const crc = @import("hash/crc.zig");10pub 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) {...@@ -550,3 +550,13 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {
550 }550 }
551 }.eql;551 }.eql;
552}552}
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 {...@@ -152,10 +152,17 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
152 ) !void {152 ) !void {
153 assert(self.state[self.state_index] == State.Value);153 assert(self.state[self.state_index] == State.Value);
154 switch (@typeInfo(@typeOf(value))) {154 switch (@typeInfo(@typeOf(value))) {
155 .Int => |info| if (info.bits < 53 or (value < 4503599627370496 and value > -4503599627370496)) {155 .Int => |info| {
156 try self.stream.print("{}", value);156 if (info.bits < 53) {
157 self.popState();157 try self.stream.print("{}", value);
158 return;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 }
159 },166 },
160 .Float => if (@floatCast(f64, value) == value) {167 .Float => if (@floatCast(f64, value) == value) {
161 try self.stream.print("{}", value);168 try self.stream.print("{}", value);
src/all_types.hpp+1
...@@ -2091,6 +2091,7 @@ struct CodeGen {...@@ -2091,6 +2091,7 @@ struct CodeGen {
2091 bool function_sections;2091 bool function_sections;
2092 bool enable_dump_analysis;2092 bool enable_dump_analysis;
2093 bool enable_doc_generation;2093 bool enable_doc_generation;
2094 bool disable_bin_generation;
20942095
2095 Buf *mmacosx_version_min;2096 Buf *mmacosx_version_min;
2096 Buf *mios_version_min;2097 Buf *mios_version_min;
src/codegen.cpp+5-1
...@@ -7586,6 +7586,8 @@ static void zig_llvm_emit_output(CodeGen *g) {...@@ -7586,6 +7586,8 @@ static void zig_llvm_emit_output(CodeGen *g) {
7586 char *err_msg = nullptr;7586 char *err_msg = nullptr;
7587 switch (g->emit_file_type) {7587 switch (g->emit_file_type) {
7588 case EmitFileTypeBinary:7588 case EmitFileTypeBinary:
7589 if (g->disable_bin_generation)
7590 return;
7589 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),7591 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7590 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,7592 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
7591 g->enable_time_report))7593 g->enable_time_report))
...@@ -10158,6 +10160,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10158,6 +10160,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10158 cache_bool(ch, g->function_sections);10160 cache_bool(ch, g->function_sections);
10159 cache_bool(ch, g->enable_dump_analysis);10161 cache_bool(ch, g->enable_dump_analysis);
10160 cache_bool(ch, g->enable_doc_generation);10162 cache_bool(ch, g->enable_doc_generation);
10163 cache_bool(ch, g->disable_bin_generation);
10161 cache_buf_opt(ch, g->mmacosx_version_min);10164 cache_buf_opt(ch, g->mmacosx_version_min);
10162 cache_buf_opt(ch, g->mios_version_min);10165 cache_buf_opt(ch, g->mios_version_min);
10163 cache_usize(ch, g->version_major);10166 cache_usize(ch, g->version_major);
...@@ -10396,7 +10399,8 @@ void codegen_build_and_link(CodeGen *g) {...@@ -10396,7 +10399,8 @@ void codegen_build_and_link(CodeGen *g) {
10396 // If there is more than one object, we have to link them (with -r).10399 // If there is more than one object, we have to link them (with -r).
10397 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,10400 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,
10398 // then we have an object from C source that we must copy to the output dir which we do with a -r link.10401 // 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 ||
10400 (!need_llvm_module(g) && !g->enable_cache)))10404 (!need_llvm_module(g) && !g->enable_cache)))
10401 {10405 {
10402 codegen_link(g);10406 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...@@ -1309,15 +1309,6 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
1309 }1309 }
1310 jw_end_array(jw);1310 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
1321 jw_object_field(jw, "errors");1312 jw_object_field(jw, "errors");
1322 jw_begin_array(jw);1313 jw_begin_array(jw);
1323 for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {1314 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...@@ -1336,5 +1327,14 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
1336 }1327 }
1337 jw_end_array(jw);1328 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
1339 jw_end_object(jw);1339 jw_end_object(jw);
1340}1340}
src/main.cpp+12-2
...@@ -65,7 +65,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -65,7 +65,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
65 " -ftime-report print timing diagnostics\n"65 " -ftime-report print timing diagnostics\n"
66 " -fstack-report print stack size diagnostics\n"66 " -fstack-report print stack size diagnostics\n"
67 " -fdump-analysis write analysis.json file with type information\n"67 " -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"
69 " --libc [file] Provide a file which specifies libc paths\n"70 " --libc [file] Provide a file which specifies libc paths\n"
70 " --name [name] override output name\n"71 " --name [name] override output name\n"
71 " --output-dir [dir] override output directory (defaults to cwd)\n"72 " --output-dir [dir] override output directory (defaults to cwd)\n"
...@@ -483,6 +484,7 @@ int main(int argc, char **argv) {...@@ -483,6 +484,7 @@ int main(int argc, char **argv) {
483 bool stack_report = false;484 bool stack_report = false;
484 bool enable_dump_analysis = false;485 bool enable_dump_analysis = false;
485 bool enable_doc_generation = false;486 bool enable_doc_generation = false;
487 bool disable_bin_generation = false;
486 const char *cache_dir = nullptr;488 const char *cache_dir = nullptr;
487 CliPkg *cur_pkg = allocate<CliPkg>(1);489 CliPkg *cur_pkg = allocate<CliPkg>(1);
488 BuildMode build_mode = BuildModeDebug;490 BuildMode build_mode = BuildModeDebug;
...@@ -668,8 +670,10 @@ int main(int argc, char **argv) {...@@ -668,8 +670,10 @@ int main(int argc, char **argv) {
668 stack_report = true;670 stack_report = true;
669 } else if (strcmp(arg, "-fdump-analysis") == 0) {671 } else if (strcmp(arg, "-fdump-analysis") == 0) {
670 enable_dump_analysis = true;672 enable_dump_analysis = true;
671 } else if (strcmp(arg, "-fgenerate-docs") == 0) {673 } else if (strcmp(arg, "-femit-docs") == 0) {
672 enable_doc_generation = true;674 enable_doc_generation = true;
675 } else if (strcmp(arg, "-fno-emit-bin") == 0) {
676 disable_bin_generation = true;
673 } else if (strcmp(arg, "--enable-valgrind") == 0) {677 } else if (strcmp(arg, "--enable-valgrind") == 0) {
674 valgrind_support = ValgrindSupportEnabled;678 valgrind_support = ValgrindSupportEnabled;
675 } else if (strcmp(arg, "--disable-valgrind") == 0) {679 } else if (strcmp(arg, "--disable-valgrind") == 0) {
...@@ -1148,6 +1152,7 @@ int main(int argc, char **argv) {...@@ -1148,6 +1152,7 @@ int main(int argc, char **argv) {
1148 g->enable_stack_report = stack_report;1152 g->enable_stack_report = stack_report;
1149 g->enable_dump_analysis = enable_dump_analysis;1153 g->enable_dump_analysis = enable_dump_analysis;
1150 g->enable_doc_generation = enable_doc_generation;1154 g->enable_doc_generation = enable_doc_generation;
1155 g->disable_bin_generation = disable_bin_generation;
1151 codegen_set_out_name(g, buf_out_name);1156 codegen_set_out_name(g, buf_out_name);
1152 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);1157 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
1153 g->want_single_threaded = want_single_threaded;1158 g->want_single_threaded = want_single_threaded;
...@@ -1290,6 +1295,11 @@ int main(int argc, char **argv) {...@@ -1290,6 +1295,11 @@ int main(int argc, char **argv) {
1290 zig_print_stack_report(g, stdout);1295 zig_print_stack_report(g, stdout);
1291 }1296 }
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
1293 Buf *test_exe_path_unresolved = &g->output_file_path;1303 Buf *test_exe_path_unresolved = &g->output_file_path;
1294 Buf *test_exe_path = buf_alloc();1304 Buf *test_exe_path = buf_alloc();
1295 *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);1305 *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 {...@@ -24,19 +24,49 @@ pub fn main() anyerror!void {
24 try dump.render(&stdout.outStream().stream);24 try dump.render(&stdout.outStream().stream);
25}25}
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
27const Dump = struct {49const Dump = struct {
28 zig_id: ?[]const u8 = null,50 zig_id: ?[]const u8 = null,
29 zig_version: ?[]const u8 = null,51 zig_version: ?[]const u8 = null,
30 root_name: ?[]const u8 = null,52 root_name: ?[]const u8 = null,
31 targets: std.ArrayList([]const u8),53 targets: std.ArrayList([]const u8),
32 files_list: std.ArrayList([]const u8),54
33 files_map: std.StringHashMap(usize),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
35 fn init(allocator: *mem.Allocator) Dump {63 fn init(allocator: *mem.Allocator) Dump {
36 return Dump{64 return Dump{
37 .targets = std.ArrayList([]const u8).init(allocator),65 .targets = std.ArrayList([]const u8).init(allocator),
38 .files_list = std.ArrayList([]const u8).init(allocator),66 .file_list = std.ArrayList([]const u8).init(allocator),
39 .files_map = std.StringHashMap(usize).init(allocator),67 .file_map = FileMap.init(allocator),
68 .node_list = std.ArrayList(Node).init(allocator),
69 .node_map = NodeMap.init(allocator),
40 };70 };
41 }71 }
4272
...@@ -56,17 +86,45 @@ const Dump = struct {...@@ -56,17 +86,45 @@ const Dump = struct {
56 const other_files = root.Object.get("files").?.value.Array.toSliceConst();86 const other_files = root.Object.get("files").?.value.Array.toSliceConst();
57 var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a());87 var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a());
58 for (other_files) |other_file, i| {88 for (other_files) |other_file, i| {
59 const gop = try self.files_map.getOrPut(other_file.String);89 const gop = try self.file_map.getOrPut(other_file.String);
60 if (gop.found_existing) {90 if (!gop.found_existing) {
61 try other_file_to_mine.putNoClobber(i, gop.kv.value);91 gop.kv.value = self.file_list.len;
62 } else {92 try self.file_list.append(other_file.String);
63 gop.kv.value = self.files_list.len;
64 try self.files_list.append(other_file.String);
65 }93 }
94 try other_file_to_mine.putNoClobber(i, gop.kv.value);
66 }95 }
6796
97 // Merge ast nodes
68 const other_ast_nodes = root.Object.get("astNodes").?.value.Array.toSliceConst();98 const other_ast_nodes = root.Object.get("astNodes").?.value.Array.toSliceConst();
69 var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a());99 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 }
70 }128 }
71129
72 fn render(self: *Dump, stream: var) !void {130 fn render(self: *Dump, stream: var) !void {
...@@ -81,9 +139,39 @@ const Dump = struct {...@@ -81,9 +139,39 @@ const Dump = struct {
81 }139 }
82 try jw.endArray();140 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
84 try jw.objectField("files");172 try jw.objectField("files");
85 try jw.beginArray();173 try jw.beginArray();
86 for (self.files_list.toSliceConst()) |file| {174 for (self.file_list.toSliceConst()) |file| {
87 try jw.arrayElem();175 try jw.arrayElem();
88 try jw.emitString(file);176 try jw.emitString(file);
89 }177 }
...@@ -105,3 +193,8 @@ const Dump = struct {...@@ -105,3 +193,8 @@ const Dump = struct {
105 }193 }
106 }194 }
107};195};
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}