| 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,12 +18,11 @@ const Inst = ir.Inst; |
| 18 | 18 | ||
| 19 | /// General-purpose allocator. | 19 | /// General-purpose allocator. |
| 20 | allocator: *Allocator, | 20 | allocator: *Allocator, |
| 21 | /// Module owns this resource. | 21 | /// Pointer to externally managed resource. |
| 22 | root_pkg: *Package, | 22 | root_pkg: *Package, |
| 23 | /// Module owns this resource. | 23 | /// Module owns this resource. |
| 24 | root_scope: *Scope.ZIRModule, | 24 | root_scope: *Scope.ZIRModule, |
| 25 | /// Pointer to externally managed resource. | 25 | bin_file: link.ElfFile, |
| 26 | bin_file: *link.ElfFile, | ||
| 27 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of | 26 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of |
| 28 | /// Decl pointers to details about them being exported. | 27 | /// Decl pointers to details about them being exported. |
| 29 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. | 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,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 | pub fn deinit(self: *Module) void { | 471 | pub fn deinit(self: *Module) void { |
| 472 | self.bin_file.deinit(); | ||
| 426 | const allocator = self.allocator; | 473 | const allocator = self.allocator; |
| 427 | self.work_queue.deinit(); | 474 | self.work_queue.deinit(); |
| 428 | { | 475 | { |
| ... | @@ -472,7 +519,6 @@ pub fn deinit(self: *Module) void { | ... | @@ -472,7 +519,6 @@ pub fn deinit(self: *Module) void { |
| 472 | } | 519 | } |
| 473 | self.export_owners.deinit(); | 520 | self.export_owners.deinit(); |
| 474 | } | 521 | } |
| 475 | self.root_pkg.destroy(); | ||
| 476 | { | 522 | { |
| 477 | self.root_scope.deinit(allocator); | 523 | self.root_scope.deinit(allocator); |
| 478 | allocator.destroy(self.root_scope); | 524 | allocator.destroy(self.root_scope); |
src-self-hosted/main.zig+14-35| ... | @@ -157,7 +157,7 @@ fn buildOutputType( | ... | @@ -157,7 +157,7 @@ fn buildOutputType( |
| 157 | var color: Color = .Auto; | 157 | var color: Color = .Auto; |
| 158 | var build_mode: std.builtin.Mode = .Debug; | 158 | var build_mode: std.builtin.Mode = .Debug; |
| 159 | var provided_name: ?[]const u8 = null; | 159 | var provided_name: ?[]const u8 = null; |
| 160 | var is_dynamic = false; | 160 | var link_mode: ?std.builtin.LinkMode = null; |
| 161 | var root_src_file: ?[]const u8 = null; | 161 | var root_src_file: ?[]const u8 = null; |
| 162 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; | 162 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; |
| 163 | var strip = false; | 163 | var strip = false; |
| ... | @@ -286,7 +286,9 @@ fn buildOutputType( | ... | @@ -286,7 +286,9 @@ fn buildOutputType( |
| 286 | } else if (mem.eql(u8, arg, "-fno-emit-zir")) { | 286 | } else if (mem.eql(u8, arg, "-fno-emit-zir")) { |
| 287 | emit_zir = .no; | 287 | emit_zir = .no; |
| 288 | } else if (mem.eql(u8, arg, "-dynamic")) { | 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 | } else if (mem.eql(u8, arg, "--strip")) { | 292 | } else if (mem.eql(u8, arg, "--strip")) { |
| 291 | strip = true; | 293 | strip = true; |
| 292 | } else if (mem.eql(u8, arg, "--debug-tokenize")) { | 294 | } else if (mem.eql(u8, arg, "--debug-tokenize")) { |
| ... | @@ -427,42 +429,19 @@ fn buildOutputType( | ... | @@ -427,42 +429,19 @@ fn buildOutputType( |
| 427 | .yes => |p| p, | 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 | .target = target_info.target, | 436 | .target = target_info.target, |
| 432 | .output_mode = output_mode, | 437 | .output_mode = output_mode, |
| 433 | .link_mode = if (is_dynamic) .Dynamic else .Static, | 438 | .root_pkg = root_pkg, |
| 434 | .object_format = object_format orelse target_info.target.getObjectFormat(), | 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 | defer module.deinit(); | 445 | defer module.deinit(); |
| 467 | 446 | ||
| 468 | const stdin = std.io.getStdIn().inStream(); | 447 | const stdin = std.io.getStdIn().inStream(); |
src-self-hosted/test.zig+38-58| ... | @@ -1,7 +1,9 @@ | ... | @@ -1,7 +1,9 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const link = @import("link.zig"); | 2 | const link = @import("link.zig"); |
| 3 | const ir = @import("ir.zig"); | 3 | const Module = @import("Module.zig"); |
| 4 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 5 | const zir = @import("zir.zig"); | ||
| 6 | const Package = @import("Package.zig"); | ||
| 5 | 7 | ||
| 6 | test "self-hosted" { | 8 | test "self-hosted" { |
| 7 | var ctx: TestContext = undefined; | 9 | var ctx: TestContext = undefined; |
| ... | @@ -98,52 +100,31 @@ pub const TestContext = struct { | ... | @@ -98,52 +100,31 @@ pub const TestContext = struct { |
| 98 | var tmp = std.testing.tmpDir(.{}); | 100 | var tmp = std.testing.tmpDir(.{}); |
| 99 | defer tmp.cleanup(); | 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 | prg_node.activate(); | 104 | prg_node.activate(); |
| 103 | defer prg_node.end(); | 105 | defer prg_node.end(); |
| 104 | 106 | ||
| 105 | var zir_module = x: { | 107 | const tmp_src_path = "test-case.zir"; |
| 106 | var parse_node = prg_node.start("parse", null); | 108 | try tmp.dir.writeFile(tmp_src_path, case.src); |
| 107 | parse_node.activate(); | ||
| 108 | defer parse_node.end(); | ||
| 109 | 109 | ||
| 110 | break :x try ir.text.parse(allocator, case.src); | 110 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); |
| 111 | }; | 111 | defer root_pkg.destroy(); |
| 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 | } | ||
| 117 | 112 | ||
| 118 | var analyzed_module = x: { | 113 | { |
| 119 | var analyze_node = prg_node.start("analyze", null); | 114 | var module = try Module.init(allocator, .{ |
| 120 | analyze_node.activate(); | ||
| 121 | defer analyze_node.end(); | ||
| 122 | |||
| 123 | break :x try ir.analyze(allocator, zir_module, .{ | ||
| 124 | .target = target, | 115 | .target = target, |
| 125 | .output_mode = .Exe, | 116 | .output_mode = .Exe, |
| 126 | .link_mode = .Static, | ||
| 127 | .optimize_mode = .Debug, | 117 | .optimize_mode = .Debug, |
| 118 | .bin_file_dir = tmp.dir, | ||
| 119 | .bin_file_path = "a.out", | ||
| 120 | .root_pkg = root_pkg, | ||
| 128 | }); | 121 | }); |
| 129 | }; | 122 | defer module.deinit(); |
| 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(); | ||
| 140 | 123 | ||
| 141 | break :x try link.updateFilePath(allocator, analyzed_module, tmp.dir, "a.out"); | 124 | var module_node = prg_node.start("parse,analysis,codegen", null); |
| 142 | }; | 125 | module_node.activate(); |
| 143 | defer link_result.deinit(allocator); | 126 | try module.update(); |
| 144 | if (link_result.errors.len != 0) { | 127 | module_node.end(); |
| 145 | debugPrintErrors(case.src, link_result.errors); | ||
| 146 | return error.LinkFailure; | ||
| 147 | } | 128 | } |
| 148 | 129 | ||
| 149 | var exec_result = x: { | 130 | var exec_result = x: { |
| ... | @@ -178,38 +159,37 @@ pub const TestContext = struct { | ... | @@ -178,38 +159,37 @@ pub const TestContext = struct { |
| 178 | case: ZIRTransformCase, | 159 | case: ZIRTransformCase, |
| 179 | target: std.Target, | 160 | target: std.Target, |
| 180 | ) !void { | 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 | prg_node.activate(); | 166 | prg_node.activate(); |
| 183 | defer prg_node.end(); | 167 | defer prg_node.end(); |
| 184 | 168 | ||
| 185 | var parse_node = prg_node.start("parse", null); | 169 | const tmp_src_path = "test-case.zir"; |
| 186 | parse_node.activate(); | 170 | try tmp.dir.writeFile(tmp_src_path, case.src); |
| 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(); | ||
| 194 | 171 | ||
| 195 | var analyze_node = prg_node.start("analyze", null); | 172 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); |
| 196 | analyze_node.activate(); | 173 | defer root_pkg.destroy(); |
| 197 | var analyzed_module = try ir.analyze(allocator, zir_module, .{ | 174 | |
| 175 | var module = try Module.init(allocator, .{ | ||
| 198 | .target = target, | 176 | .target = target, |
| 199 | .output_mode = .Obj, | 177 | .output_mode = .Obj, |
| 200 | .link_mode = .Static, | ||
| 201 | .optimize_mode = .Debug, | 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); | 183 | defer module.deinit(); |
| 204 | if (analyzed_module.errors.len != 0) { | 184 | |
| 205 | debugPrintErrors(case.src, analyzed_module.errors); | 185 | var module_node = prg_node.start("parse/analysis/codegen", null); |
| 206 | return error.ParseFailure; | 186 | module_node.activate(); |
| 207 | } | 187 | try module.update(); |
| 208 | analyze_node.end(); | 188 | module_node.end(); |
| 209 | 189 | ||
| 210 | var emit_node = prg_node.start("emit", null); | 190 | var emit_node = prg_node.start("emit", null); |
| 211 | emit_node.activate(); | 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 | defer new_zir_module.deinit(allocator); | 193 | defer new_zir_module.deinit(allocator); |
| 214 | emit_node.end(); | 194 | emit_node.end(); |
| 215 | 195 |