| author | |
| committer | |
| log | 294bfb3321fe82371d57d39137615dddfef9af4b |
| tree | 660e976af4692eb01679448d0c4447ba648085f9 |
| parent | f2feb4e47aa7d74f26f5bda1f8383ccd0f54026a |
3 files changed, 102 insertions(+), 97 deletions(-)
src-self-hosted/Module.zig+50-4| ... | ... | @@ -18,12 +18,11 @@ const Inst = ir.Inst; |
| 18 | 18 | |
| 19 | 19 | /// General-purpose allocator. |
| 20 | 20 | allocator: *Allocator, |
| 21 | /// Module owns this resource. | |
| 21 | /// Pointer to externally managed resource. | |
| 22 | 22 | root_pkg: *Package, |
| 23 | 23 | /// Module owns this resource. |
| 24 | 24 | root_scope: *Scope.ZIRModule, |
| 25 | /// Pointer to externally managed resource. | |
| 26 | bin_file: *link.ElfFile, | |
| 25 | bin_file: link.ElfFile, | |
| 27 | 26 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of |
| 28 | 27 | /// Decl pointers to details about them being exported. |
| 29 | 28 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. |
| ... | ... | @@ -422,7 +421,55 @@ pub const AllErrors = struct { |
| 422 | 421 | } |
| 423 | 422 | }; |
| 424 | 423 | |
| 424 | pub const InitOptions = struct { | |
| 425 | target: std.Target, | |
| 426 | root_pkg: *Package, | |
| 427 | output_mode: std.builtin.OutputMode, | |
| 428 | bin_file_dir: ?std.fs.Dir = null, | |
| 429 | bin_file_path: []const u8, | |
| 430 | link_mode: ?std.builtin.LinkMode = null, | |
| 431 | object_format: ?std.builtin.ObjectFormat = null, | |
| 432 | optimize_mode: std.builtin.Mode = .Debug, | |
| 433 | }; | |
| 434 | ||
| 435 | pub fn init(gpa: *Allocator, options: InitOptions) !Module { | |
| 436 | const root_scope = try gpa.create(Scope.ZIRModule); | |
| 437 | errdefer gpa.destroy(root_scope); | |
| 438 | ||
| 439 | root_scope.* = .{ | |
| 440 | .sub_file_path = options.root_pkg.root_src_path, | |
| 441 | .source = .{ .unloaded = {} }, | |
| 442 | .contents = .{ .not_available = {} }, | |
| 443 | .status = .never_loaded, | |
| 444 | }; | |
| 445 | ||
| 446 | const bin_file_dir = options.bin_file_dir orelse std.fs.cwd(); | |
| 447 | var bin_file = try link.openBinFilePath(gpa, bin_file_dir, options.bin_file_path, .{ | |
| 448 | .target = options.target, | |
| 449 | .output_mode = options.output_mode, | |
| 450 | .link_mode = options.link_mode orelse .Static, | |
| 451 | .object_format = options.object_format orelse options.target.getObjectFormat(), | |
| 452 | }); | |
| 453 | errdefer bin_file.deinit(); | |
| 454 | ||
| 455 | return Module{ | |
| 456 | .allocator = gpa, | |
| 457 | .root_pkg = options.root_pkg, | |
| 458 | .root_scope = root_scope, | |
| 459 | .bin_file = bin_file, | |
| 460 | .optimize_mode = options.optimize_mode, | |
| 461 | .decl_table = std.AutoHashMap(Decl.Hash, *Decl).init(gpa), | |
| 462 | .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa), | |
| 463 | .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa), | |
| 464 | .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa), | |
| 465 | .failed_files = std.AutoHashMap(*Scope.ZIRModule, *ErrorMsg).init(gpa), | |
| 466 | .failed_exports = std.AutoHashMap(*Export, *ErrorMsg).init(gpa), | |
| 467 | .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa), | |
| 468 | }; | |
| 469 | } | |
| 470 | ||
| 425 | 471 | pub fn deinit(self: *Module) void { |
| 472 | self.bin_file.deinit(); | |
| 426 | 473 | const allocator = self.allocator; |
| 427 | 474 | self.work_queue.deinit(); |
| 428 | 475 | { |
| ... | ... | @@ -472,7 +519,6 @@ pub fn deinit(self: *Module) void { |
| 472 | 519 | } |
| 473 | 520 | self.export_owners.deinit(); |
| 474 | 521 | } |
| 475 | self.root_pkg.destroy(); | |
| 476 | 522 | { |
| 477 | 523 | self.root_scope.deinit(allocator); |
| 478 | 524 | allocator.destroy(self.root_scope); |
src-self-hosted/main.zig+14-35| ... | ... | @@ -157,7 +157,7 @@ fn buildOutputType( |
| 157 | 157 | var color: Color = .Auto; |
| 158 | 158 | var build_mode: std.builtin.Mode = .Debug; |
| 159 | 159 | var provided_name: ?[]const u8 = null; |
| 160 | var is_dynamic = false; | |
| 160 | var link_mode: ?std.builtin.LinkMode = null; | |
| 161 | 161 | var root_src_file: ?[]const u8 = null; |
| 162 | 162 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; |
| 163 | 163 | var strip = false; |
| ... | ... | @@ -286,7 +286,9 @@ fn buildOutputType( |
| 286 | 286 | } else if (mem.eql(u8, arg, "-fno-emit-zir")) { |
| 287 | 287 | emit_zir = .no; |
| 288 | 288 | } else if (mem.eql(u8, arg, "-dynamic")) { |
| 289 | is_dynamic = true; | |
| 289 | link_mode = .Dynamic; | |
| 290 | } else if (mem.eql(u8, arg, "-static")) { | |
| 291 | link_mode = .Static; | |
| 290 | 292 | } else if (mem.eql(u8, arg, "--strip")) { |
| 291 | 293 | strip = true; |
| 292 | 294 | } else if (mem.eql(u8, arg, "--debug-tokenize")) { |
| ... | ... | @@ -427,42 +429,19 @@ fn buildOutputType( |
| 427 | 429 | .yes => |p| p, |
| 428 | 430 | }; |
| 429 | 431 | |
| 430 | var bin_file = try link.openBinFilePath(gpa, fs.cwd(), bin_path, .{ | |
| 432 | const root_pkg = try Package.create(gpa, fs.cwd(), ".", src_path); | |
| 433 | defer root_pkg.destroy(); | |
| 434 | ||
| 435 | var module = try Module.init(gpa, .{ | |
| 431 | 436 | .target = target_info.target, |
| 432 | 437 | .output_mode = output_mode, |
| 433 | .link_mode = if (is_dynamic) .Dynamic else .Static, | |
| 434 | .object_format = object_format orelse target_info.target.getObjectFormat(), | |
| 438 | .root_pkg = root_pkg, | |
| 439 | .bin_file_dir = fs.cwd(), | |
| 440 | .bin_file_path = bin_path, | |
| 441 | .link_mode = link_mode, | |
| 442 | .object_format = object_format, | |
| 443 | .optimize_mode = build_mode, | |
| 435 | 444 | }); |
| 436 | defer bin_file.deinit(); | |
| 437 | ||
| 438 | var module = blk: { | |
| 439 | const root_pkg = try Package.create(gpa, fs.cwd(), ".", src_path); | |
| 440 | errdefer root_pkg.destroy(); | |
| 441 | ||
| 442 | const root_scope = try gpa.create(Module.Scope.ZIRModule); | |
| 443 | errdefer gpa.destroy(root_scope); | |
| 444 | root_scope.* = .{ | |
| 445 | .sub_file_path = root_pkg.root_src_path, | |
| 446 | .source = .{ .unloaded = {} }, | |
| 447 | .contents = .{ .not_available = {} }, | |
| 448 | .status = .never_loaded, | |
| 449 | }; | |
| 450 | ||
| 451 | break :blk Module{ | |
| 452 | .allocator = gpa, | |
| 453 | .root_pkg = root_pkg, | |
| 454 | .root_scope = root_scope, | |
| 455 | .bin_file = &bin_file, | |
| 456 | .optimize_mode = .Debug, | |
| 457 | .decl_table = std.AutoHashMap(Module.Decl.Hash, *Module.Decl).init(gpa), | |
| 458 | .decl_exports = std.AutoHashMap(*Module.Decl, []*Module.Export).init(gpa), | |
| 459 | .export_owners = std.AutoHashMap(*Module.Decl, []*Module.Export).init(gpa), | |
| 460 | .failed_decls = std.AutoHashMap(*Module.Decl, *Module.ErrorMsg).init(gpa), | |
| 461 | .failed_files = std.AutoHashMap(*Module.Scope.ZIRModule, *Module.ErrorMsg).init(gpa), | |
| 462 | .failed_exports = std.AutoHashMap(*Module.Export, *Module.ErrorMsg).init(gpa), | |
| 463 | .work_queue = std.fifo.LinearFifo(Module.WorkItem, .Dynamic).init(gpa), | |
| 464 | }; | |
| 465 | }; | |
| 466 | 445 | defer module.deinit(); |
| 467 | 446 | |
| 468 | 447 | const stdin = std.io.getStdIn().inStream(); |
src-self-hosted/test.zig+38-58| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const link = @import("link.zig"); |
| 3 | const ir = @import("ir.zig"); | |
| 3 | const Module = @import("Module.zig"); | |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | const zir = @import("zir.zig"); | |
| 6 | const Package = @import("Package.zig"); | |
| 5 | 7 | |
| 6 | 8 | test "self-hosted" { |
| 7 | 9 | var ctx: TestContext = undefined; |
| ... | ... | @@ -98,52 +100,31 @@ pub const TestContext = struct { |
| 98 | 100 | var tmp = std.testing.tmpDir(.{}); |
| 99 | 101 | defer tmp.cleanup(); |
| 100 | 102 | |
| 101 | var prg_node = root_node.start(case.name, 4); | |
| 103 | var prg_node = root_node.start(case.name, 2); | |
| 102 | 104 | prg_node.activate(); |
| 103 | 105 | defer prg_node.end(); |
| 104 | 106 | |
| 105 | var zir_module = x: { | |
| 106 | var parse_node = prg_node.start("parse", null); | |
| 107 | parse_node.activate(); | |
| 108 | defer parse_node.end(); | |
| 107 | const tmp_src_path = "test-case.zir"; | |
| 108 | try tmp.dir.writeFile(tmp_src_path, case.src); | |
| 109 | 109 | |
| 110 | break :x try ir.text.parse(allocator, case.src); | |
| 111 | }; | |
| 112 | defer zir_module.deinit(allocator); | |
| 113 | if (zir_module.errors.len != 0) { | |
| 114 | debugPrintErrors(case.src, zir_module.errors); | |
| 115 | return error.ParseFailure; | |
| 116 | } | |
| 110 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); | |
| 111 | defer root_pkg.destroy(); | |
| 117 | 112 | |
| 118 | var analyzed_module = x: { | |
| 119 | var analyze_node = prg_node.start("analyze", null); | |
| 120 | analyze_node.activate(); | |
| 121 | defer analyze_node.end(); | |
| 122 | ||
| 123 | break :x try ir.analyze(allocator, zir_module, .{ | |
| 113 | { | |
| 114 | var module = try Module.init(allocator, .{ | |
| 124 | 115 | .target = target, |
| 125 | 116 | .output_mode = .Exe, |
| 126 | .link_mode = .Static, | |
| 127 | 117 | .optimize_mode = .Debug, |
| 118 | .bin_file_dir = tmp.dir, | |
| 119 | .bin_file_path = "a.out", | |
| 120 | .root_pkg = root_pkg, | |
| 128 | 121 | }); |
| 129 | }; | |
| 130 | defer analyzed_module.deinit(allocator); | |
| 131 | if (analyzed_module.errors.len != 0) { | |
| 132 | debugPrintErrors(case.src, analyzed_module.errors); | |
| 133 | return error.ParseFailure; | |
| 134 | } | |
| 135 | ||
| 136 | var link_result = x: { | |
| 137 | var link_node = prg_node.start("link", null); | |
| 138 | link_node.activate(); | |
| 139 | defer link_node.end(); | |
| 122 | defer module.deinit(); | |
| 140 | 123 | |
| 141 | break :x try link.updateFilePath(allocator, analyzed_module, tmp.dir, "a.out"); | |
| 142 | }; | |
| 143 | defer link_result.deinit(allocator); | |
| 144 | if (link_result.errors.len != 0) { | |
| 145 | debugPrintErrors(case.src, link_result.errors); | |
| 146 | return error.LinkFailure; | |
| 124 | var module_node = prg_node.start("parse,analysis,codegen", null); | |
| 125 | module_node.activate(); | |
| 126 | try module.update(); | |
| 127 | module_node.end(); | |
| 147 | 128 | } |
| 148 | 129 | |
| 149 | 130 | var exec_result = x: { |
| ... | ... | @@ -178,38 +159,37 @@ pub const TestContext = struct { |
| 178 | 159 | case: ZIRTransformCase, |
| 179 | 160 | target: std.Target, |
| 180 | 161 | ) !void { |
| 181 | var prg_node = root_node.start(case.name, 4); | |
| 162 | var tmp = std.testing.tmpDir(.{}); | |
| 163 | defer tmp.cleanup(); | |
| 164 | ||
| 165 | var prg_node = root_node.start(case.name, 3); | |
| 182 | 166 | prg_node.activate(); |
| 183 | 167 | defer prg_node.end(); |
| 184 | 168 | |
| 185 | var parse_node = prg_node.start("parse", null); | |
| 186 | parse_node.activate(); | |
| 187 | var zir_module = try ir.text.parse(allocator, case.src); | |
| 188 | defer zir_module.deinit(allocator); | |
| 189 | if (zir_module.errors.len != 0) { | |
| 190 | debugPrintErrors(case.src, zir_module.errors); | |
| 191 | return error.ParseFailure; | |
| 192 | } | |
| 193 | parse_node.end(); | |
| 169 | const tmp_src_path = "test-case.zir"; | |
| 170 | try tmp.dir.writeFile(tmp_src_path, case.src); | |
| 194 | 171 | |
| 195 | var analyze_node = prg_node.start("analyze", null); | |
| 196 | analyze_node.activate(); | |
| 197 | var analyzed_module = try ir.analyze(allocator, zir_module, .{ | |
| 172 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); | |
| 173 | defer root_pkg.destroy(); | |
| 174 | ||
| 175 | var module = try Module.init(allocator, .{ | |
| 198 | 176 | .target = target, |
| 199 | 177 | .output_mode = .Obj, |
| 200 | .link_mode = .Static, | |
| 201 | 178 | .optimize_mode = .Debug, |
| 179 | .bin_file_dir = tmp.dir, | |
| 180 | .bin_file_path = "test-case.o", | |
| 181 | .root_pkg = root_pkg, | |
| 202 | 182 | }); |
| 203 | defer analyzed_module.deinit(allocator); | |
| 204 | if (analyzed_module.errors.len != 0) { | |
| 205 | debugPrintErrors(case.src, analyzed_module.errors); | |
| 206 | return error.ParseFailure; | |
| 207 | } | |
| 208 | analyze_node.end(); | |
| 183 | defer module.deinit(); | |
| 184 | ||
| 185 | var module_node = prg_node.start("parse/analysis/codegen", null); | |
| 186 | module_node.activate(); | |
| 187 | try module.update(); | |
| 188 | module_node.end(); | |
| 209 | 189 | |
| 210 | 190 | var emit_node = prg_node.start("emit", null); |
| 211 | 191 | emit_node.activate(); |
| 212 | var new_zir_module = try ir.text.emit_zir(allocator, analyzed_module); | |
| 192 | var new_zir_module = try zir.emit(allocator, module); | |
| 213 | 193 | defer new_zir_module.deinit(allocator); |
| 214 | 194 | emit_node.end(); |
| 215 | 195 |