authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-04 17:38:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-04 17:38:10-07:00
log75efb736ce704fc43bdbe2410989c2b275d855e6
tree9601aa3c7293a4791f0451a9a99a2319876e2fb0
parent31ad3af956231357ffa2c0fcfaf96a95c2fe1e8b

zig reduce: run results through astgen

and use that to fix up usused variable declarations and parameters that are caused by transformations. also add a transformation to replace global variable init with `undefined`.

2 files changed, 59 insertions(+), 6 deletions(-)

src/reduce.zig+53-3
......@@ -5,6 +5,8 @@ const assert = std.debug.assert;
55const fatal = @import("./main.zig").fatal;
66const Ast = std.zig.Ast;
77const Walk = @import("reduce/Walk.zig");
8const AstGen = @import("AstGen.zig");
9const Zir = @import("Zir.zig");
810
911const usage =
1012 \\zig reduce [options] ./checker root_source_file.zig [-- [argv]]
......@@ -39,8 +41,6 @@ const Interestingness = enum { interesting, unknown, boring };
3941// - add support for parsing the module flags
4042// - more fancy transformations
4143// - @import inlining of modules
42// - @import inlining of files
43// - deleting unused functions and other globals
4444// - removing statements or blocks of code
4545// - replacing operands of `and` and `or` with `true` and `false`
4646// - replacing if conditions with `true` and `false`
......@@ -109,6 +109,9 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
109109 var rendered = std.ArrayList(u8).init(gpa);
110110 defer rendered.deinit();
111111
112 var astgen_input = std.ArrayList(u8).init(gpa);
113 defer astgen_input.deinit();
114
112115 var tree = try parse(gpa, root_source_file_path);
113116 defer {
114117 gpa.free(tree.source);
......@@ -129,6 +132,10 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
129132
130133 var fixups: Ast.Fixups = .{};
131134 defer fixups.deinit(gpa);
135
136 var more_fixups: Ast.Fixups = .{};
137 defer more_fixups.deinit(gpa);
138
132139 var rng = std.rand.DefaultPrng.init(seed);
133140
134141 // 1. Walk the AST of the source file looking for independent
......@@ -171,8 +178,51 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
171178
172179 rendered.clearRetainingCapacity();
173180 try tree.renderToArrayList(&rendered, fixups);
174 try std.fs.cwd().writeFile(root_source_file_path, rendered.items);
175181
182 // The transformations we applied may have resulted in unused locals,
183 // in which case we would like to add the respective discards.
184 {
185 try astgen_input.resize(rendered.items.len);
186 @memcpy(astgen_input.items, rendered.items);
187 try astgen_input.append(0);
188 const source_with_null = astgen_input.items[0 .. astgen_input.items.len - 1 :0];
189 var astgen_tree = try Ast.parse(gpa, source_with_null, .zig);
190 defer astgen_tree.deinit(gpa);
191 if (astgen_tree.errors.len != 0) {
192 @panic("syntax errors occurred");
193 }
194 var zir = try AstGen.generate(gpa, astgen_tree);
195 defer zir.deinit(gpa);
196
197 if (zir.hasCompileErrors()) {
198 more_fixups.clearRetainingCapacity();
199 const payload_index = zir.extra[@intFromEnum(Zir.ExtraIndex.compile_errors)];
200 assert(payload_index != 0);
201 const header = zir.extraData(Zir.Inst.CompileErrors, payload_index);
202 var extra_index = header.end;
203 for (0..header.data.items_len) |_| {
204 const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);
205 extra_index = item.end;
206 const msg = zir.nullTerminatedString(item.data.msg);
207 if (mem.eql(u8, msg, "unused local constant") or
208 mem.eql(u8, msg, "unused local variable") or
209 mem.eql(u8, msg, "unused function parameter") or
210 mem.eql(u8, msg, "unused capture"))
211 {
212 const ident_token = item.data.token;
213 try more_fixups.unused_var_decls.put(gpa, ident_token, {});
214 } else {
215 std.debug.print("found other ZIR error: '{s}'\n", .{msg});
216 }
217 }
218 if (more_fixups.count() != 0) {
219 rendered.clearRetainingCapacity();
220 try astgen_tree.renderToArrayList(&rendered, more_fixups);
221 }
222 }
223 }
224
225 try std.fs.cwd().writeFile(root_source_file_path, rendered.items);
176226 //std.debug.print("trying this code:\n{s}\n", .{rendered.items});
177227
178228 const interestingness = try runCheck(arena, interestingness_argv.items);
src/reduce/Walk.zig+6-3
......@@ -581,9 +581,12 @@ fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.Var
581581 try walkExpression(w, var_decl.ast.section_node);
582582 }
583583
584 assert(var_decl.ast.init_node != 0);
585
586 return walkExpression(w, var_decl.ast.init_node);
584 if (var_decl.ast.init_node != 0) {
585 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
586 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
587 }
588 try walkExpression(w, var_decl.ast.init_node);
589 }
587590}
588591
589592fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {