authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-16 22:51:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-16 22:51:01-07:00
log8c9ac4db978c80246b4872c899b1618b1b195ec2
treee6bddfb9df54fc6d60518978506e6869c1b2be80
parent8436134499c623485aeb20374a9928685db4211e

stage2: implement error notes and regress -femit-zir

* Implement error notes - note: other symbol exported here - note: previous else prong is here - note: previous '_' prong is here * Add Compilation.CObject.ErrorMsg. This object properly converts to AllErrors.Message when the time comes. * Add Compilation.CObject.failure_retryable. Properly handles out-of-memory and other transient failures. * Introduce Module.SrcLoc which has not only a byte offset but also references the file which the byte offset applies to. * Scope.Block now contains both a pointer to the "owner" Decl and the "source" Decl. As an example, during inline function call, the "owner" will be the Decl of the caller and the "source" will be the Decl of the callee. * Module.ErrorMsg now sports a `file_scope` field so that notes can refer to source locations in a file other than the parent error message. * Some instances where a `*Scope` was stored, now store a `*Scope.Container`. * Some methods in the `Scope` namespace were moved to the more specific type, since there was only an implementation for one particular tag. - `removeDecl` moved to `Scope.Container` - `destroy` moved to `Scope.File` * Two kinds of Scope deleted: - zir_module - decl * astgen: properly use DeclVal / DeclRef. DeclVal was incorrectly changed to be a reference; this commit fixes it. Fewer ZIR instructions processed as a result. - declval_in_module is renamed to declval - previous declval ZIR instruction is deleted; it was only for .zir files. * Test harness: friendlier diagnostics when an unexpected set of errors is encountered. * zir_sema: fix analyzeInstBlockFlat by properly calling resolvingInst on the last zir instruction in the block. Compile log implementation: * Write to a buffer rather than directly to stderr. * Only keep track of 1 callsite per Decl. * No longer mutate the ZIR Inst struct data. * "Compile log statement found" errors are only emitted when there are no other compile errors. -femit-zir and support for .zir source files is regressed. If we wanted to support this again, outputting .zir would need to be done as yet another backend rather than in the haphazard way it was previously implemented. For parsing .zir, it was implemented previously in a way that was not helpful for debugging. We need tighter integration with the test harness for it to be useful; so clearly a rewrite is needed. Given that a rewrite is needed, and it was getting in the way of progress and organization of the rest of stage2, I regressed the feature.

18 files changed, 904 insertions(+), 2618 deletions(-)

src/Compilation.zig+179-126
......@@ -51,7 +51,7 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),
5151
5252/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
5353/// This data is accessed by multiple threads and is protected by `mutex`.
54failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *ErrorMsg) = .{},
54failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},
5555
5656keep_source_files_loaded: bool,
5757use_clang: bool,
......@@ -215,13 +215,29 @@ pub const CObject = struct {
215215 },
216216 /// There will be a corresponding ErrorMsg in Compilation.failed_c_objects.
217217 failure,
218 /// A transient failure happened when trying to compile the C Object; it may
219 /// succeed if we try again. There may be a corresponding ErrorMsg in
220 /// Compilation.failed_c_objects. If there is not, the failure is out of memory.
221 failure_retryable,
218222 },
219223
224 pub const ErrorMsg = struct {
225 msg: []const u8,
226 line: u32,
227 column: u32,
228
229 pub fn destroy(em: *ErrorMsg, gpa: *Allocator) void {
230 gpa.free(em.msg);
231 gpa.destroy(em);
232 em.* = undefined;
233 }
234 };
235
220236 /// Returns if there was failure.
221237 pub fn clearStatus(self: *CObject, gpa: *Allocator) bool {
222238 switch (self.status) {
223239 .new => return false,
224 .failure => {
240 .failure, .failure_retryable => {
225241 self.status = .new;
226242 return true;
227243 },
......@@ -240,6 +256,11 @@ pub const CObject = struct {
240256 }
241257};
242258
259/// To support incremental compilation, errors are stored in various places
260/// so that they can be created and destroyed appropriately. This structure
261/// is used to collect all the errors from the various places into one
262/// convenient place for API users to consume. It is allocated into 1 heap
263/// and freed all at once.
243264pub const AllErrors = struct {
244265 arena: std.heap.ArenaAllocator.State,
245266 list: []const Message,
......@@ -251,23 +272,32 @@ pub const AllErrors = struct {
251272 column: usize,
252273 byte_offset: usize,
253274 msg: []const u8,
275 notes: []Message = &.{},
254276 },
255277 plain: struct {
256278 msg: []const u8,
257279 },
258280
259 pub fn renderToStdErr(self: Message) void {
260 switch (self) {
281 pub fn renderToStdErr(msg: Message) void {
282 return msg.renderToStdErrInner("error");
283 }
284
285 fn renderToStdErrInner(msg: Message, kind: []const u8) void {
286 switch (msg) {
261287 .src => |src| {
262 std.debug.print("{s}:{d}:{d}: error: {s}\n", .{
288 std.debug.print("{s}:{d}:{d}: {s}: {s}\n", .{
263289 src.src_path,
264290 src.line + 1,
265291 src.column + 1,
292 kind,
266293 src.msg,
267294 });
295 for (src.notes) |note| {
296 note.renderToStdErrInner("note");
297 }
268298 },
269299 .plain => |plain| {
270 std.debug.print("error: {s}\n", .{plain.msg});
300 std.debug.print("{s}: {s}\n", .{ kind, plain.msg });
271301 },
272302 }
273303 }
......@@ -278,20 +308,38 @@ pub const AllErrors = struct {
278308 }
279309
280310 fn add(
311 module: *Module,
281312 arena: *std.heap.ArenaAllocator,
282313 errors: *std.ArrayList(Message),
283 sub_file_path: []const u8,
284 source: []const u8,
285 simple_err_msg: ErrorMsg,
314 module_err_msg: Module.ErrorMsg,
286315 ) !void {
287 const loc = std.zig.findLineColumn(source, simple_err_msg.byte_offset);
316 const notes = try arena.allocator.alloc(Message, module_err_msg.notes.len);
317 for (notes) |*note, i| {
318 const module_note = module_err_msg.notes[i];
319 const source = try module_note.src_loc.file_scope.getSource(module);
320 const loc = std.zig.findLineColumn(source, module_note.src_loc.byte_offset);
321 const sub_file_path = module_note.src_loc.file_scope.sub_file_path;
322 note.* = .{
323 .src = .{
324 .src_path = try arena.allocator.dupe(u8, sub_file_path),
325 .msg = try arena.allocator.dupe(u8, module_note.msg),
326 .byte_offset = module_note.src_loc.byte_offset,
327 .line = loc.line,
328 .column = loc.column,
329 },
330 };
331 }
332 const source = try module_err_msg.src_loc.file_scope.getSource(module);
333 const loc = std.zig.findLineColumn(source, module_err_msg.src_loc.byte_offset);
334 const sub_file_path = module_err_msg.src_loc.file_scope.sub_file_path;
288335 try errors.append(.{
289336 .src = .{
290337 .src_path = try arena.allocator.dupe(u8, sub_file_path),
291 .msg = try arena.allocator.dupe(u8, simple_err_msg.msg),
292 .byte_offset = simple_err_msg.byte_offset,
338 .msg = try arena.allocator.dupe(u8, module_err_msg.msg),
339 .byte_offset = module_err_msg.src_loc.byte_offset,
293340 .line = loc.line,
294341 .column = loc.column,
342 .notes = notes,
295343 },
296344 });
297345 }
......@@ -849,17 +897,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
849897 .ty = struct_ty,
850898 },
851899 };
852 break :rs &root_scope.base;
900 break :rs root_scope;
853901 } else if (mem.endsWith(u8, root_pkg.root_src_path, ".zir")) {
854 const root_scope = try gpa.create(Module.Scope.ZIRModule);
855 root_scope.* = .{
856 .sub_file_path = root_pkg.root_src_path,
857 .source = .{ .unloaded = {} },
858 .contents = .{ .not_available = {} },
859 .status = .never_loaded,
860 .decls = .{},
861 };
862 break :rs &root_scope.base;
902 return error.ZirFilesUnsupported;
863903 } else {
864904 unreachable;
865905 }
......@@ -1258,32 +1298,23 @@ pub fn update(self: *Compilation) !void {
12581298 const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_llvm;
12591299 if (!use_stage1) {
12601300 if (self.bin_file.options.module) |module| {
1301 module.compile_log_text.shrinkAndFree(module.gpa, 0);
12611302 module.generation += 1;
12621303
12631304 // TODO Detect which source files changed.
12641305 // Until then we simulate a full cache miss. Source files could have been loaded for any reason;
12651306 // to force a refresh we unload now.
1266 if (module.root_scope.cast(Module.Scope.File)) |zig_file| {
1267 zig_file.unload(module.gpa);
1268 module.failed_root_src_file = null;
1269 module.analyzeContainer(&zig_file.root_container) catch |err| switch (err) {
1270 error.AnalysisFail => {
1271 assert(self.totalErrorCount() != 0);
1272 },
1273 error.OutOfMemory => return error.OutOfMemory,
1274 else => |e| {
1275 module.failed_root_src_file = e;
1276 },
1277 };
1278 } else if (module.root_scope.cast(Module.Scope.ZIRModule)) |zir_module| {
1279 zir_module.unload(module.gpa);
1280 module.analyzeRootZIRModule(zir_module) catch |err| switch (err) {
1281 error.AnalysisFail => {
1282 assert(self.totalErrorCount() != 0);
1283 },
1284 else => |e| return e,
1285 };
1286 }
1307 module.root_scope.unload(module.gpa);
1308 module.failed_root_src_file = null;
1309 module.analyzeContainer(&module.root_scope.root_container) catch |err| switch (err) {
1310 error.AnalysisFail => {
1311 assert(self.totalErrorCount() != 0);
1312 },
1313 error.OutOfMemory => return error.OutOfMemory,
1314 else => |e| {
1315 module.failed_root_src_file = e;
1316 },
1317 };
12871318
12881319 // TODO only analyze imports if they are still referenced
12891320 for (module.import_table.items()) |entry| {
......@@ -1359,14 +1390,18 @@ pub fn totalErrorCount(self: *Compilation) usize {
13591390 module.failed_exports.items().len +
13601391 module.failed_files.items().len +
13611392 @boolToInt(module.failed_root_src_file != null);
1362 for (module.compile_log_decls.items()) |entry| {
1363 total += entry.value.items.len;
1364 }
13651393 }
13661394
13671395 // The "no entry point found" error only counts if there are no other errors.
13681396 if (total == 0) {
1369 return @boolToInt(self.link_error_flags.no_entry_point_found);
1397 total += @boolToInt(self.link_error_flags.no_entry_point_found);
1398 }
1399
1400 // Compile log errors only count if there are no other errors.
1401 if (total == 0) {
1402 if (self.bin_file.options.module) |module| {
1403 total += @boolToInt(module.compile_log_decls.items().len != 0);
1404 }
13701405 }
13711406
13721407 return total;
......@@ -1382,32 +1417,32 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
13821417 for (self.failed_c_objects.items()) |entry| {
13831418 const c_object = entry.key;
13841419 const err_msg = entry.value;
1385 try AllErrors.add(&arena, &errors, c_object.src.src_path, "", err_msg.*);
1420 // TODO these fields will need to be adjusted when we have proper
1421 // C error reporting bubbling up.
1422 try errors.append(.{
1423 .src = .{
1424 .src_path = try arena.allocator.dupe(u8, c_object.src.src_path),
1425 .msg = try std.fmt.allocPrint(&arena.allocator, "unable to build C object: {s}", .{
1426 err_msg.msg,
1427 }),
1428 .byte_offset = 0,
1429 .line = err_msg.line,
1430 .column = err_msg.column,
1431 },
1432 });
13861433 }
13871434 if (self.bin_file.options.module) |module| {
13881435 for (module.failed_files.items()) |entry| {
1389 const scope = entry.key;
1390 const err_msg = entry.value;
1391 const source = try scope.getSource(module);
1392 try AllErrors.add(&arena, &errors, scope.subFilePath(), source, err_msg.*);
1436 try AllErrors.add(module, &arena, &errors, entry.value.*);
13931437 }
13941438 for (module.failed_decls.items()) |entry| {
1395 const decl = entry.key;
1396 const err_msg = entry.value;
1397 const source = try decl.scope.getSource(module);
1398 try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*);
1439 try AllErrors.add(module, &arena, &errors, entry.value.*);
13991440 }
14001441 for (module.emit_h_failed_decls.items()) |entry| {
1401 const decl = entry.key;
1402 const err_msg = entry.value;
1403 const source = try decl.scope.getSource(module);
1404 try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*);
1442 try AllErrors.add(module, &arena, &errors, entry.value.*);
14051443 }
14061444 for (module.failed_exports.items()) |entry| {
1407 const decl = entry.key.owner_decl;
1408 const err_msg = entry.value;
1409 const source = try decl.scope.getSource(module);
1410 try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*);
1445 try AllErrors.add(module, &arena, &errors, entry.value.*);
14111446 }
14121447 if (module.failed_root_src_file) |err| {
14131448 const file_path = try module.root_pkg.root_src_directory.join(&arena.allocator, &[_][]const u8{
......@@ -1418,15 +1453,6 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
14181453 });
14191454 try AllErrors.addPlain(&arena, &errors, msg);
14201455 }
1421 for (module.compile_log_decls.items()) |entry| {
1422 const decl = entry.key;
1423 const path = decl.scope.subFilePath();
1424 const source = try decl.scope.getSource(module);
1425 for (entry.value.items) |src_loc| {
1426 const err_msg = ErrorMsg{ .byte_offset = src_loc, .msg = "found compile log statement" };
1427 try AllErrors.add(&arena, &errors, path, source, err_msg);
1428 }
1429 }
14301456 }
14311457
14321458 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {
......@@ -1437,6 +1463,28 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
14371463 });
14381464 }
14391465
1466 if (self.bin_file.options.module) |module| {
1467 const compile_log_items = module.compile_log_decls.items();
1468 if (errors.items.len == 0 and compile_log_items.len != 0) {
1469 // First one will be the error; subsequent ones will be notes.
1470 const err_msg = Module.ErrorMsg{
1471 .src_loc = compile_log_items[0].value,
1472 .msg = "found compile log statement",
1473 .notes = try self.gpa.alloc(Module.ErrorMsg, compile_log_items.len - 1),
1474 };
1475 defer self.gpa.free(err_msg.notes);
1476
1477 for (compile_log_items[1..]) |entry, i| {
1478 err_msg.notes[i] = .{
1479 .src_loc = entry.value,
1480 .msg = "also here",
1481 };
1482 }
1483
1484 try AllErrors.add(module, &arena, &errors, err_msg);
1485 }
1486 }
1487
14401488 assert(errors.items.len == self.totalErrorCount());
14411489
14421490 return AllErrors{
......@@ -1445,6 +1493,11 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
14451493 };
14461494}
14471495
1496pub fn getCompileLogOutput(self: *Compilation) []const u8 {
1497 const module = self.bin_file.options.module orelse return &[0]u8{};
1498 return module.compile_log_text.items;
1499}
1500
14481501pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemory }!void {
14491502 var progress: std.Progress = .{};
14501503 var main_progress_node = try progress.start("", 0);
......@@ -1517,9 +1570,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
15171570 },
15181571 else => {
15191572 try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1);
1520 module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
1573 module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
15211574 module.gpa,
1522 decl.src(),
1575 decl.srcLoc(),
15231576 "unable to codegen: {s}",
15241577 .{@errorName(err)},
15251578 ));
......@@ -1586,9 +1639,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
15861639 const module = self.bin_file.options.module.?;
15871640 self.bin_file.updateDeclLineNumber(module, decl) catch |err| {
15881641 try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1);
1589 module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
1642 module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
15901643 module.gpa,
1591 decl.src(),
1644 decl.srcLoc(),
15921645 "unable to update line number: {s}",
15931646 .{@errorName(err)},
15941647 ));
......@@ -1858,26 +1911,38 @@ fn workerUpdateCObject(
18581911 comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
18591912 error.AnalysisFail => return,
18601913 else => {
1861 {
1862 const lock = comp.mutex.acquire();
1863 defer lock.release();
1864 comp.failed_c_objects.ensureCapacity(comp.gpa, comp.failed_c_objects.items().len + 1) catch {
1865 fatal("TODO handle this by setting c_object.status = oom failure", .{});
1866 };
1867 comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, ErrorMsg.create(
1868 comp.gpa,
1869 0,
1870 "unable to build C object: {s}",
1871 .{@errorName(err)},
1872 ) catch {
1873 fatal("TODO handle this by setting c_object.status = oom failure", .{});
1874 });
1875 }
1876 c_object.status = .{ .failure = {} };
1914 comp.reportRetryableCObjectError(c_object, err) catch |oom| switch (oom) {
1915 // Swallowing this error is OK because it's implied to be OOM when
1916 // there is a missing failed_c_objects error message.
1917 error.OutOfMemory => {},
1918 };
18771919 },
18781920 };
18791921}
18801922
1923fn reportRetryableCObjectError(
1924 comp: *Compilation,
1925 c_object: *CObject,
1926 err: anyerror,
1927) error{OutOfMemory}!void {
1928 c_object.status = .failure_retryable;
1929
1930 const c_obj_err_msg = try comp.gpa.create(CObject.ErrorMsg);
1931 errdefer comp.gpa.destroy(c_obj_err_msg);
1932 const msg = try std.fmt.allocPrint(comp.gpa, "unable to build C object: {s}", .{@errorName(err)});
1933 errdefer comp.gpa.free(msg);
1934 c_obj_err_msg.* = .{
1935 .msg = msg,
1936 .line = 0,
1937 .column = 0,
1938 };
1939 {
1940 const lock = comp.mutex.acquire();
1941 defer lock.release();
1942 try comp.failed_c_objects.putNoClobber(comp.gpa, c_object, c_obj_err_msg);
1943 }
1944}
1945
18811946fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *std.Progress.Node) !void {
18821947 if (!build_options.have_llvm) {
18831948 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
......@@ -1892,7 +1957,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
18921957 // There was previous failure.
18931958 const lock = comp.mutex.acquire();
18941959 defer lock.release();
1895 comp.failed_c_objects.removeAssertDiscard(c_object);
1960 // If the failure was OOM, there will not be an entry here, so we do
1961 // not assert discard.
1962 _ = comp.failed_c_objects.swapRemove(c_object);
18961963 }
18971964
18981965 var man = comp.obtainCObjectCacheManifest();
......@@ -2343,11 +2410,27 @@ pub fn addCCArgs(
23432410
23442411fn failCObj(comp: *Compilation, c_object: *CObject, comptime format: []const u8, args: anytype) InnerError {
23452412 @setCold(true);
2346 const err_msg = try ErrorMsg.create(comp.gpa, 0, "unable to build C object: " ++ format, args);
2413 const err_msg = blk: {
2414 const msg = try std.fmt.allocPrint(comp.gpa, format, args);
2415 errdefer comp.gpa.free(msg);
2416 const err_msg = try comp.gpa.create(CObject.ErrorMsg);
2417 errdefer comp.gpa.destroy(err_msg);
2418 err_msg.* = .{
2419 .msg = msg,
2420 .line = 0,
2421 .column = 0,
2422 };
2423 break :blk err_msg;
2424 };
23472425 return comp.failCObjWithOwnedErrorMsg(c_object, err_msg);
23482426}
23492427
2350fn failCObjWithOwnedErrorMsg(comp: *Compilation, c_object: *CObject, err_msg: *ErrorMsg) InnerError {
2428fn failCObjWithOwnedErrorMsg(
2429 comp: *Compilation,
2430 c_object: *CObject,
2431 err_msg: *CObject.ErrorMsg,
2432) InnerError {
2433 @setCold(true);
23512434 {
23522435 const lock = comp.mutex.acquire();
23532436 defer lock.release();
......@@ -2361,36 +2444,6 @@ fn failCObjWithOwnedErrorMsg(comp: *Compilation, c_object: *CObject, err_msg: *E
23612444 return error.AnalysisFail;
23622445}
23632446
2364pub const ErrorMsg = struct {
2365 byte_offset: usize,
2366 msg: []const u8,
2367
2368 pub fn create(gpa: *Allocator, byte_offset: usize, comptime format: []const u8, args: anytype) !*ErrorMsg {
2369 const self = try gpa.create(ErrorMsg);
2370 errdefer gpa.destroy(self);
2371 self.* = try init(gpa, byte_offset, format, args);
2372 return self;
2373 }
2374
2375 /// Assumes the ErrorMsg struct and msg were both allocated with allocator.
2376 pub fn destroy(self: *ErrorMsg, gpa: *Allocator) void {
2377 self.deinit(gpa);
2378 gpa.destroy(self);
2379 }
2380
2381 pub fn init(gpa: *Allocator, byte_offset: usize, comptime format: []const u8, args: anytype) !ErrorMsg {
2382 return ErrorMsg{
2383 .byte_offset = byte_offset,
2384 .msg = try std.fmt.allocPrint(gpa, format, args),
2385 };
2386 }
2387
2388 pub fn deinit(self: *ErrorMsg, gpa: *Allocator) void {
2389 gpa.free(self.msg);
2390 self.* = undefined;
2391 }
2392};
2393
23942447pub const FileExt = enum {
23952448 c,
23962449 cpp,
src/Module.zig+281-483
......@@ -35,8 +35,7 @@ zig_cache_artifact_directory: Compilation.Directory,
3535/// Pointer to externally managed resource. `null` if there is no zig file being compiled.
3636root_pkg: *Package,
3737/// Module owns this resource.
38/// The `Scope` is either a `Scope.ZIRModule` or `Scope.File`.
39root_scope: *Scope,
38root_scope: *Scope.File,
4039/// It's rare for a decl to be exported, so we save memory by having a sparse map of
4140/// Decl pointers to details about them being exported.
4241/// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table.
......@@ -57,19 +56,19 @@ decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_has
5756/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
5857/// Note that a Decl can succeed but the Fn it represents can fail. In this case,
5958/// a Decl can have a failed_decls entry but have analysis status of success.
60failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
59failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},
6160/// When emit_h is non-null, each Decl gets one more compile error slot for
6261/// emit-h failing for that Decl. This table is also how we tell if a Decl has
6362/// failed emit-h or succeeded.
64emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
65/// A Decl can have multiple compileLogs, but only one error, so we map a Decl to a the src locs of all the compileLogs
66compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, ArrayListUnmanaged(usize)) = .{},
63emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},
64/// Keep track of one `@compileLog` callsite per owner Decl.
65compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, SrcLoc) = .{},
6766/// Using a map here for consistency with the other fields here.
6867/// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator.
69failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{},
68failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *ErrorMsg) = .{},
7069/// Using a map here for consistency with the other fields here.
7170/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
72failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *Compilation.ErrorMsg) = .{},
71failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
7372
7473next_anon_name_index: usize = 0,
7574
......@@ -103,6 +102,8 @@ stage1_flags: packed struct {
103102
104103emit_h: ?Compilation.EmitLoc,
105104
105compile_log_text: std.ArrayListUnmanaged(u8) = .{},
106
106107pub const Export = struct {
107108 options: std.builtin.ExportOptions,
108109 /// Byte offset into the file that contains the export directive.
......@@ -138,9 +139,9 @@ pub const Decl = struct {
138139 /// mapping them to an address in the output file.
139140 /// Memory owned by this decl, using Module's allocator.
140141 name: [*:0]const u8,
141 /// The direct parent container of the Decl. This is either a `Scope.Container` or `Scope.ZIRModule`.
142 /// The direct parent container of the Decl.
142143 /// Reference to externally owned memory.
143 scope: *Scope,
144 container: *Scope.Container,
144145 /// The AST Node decl index or ZIR Inst index that contains this declaration.
145146 /// Must be recomputed when the corresponding source file is modified.
146147 src_index: usize,
......@@ -235,31 +236,21 @@ pub const Decl = struct {
235236 }
236237 }
237238
239 pub fn srcLoc(self: Decl) SrcLoc {
240 return .{
241 .byte_offset = self.src(),
242 .file_scope = self.getFileScope(),
243 };
244 }
245
238246 pub fn src(self: Decl) usize {
239 switch (self.scope.tag) {
240 .container => {
241 const container = @fieldParentPtr(Scope.Container, "base", self.scope);
242 const tree = container.file_scope.contents.tree;
243 // TODO Container should have its own decls()
244 const decl_node = tree.root_node.decls()[self.src_index];
245 return tree.token_locs[decl_node.firstToken()].start;
246 },
247 .zir_module => {
248 const zir_module = @fieldParentPtr(Scope.ZIRModule, "base", self.scope);
249 const module = zir_module.contents.module;
250 const src_decl = module.decls[self.src_index];
251 return src_decl.inst.src;
252 },
253 .file, .block => unreachable,
254 .gen_zir => unreachable,
255 .local_val => unreachable,
256 .local_ptr => unreachable,
257 .decl => unreachable,
258 }
247 const tree = self.container.file_scope.contents.tree;
248 const decl_node = tree.root_node.decls()[self.src_index];
249 return tree.token_locs[decl_node.firstToken()].start;
259250 }
260251
261252 pub fn fullyQualifiedNameHash(self: Decl) Scope.NameHash {
262 return self.scope.fullyQualifiedNameHash(mem.spanZ(self.name));
253 return self.container.fullyQualifiedNameHash(mem.spanZ(self.name));
263254 }
264255
265256 pub fn typedValue(self: *Decl) error{AnalysisFail}!TypedValue {
......@@ -293,9 +284,8 @@ pub const Decl = struct {
293284 }
294285 }
295286
296 /// Asserts that the `Decl` is part of AST and not ZIRModule.
297 pub fn getFileScope(self: *Decl) *Scope.File {
298 return self.scope.cast(Scope.Container).?.file_scope;
287 pub fn getFileScope(self: Decl) *Scope.File {
288 return self.container.file_scope;
299289 }
300290
301291 pub fn getEmitH(decl: *Decl, module: *Module) *EmitH {
......@@ -326,7 +316,7 @@ pub const Fn = struct {
326316 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
327317 /// Even after we finish analysis, the ZIR is kept in memory, so that
328318 /// comptime and inline function calls can happen.
329 zir: zir.Module.Body,
319 zir: zir.Body,
330320 /// undefined unless analysis state is `success`.
331321 body: Body,
332322 state: Analysis,
......@@ -373,47 +363,49 @@ pub const Scope = struct {
373363 return @fieldParentPtr(T, "base", base);
374364 }
375365
376 /// Asserts the scope has a parent which is a DeclAnalysis and
377 /// returns the arena Allocator.
366 /// Returns the arena Allocator associated with the Decl of the Scope.
378367 pub fn arena(self: *Scope) *Allocator {
379368 switch (self.tag) {
380369 .block => return self.cast(Block).?.arena,
381 .decl => return &self.cast(DeclAnalysis).?.arena.allocator,
382370 .gen_zir => return self.cast(GenZIR).?.arena,
383371 .local_val => return self.cast(LocalVal).?.gen_zir.arena,
384372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,
385 .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator,
386373 .file => unreachable,
387374 .container => unreachable,
388375 }
389376 }
390377
391 /// If the scope has a parent which is a `DeclAnalysis`,
392 /// returns the `Decl`, otherwise returns `null`.
393 pub fn decl(self: *Scope) ?*Decl {
378 pub fn ownerDecl(self: *Scope) ?*Decl {
379 return switch (self.tag) {
380 .block => self.cast(Block).?.owner_decl,
381 .gen_zir => self.cast(GenZIR).?.decl,
382 .local_val => self.cast(LocalVal).?.gen_zir.decl,
383 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
384 .file => null,
385 .container => null,
386 };
387 }
388
389 pub fn srcDecl(self: *Scope) ?*Decl {
394390 return switch (self.tag) {
395 .block => self.cast(Block).?.decl,
391 .block => self.cast(Block).?.src_decl,
396392 .gen_zir => self.cast(GenZIR).?.decl,
397393 .local_val => self.cast(LocalVal).?.gen_zir.decl,
398394 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
399 .decl => self.cast(DeclAnalysis).?.decl,
400 .zir_module => null,
401395 .file => null,
402396 .container => null,
403397 };
404398 }
405399
406 /// Asserts the scope has a parent which is a ZIRModule or Container and
407 /// returns it.
408 pub fn namespace(self: *Scope) *Scope {
400 /// Asserts the scope has a parent which is a Container and returns it.
401 pub fn namespace(self: *Scope) *Container {
409402 switch (self.tag) {
410 .block => return self.cast(Block).?.decl.scope,
411 .gen_zir => return self.cast(GenZIR).?.decl.scope,
412 .local_val => return self.cast(LocalVal).?.gen_zir.decl.scope,
413 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.scope,
414 .decl => return self.cast(DeclAnalysis).?.decl.scope,
415 .file => return &self.cast(File).?.root_container.base,
416 .zir_module, .container => return self,
403 .block => return self.cast(Block).?.owner_decl.container,
404 .gen_zir => return self.cast(GenZIR).?.decl.container,
405 .local_val => return self.cast(LocalVal).?.gen_zir.decl.container,
406 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container,
407 .file => return &self.cast(File).?.root_container,
408 .container => return self.cast(Container).?,
417409 }
418410 }
419411
......@@ -426,9 +418,7 @@ pub const Scope = struct {
426418 .gen_zir => unreachable,
427419 .local_val => unreachable,
428420 .local_ptr => unreachable,
429 .decl => unreachable,
430421 .file => unreachable,
431 .zir_module => return self.cast(ZIRModule).?.fullyQualifiedNameHash(name),
432422 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),
433423 }
434424 }
......@@ -437,12 +427,10 @@ pub const Scope = struct {
437427 pub fn tree(self: *Scope) *ast.Tree {
438428 switch (self.tag) {
439429 .file => return self.cast(File).?.contents.tree,
440 .zir_module => unreachable,
441 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(Container).?.file_scope.contents.tree,
442 .block => return self.cast(Block).?.decl.scope.cast(Container).?.file_scope.contents.tree,
443 .gen_zir => return self.cast(GenZIR).?.decl.scope.cast(Container).?.file_scope.contents.tree,
444 .local_val => return self.cast(LocalVal).?.gen_zir.decl.scope.cast(Container).?.file_scope.contents.tree,
445 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.scope.cast(Container).?.file_scope.contents.tree,
430 .block => return self.cast(Block).?.src_decl.container.file_scope.contents.tree,
431 .gen_zir => return self.cast(GenZIR).?.decl.container.file_scope.contents.tree,
432 .local_val => return self.cast(LocalVal).?.gen_zir.decl.container.file_scope.contents.tree,
433 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.contents.tree,
446434 .container => return self.cast(Container).?.file_scope.contents.tree,
447435 }
448436 }
......@@ -454,38 +442,21 @@ pub const Scope = struct {
454442 .gen_zir => self.cast(GenZIR).?,
455443 .local_val => return self.cast(LocalVal).?.gen_zir,
456444 .local_ptr => return self.cast(LocalPtr).?.gen_zir,
457 .decl => unreachable,
458 .zir_module => unreachable,
459445 .file => unreachable,
460446 .container => unreachable,
461447 };
462448 }
463449
464 /// Asserts the scope has a parent which is a ZIRModule, Container or File and
450 /// Asserts the scope has a parent which is a Container or File and
465451 /// returns the sub_file_path field.
466452 pub fn subFilePath(base: *Scope) []const u8 {
467453 switch (base.tag) {
468454 .container => return @fieldParentPtr(Container, "base", base).file_scope.sub_file_path,
469455 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
470 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path,
471456 .block => unreachable,
472457 .gen_zir => unreachable,
473458 .local_val => unreachable,
474459 .local_ptr => unreachable,
475 .decl => unreachable,
476 }
477 }
478
479 pub fn unload(base: *Scope, gpa: *Allocator) void {
480 switch (base.tag) {
481 .file => return @fieldParentPtr(File, "base", base).unload(gpa),
482 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).unload(gpa),
483 .block => unreachable,
484 .gen_zir => unreachable,
485 .local_val => unreachable,
486 .local_ptr => unreachable,
487 .decl => unreachable,
488 .container => unreachable,
489460 }
490461 }
491462
......@@ -493,67 +464,28 @@ pub const Scope = struct {
493464 switch (base.tag) {
494465 .container => return @fieldParentPtr(Container, "base", base).file_scope.getSource(module),
495466 .file => return @fieldParentPtr(File, "base", base).getSource(module),
496 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module),
497467 .gen_zir => unreachable,
498468 .local_val => unreachable,
499469 .local_ptr => unreachable,
500470 .block => unreachable,
501 .decl => unreachable,
502471 }
503472 }
504473
474 /// When called from inside a Block Scope, chases the src_decl, not the owner_decl.
505475 pub fn getFileScope(base: *Scope) *Scope.File {
506476 var cur = base;
507477 while (true) {
508478 cur = switch (cur.tag) {
509479 .container => return @fieldParentPtr(Container, "base", cur).file_scope,
510480 .file => return @fieldParentPtr(File, "base", cur),
511 .zir_module => unreachable, // TODO are zir modules allowed to import packages?
512481 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
513482 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
514483 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
515 .block => @fieldParentPtr(Block, "base", cur).decl.scope,
516 .decl => @fieldParentPtr(DeclAnalysis, "base", cur).decl.scope,
484 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,
517485 };
518486 }
519487 }
520488
521 /// Asserts the scope is a namespace Scope and removes the Decl from the namespace.
522 pub fn removeDecl(base: *Scope, child: *Decl) void {
523 switch (base.tag) {
524 .container => return @fieldParentPtr(Container, "base", base).removeDecl(child),
525 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).removeDecl(child),
526 .file => unreachable,
527 .block => unreachable,
528 .gen_zir => unreachable,
529 .local_val => unreachable,
530 .local_ptr => unreachable,
531 .decl => unreachable,
532 }
533 }
534
535 /// Asserts the scope is a File or ZIRModule and deinitializes it, then deallocates it.
536 pub fn destroy(base: *Scope, gpa: *Allocator) void {
537 switch (base.tag) {
538 .file => {
539 const scope_file = @fieldParentPtr(File, "base", base);
540 scope_file.deinit(gpa);
541 gpa.destroy(scope_file);
542 },
543 .zir_module => {
544 const scope_zir_module = @fieldParentPtr(ZIRModule, "base", base);
545 scope_zir_module.deinit(gpa);
546 gpa.destroy(scope_zir_module);
547 },
548 .block => unreachable,
549 .gen_zir => unreachable,
550 .local_val => unreachable,
551 .local_ptr => unreachable,
552 .decl => unreachable,
553 .container => unreachable,
554 }
555 }
556
557489 fn name_hash_hash(x: NameHash) u32 {
558490 return @truncate(u32, @bitCast(u128, x));
559491 }
......@@ -563,14 +495,11 @@ pub const Scope = struct {
563495 }
564496
565497 pub const Tag = enum {
566 /// .zir source code.
567 zir_module,
568498 /// .zig source code.
569499 file,
570500 /// struct, enum or union, every .file contains one of these.
571501 container,
572502 block,
573 decl,
574503 gen_zir,
575504 local_val,
576505 local_ptr,
......@@ -657,6 +586,11 @@ pub const Scope = struct {
657586 self.* = undefined;
658587 }
659588
589 pub fn destroy(self: *File, gpa: *Allocator) void {
590 self.deinit(gpa);
591 gpa.destroy(self);
592 }
593
660594 pub fn dumpSrc(self: *File, src: usize) void {
661595 const loc = std.zig.findLineColumn(self.source.bytes, src);
662596 std.debug.print("{s}:{d}:{d}\n", .{ self.sub_file_path, loc.line + 1, loc.column + 1 });
......@@ -681,109 +615,6 @@ pub const Scope = struct {
681615 }
682616 };
683617
684 pub const ZIRModule = struct {
685 pub const base_tag: Tag = .zir_module;
686 base: Scope = Scope{ .tag = base_tag },
687 /// Relative to the owning package's root_src_dir.
688 /// Reference to external memory, not owned by ZIRModule.
689 sub_file_path: []const u8,
690 source: union(enum) {
691 unloaded: void,
692 bytes: [:0]const u8,
693 },
694 contents: union {
695 not_available: void,
696 module: *zir.Module,
697 },
698 status: enum {
699 never_loaded,
700 unloaded_success,
701 unloaded_parse_failure,
702 unloaded_sema_failure,
703
704 loaded_sema_failure,
705 loaded_success,
706 },
707
708 /// Even though .zir files only have 1 module, this set is still needed
709 /// because of anonymous Decls, which can exist in the global set, but
710 /// not this one.
711 decls: ArrayListUnmanaged(*Decl),
712
713 pub fn unload(self: *ZIRModule, gpa: *Allocator) void {
714 switch (self.status) {
715 .never_loaded,
716 .unloaded_parse_failure,
717 .unloaded_sema_failure,
718 .unloaded_success,
719 => {},
720
721 .loaded_success => {
722 self.contents.module.deinit(gpa);
723 gpa.destroy(self.contents.module);
724 self.contents = .{ .not_available = {} };
725 self.status = .unloaded_success;
726 },
727 .loaded_sema_failure => {
728 self.contents.module.deinit(gpa);
729 gpa.destroy(self.contents.module);
730 self.contents = .{ .not_available = {} };
731 self.status = .unloaded_sema_failure;
732 },
733 }
734 switch (self.source) {
735 .bytes => |bytes| {
736 gpa.free(bytes);
737 self.source = .{ .unloaded = {} };
738 },
739 .unloaded => {},
740 }
741 }
742
743 pub fn deinit(self: *ZIRModule, gpa: *Allocator) void {
744 self.decls.deinit(gpa);
745 self.unload(gpa);
746 self.* = undefined;
747 }
748
749 pub fn removeDecl(self: *ZIRModule, child: *Decl) void {
750 for (self.decls.items) |item, i| {
751 if (item == child) {
752 _ = self.decls.swapRemove(i);
753 return;
754 }
755 }
756 }
757
758 pub fn dumpSrc(self: *ZIRModule, src: usize) void {
759 const loc = std.zig.findLineColumn(self.source.bytes, src);
760 std.debug.print("{s}:{d}:{d}\n", .{ self.sub_file_path, loc.line + 1, loc.column + 1 });
761 }
762
763 pub fn getSource(self: *ZIRModule, module: *Module) ![:0]const u8 {
764 switch (self.source) {
765 .unloaded => {
766 const source = try module.root_pkg.root_src_directory.handle.readFileAllocOptions(
767 module.gpa,
768 self.sub_file_path,
769 std.math.maxInt(u32),
770 null,
771 1,
772 0,
773 );
774 self.source = .{ .bytes = source };
775 return source;
776 },
777 .bytes => |bytes| return bytes,
778 }
779 }
780
781 pub fn fullyQualifiedNameHash(self: *ZIRModule, name: []const u8) NameHash {
782 // ZIR modules only have 1 file with all decls global in the same namespace.
783 return std.zig.hashSrc(name);
784 }
785 };
786
787618 /// This is a temporary structure, references to it are valid only
788619 /// during semantic analysis of the block.
789620 pub const Block = struct {
......@@ -794,9 +625,14 @@ pub const Scope = struct {
794625 /// Maps ZIR to TZIR. Shared to sub-blocks.
795626 inst_table: *InstTable,
796627 func: ?*Fn,
797 decl: *Decl,
628 /// When analyzing an inline function call, owner_decl is the Decl of the caller
629 /// and src_decl is the Decl of the callee.
630 /// This Decl owns the arena memory of this Block.
631 owner_decl: *Decl,
632 /// This Decl is the Decl according to the Zig source code corresponding to this Block.
633 src_decl: *Decl,
798634 instructions: ArrayListUnmanaged(*Inst),
799 /// Points to the arena allocator of DeclAnalysis
635 /// Points to the arena allocator of the Decl.
800636 arena: *Allocator,
801637 label: ?Label = null,
802638 inlining: ?*Inlining,
......@@ -845,21 +681,12 @@ pub const Scope = struct {
845681 }
846682 };
847683
848 /// This is a temporary structure, references to it are valid only
849 /// during semantic analysis of the decl.
850 pub const DeclAnalysis = struct {
851 pub const base_tag: Tag = .decl;
852 base: Scope = Scope{ .tag = base_tag },
853 decl: *Decl,
854 arena: std.heap.ArenaAllocator,
855 };
856
857684 /// This is a temporary structure, references to it are valid only
858685 /// during semantic analysis of the decl.
859686 pub const GenZIR = struct {
860687 pub const base_tag: Tag = .gen_zir;
861688 base: Scope = Scope{ .tag = base_tag },
862 /// Parents can be: `GenZIR`, `ZIRModule`, `File`
689 /// Parents can be: `GenZIR`, `File`
863690 parent: *Scope,
864691 decl: *Decl,
865692 arena: *Allocator,
......@@ -905,11 +732,73 @@ pub const Scope = struct {
905732 };
906733};
907734
735/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
736/// Its memory is managed with the general purpose allocator so that they
737/// can be created and destroyed in response to incremental updates.
738/// In some cases, the Scope.File could have been inferred from where the ErrorMsg
739/// is stored. For example, if it is stored in Module.failed_decls, then the Scope.File
740/// would be determined by the Decl Scope. However, the data structure contains the field
741/// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different
742/// file than the parent error message. It also simplifies processing of error messages.
743pub const ErrorMsg = struct {
744 src_loc: SrcLoc,
745 msg: []const u8,
746 notes: []ErrorMsg = &.{},
747
748 pub fn create(
749 gpa: *Allocator,
750 src_loc: SrcLoc,
751 comptime format: []const u8,
752 args: anytype,
753 ) !*ErrorMsg {
754 const self = try gpa.create(ErrorMsg);
755 errdefer gpa.destroy(self);
756 self.* = try init(gpa, src_loc, format, args);
757 return self;
758 }
759
760 /// Assumes the ErrorMsg struct and msg were both allocated with `gpa`,
761 /// as well as all notes.
762 pub fn destroy(self: *ErrorMsg, gpa: *Allocator) void {
763 self.deinit(gpa);
764 gpa.destroy(self);
765 }
766
767 pub fn init(
768 gpa: *Allocator,
769 src_loc: SrcLoc,
770 comptime format: []const u8,
771 args: anytype,
772 ) !ErrorMsg {
773 return ErrorMsg{
774 .src_loc = src_loc,
775 .msg = try std.fmt.allocPrint(gpa, format, args),
776 };
777 }
778
779 pub fn deinit(self: *ErrorMsg, gpa: *Allocator) void {
780 for (self.notes) |*note| {
781 note.deinit(gpa);
782 }
783 gpa.free(self.notes);
784 gpa.free(self.msg);
785 self.* = undefined;
786 }
787};
788
789/// Canonical reference to a position within a source file.
790pub const SrcLoc = struct {
791 file_scope: *Scope.File,
792 byte_offset: usize,
793};
794
908795pub const InnerError = error{ OutOfMemory, AnalysisFail };
909796
910797pub fn deinit(self: *Module) void {
911798 const gpa = self.gpa;
912799
800 self.compile_log_text.deinit(gpa);
801
913802 self.zig_cache_artifact_directory.handle.close();
914803
915804 self.deletion_set.deinit(gpa);
......@@ -939,9 +828,6 @@ pub fn deinit(self: *Module) void {
939828 }
940829 self.failed_exports.deinit(gpa);
941830
942 for (self.compile_log_decls.items()) |*entry| {
943 entry.value.deinit(gpa);
944 }
945831 self.compile_log_decls.deinit(gpa);
946832
947833 for (self.decl_exports.items()) |entry| {
......@@ -965,7 +851,7 @@ pub fn deinit(self: *Module) void {
965851 self.global_error_set.deinit(gpa);
966852
967853 for (self.import_table.items()) |entry| {
968 entry.value.base.destroy(gpa);
854 entry.value.destroy(gpa);
969855 }
970856 self.import_table.deinit(gpa);
971857}
......@@ -978,7 +864,7 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
978864 gpa.free(export_list);
979865}
980866
981pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
867pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {
982868 const tracy = trace(@src());
983869 defer tracy.end();
984870
......@@ -999,7 +885,7 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
999885
1000886 // The exports this Decl performs will be re-discovered, so we remove them here
1001887 // prior to re-analysis.
1002 self.deleteDeclExports(decl);
888 mod.deleteDeclExports(decl);
1003889 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
1004890 for (decl.dependencies.items()) |entry| {
1005891 const dep = entry.key;
......@@ -1008,7 +894,7 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1008894 // We don't perform a deletion here, because this Decl or another one
1009895 // may end up referencing it before the update is complete.
1010896 dep.deletion_flag = true;
1011 try self.deletion_set.append(self.gpa, dep);
897 try mod.deletion_set.append(mod.gpa, dep);
1012898 }
1013899 }
1014900 decl.dependencies.clearRetainingCapacity();
......@@ -1019,24 +905,21 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1019905 .unreferenced => false,
1020906 };
1021907
1022 const type_changed = if (self.root_scope.cast(Scope.ZIRModule)) |zir_module|
1023 try zir_sema.analyzeZirDecl(self, decl, zir_module.contents.module.decls[decl.src_index])
1024 else
1025 self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
1026 error.OutOfMemory => return error.OutOfMemory,
1027 error.AnalysisFail => return error.AnalysisFail,
1028 else => {
1029 try self.failed_decls.ensureCapacity(self.gpa, self.failed_decls.items().len + 1);
1030 self.failed_decls.putAssumeCapacityNoClobber(decl, try Compilation.ErrorMsg.create(
1031 self.gpa,
1032 decl.src(),
1033 "unable to analyze: {s}",
1034 .{@errorName(err)},
1035 ));
1036 decl.analysis = .sema_failure_retryable;
1037 return error.AnalysisFail;
1038 },
1039 };
908 const type_changed = mod.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
909 error.OutOfMemory => return error.OutOfMemory,
910 error.AnalysisFail => return error.AnalysisFail,
911 else => {
912 decl.analysis = .sema_failure_retryable;
913 try mod.failed_decls.ensureCapacity(mod.gpa, mod.failed_decls.items().len + 1);
914 mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
915 mod.gpa,
916 decl.srcLoc(),
917 "unable to analyze: {s}",
918 .{@errorName(err)},
919 ));
920 return error.AnalysisFail;
921 },
922 };
1040923
1041924 if (subsequent_analysis) {
1042925 // We may need to chase the dependants and re-analyze them.
......@@ -1055,8 +938,8 @@ pub fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1055938 .codegen_failure,
1056939 .codegen_failure_retryable,
1057940 .complete,
1058 => if (dep.generation != self.generation) {
1059 try self.markOutdatedDecl(dep);
941 => if (dep.generation != mod.generation) {
942 try mod.markOutdatedDecl(dep);
1060943 },
1061944 }
1062945 }
......@@ -1068,8 +951,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1068951 const tracy = trace(@src());
1069952 defer tracy.end();
1070953
1071 const container_scope = decl.scope.cast(Scope.Container).?;
1072 const tree = try self.getAstTree(container_scope.file_scope);
954 const tree = try self.getAstTree(decl.container.file_scope);
1073955 const ast_node = tree.root_node.decls()[decl.src_index];
1074956 switch (ast_node.tag) {
1075957 .FnProto => {
......@@ -1085,7 +967,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1085967 var fn_type_scope: Scope.GenZIR = .{
1086968 .decl = decl,
1087969 .arena = &fn_type_scope_arena.allocator,
1088 .parent = decl.scope,
970 .parent = &decl.container.base,
1089971 };
1090972 defer fn_type_scope.instructions.deinit(self.gpa);
1091973
......@@ -1197,7 +1079,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
11971079 .parent = null,
11981080 .inst_table = &inst_table,
11991081 .func = null,
1200 .decl = decl,
1082 .owner_decl = decl,
1083 .src_decl = decl,
12011084 .instructions = .{},
12021085 .arena = &decl_arena.allocator,
12031086 .inlining = null,
......@@ -1242,12 +1125,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
12421125 const new_func = try decl_arena.allocator.create(Fn);
12431126 const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);
12441127
1245 const fn_zir: zir.Module.Body = blk: {
1128 const fn_zir: zir.Body = blk: {
12461129 // We put the ZIR inside the Decl arena.
12471130 var gen_scope: Scope.GenZIR = .{
12481131 .decl = decl,
12491132 .arena = &decl_arena.allocator,
1250 .parent = decl.scope,
1133 .parent = &decl.container.base,
12511134 };
12521135 defer gen_scope.instructions.deinit(self.gpa);
12531136
......@@ -1400,7 +1283,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
14001283 .parent = null,
14011284 .inst_table = &decl_inst_table,
14021285 .func = null,
1403 .decl = decl,
1286 .owner_decl = decl,
1287 .src_decl = decl,
14041288 .instructions = .{},
14051289 .arena = &decl_arena.allocator,
14061290 .inlining = null,
......@@ -1444,7 +1328,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
14441328 var gen_scope: Scope.GenZIR = .{
14451329 .decl = decl,
14461330 .arena = &gen_scope_arena.allocator,
1447 .parent = decl.scope,
1331 .parent = &decl.container.base,
14481332 };
14491333 defer gen_scope.instructions.deinit(self.gpa);
14501334
......@@ -1472,7 +1356,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
14721356 .parent = null,
14731357 .inst_table = &var_inst_table,
14741358 .func = null,
1475 .decl = decl,
1359 .owner_decl = decl,
1360 .src_decl = decl,
14761361 .instructions = .{},
14771362 .arena = &gen_scope_arena.allocator,
14781363 .inlining = null,
......@@ -1503,7 +1388,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
15031388 var type_scope: Scope.GenZIR = .{
15041389 .decl = decl,
15051390 .arena = &type_scope_arena.allocator,
1506 .parent = decl.scope,
1391 .parent = &decl.container.base,
15071392 };
15081393 defer type_scope.instructions.deinit(self.gpa);
15091394
......@@ -1584,7 +1469,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
15841469 var gen_scope: Scope.GenZIR = .{
15851470 .decl = decl,
15861471 .arena = &analysis_arena.allocator,
1587 .parent = decl.scope,
1472 .parent = &decl.container.base,
15881473 };
15891474 defer gen_scope.instructions.deinit(self.gpa);
15901475
......@@ -1602,7 +1487,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
16021487 .parent = null,
16031488 .inst_table = &inst_table,
16041489 .func = null,
1605 .decl = decl,
1490 .owner_decl = decl,
1491 .src_decl = decl,
16061492 .instructions = .{},
16071493 .arena = &analysis_arena.allocator,
16081494 .inlining = null,
......@@ -1632,44 +1518,6 @@ fn declareDeclDependency(self: *Module, depender: *Decl, dependee: *Decl) !void
16321518 dependee.dependants.putAssumeCapacity(depender, {});
16331519}
16341520
1635fn getSrcModule(self: *Module, root_scope: *Scope.ZIRModule) !*zir.Module {
1636 switch (root_scope.status) {
1637 .never_loaded, .unloaded_success => {
1638 try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1);
1639
1640 const source = try root_scope.getSource(self);
1641
1642 var keep_zir_module = false;
1643 const zir_module = try self.gpa.create(zir.Module);
1644 defer if (!keep_zir_module) self.gpa.destroy(zir_module);
1645
1646 zir_module.* = try zir.parse(self.gpa, source);
1647 defer if (!keep_zir_module) zir_module.deinit(self.gpa);
1648
1649 if (zir_module.error_msg) |src_err_msg| {
1650 self.failed_files.putAssumeCapacityNoClobber(
1651 &root_scope.base,
1652 try Compilation.ErrorMsg.create(self.gpa, src_err_msg.byte_offset, "{s}", .{src_err_msg.msg}),
1653 );
1654 root_scope.status = .unloaded_parse_failure;
1655 return error.AnalysisFail;
1656 }
1657
1658 root_scope.status = .loaded_success;
1659 root_scope.contents = .{ .module = zir_module };
1660 keep_zir_module = true;
1661
1662 return zir_module;
1663 },
1664
1665 .unloaded_parse_failure,
1666 .unloaded_sema_failure,
1667 => return error.AnalysisFail,
1668
1669 .loaded_success, .loaded_sema_failure => return root_scope.contents.module,
1670 }
1671}
1672
16731521pub fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
16741522 const tracy = trace(@src());
16751523 defer tracy.end();
......@@ -1691,10 +1539,13 @@ pub fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
16911539 defer msg.deinit();
16921540
16931541 try parse_err.render(tree.token_ids, msg.writer());
1694 const err_msg = try self.gpa.create(Compilation.ErrorMsg);
1542 const err_msg = try self.gpa.create(ErrorMsg);
16951543 err_msg.* = .{
1544 .src_loc = .{
1545 .file_scope = root_scope,
1546 .byte_offset = tree.token_locs[parse_err.loc()].start,
1547 },
16961548 .msg = msg.toOwnedSlice(),
1697 .byte_offset = tree.token_locs[parse_err.loc()].start,
16981549 };
16991550
17001551 self.failed_files.putAssumeCapacityNoClobber(&root_scope.base, err_msg);
......@@ -1753,9 +1604,12 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
17531604 decl.src_index = decl_i;
17541605 if (deleted_decls.swapRemove(decl) == null) {
17551606 decl.analysis = .sema_failure;
1756 const err_msg = try Compilation.ErrorMsg.create(self.gpa, tree.token_locs[name_tok].start, "redefinition of '{s}'", .{decl.name});
1757 errdefer err_msg.destroy(self.gpa);
1758 try self.failed_decls.putNoClobber(self.gpa, decl, err_msg);
1607 const msg = try ErrorMsg.create(self.gpa, .{
1608 .file_scope = container_scope.file_scope,
1609 .byte_offset = tree.token_locs[name_tok].start,
1610 }, "redefinition of '{s}'", .{decl.name});
1611 errdefer msg.destroy(self.gpa);
1612 try self.failed_decls.putNoClobber(self.gpa, decl, msg);
17591613 } else {
17601614 if (!srcHashEql(decl.contents_hash, contents_hash)) {
17611615 try self.markOutdatedDecl(decl);
......@@ -1795,7 +1649,10 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
17951649 decl.src_index = decl_i;
17961650 if (deleted_decls.swapRemove(decl) == null) {
17971651 decl.analysis = .sema_failure;
1798 const err_msg = try Compilation.ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{s}'", .{decl.name});
1652 const err_msg = try ErrorMsg.create(self.gpa, .{
1653 .file_scope = container_scope.file_scope,
1654 .byte_offset = name_loc.start,
1655 }, "redefinition of '{s}'", .{decl.name});
17991656 errdefer err_msg.destroy(self.gpa);
18001657 try self.failed_decls.putNoClobber(self.gpa, decl, err_msg);
18011658 } else if (!srcHashEql(decl.contents_hash, contents_hash)) {
......@@ -1840,65 +1697,12 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
18401697 }
18411698}
18421699
1843pub fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
1844 // We may be analyzing it for the first time, or this may be
1845 // an incremental update. This code handles both cases.
1846 const src_module = try self.getSrcModule(root_scope);
1847
1848 try self.comp.work_queue.ensureUnusedCapacity(src_module.decls.len);
1849 try root_scope.decls.ensureCapacity(self.gpa, src_module.decls.len);
1850
1851 var exports_to_resolve = std.ArrayList(*zir.Decl).init(self.gpa);
1852 defer exports_to_resolve.deinit();
1853
1854 // Keep track of the decls that we expect to see in this file so that
1855 // we know which ones have been deleted.
1856 var deleted_decls = std.AutoArrayHashMap(*Decl, void).init(self.gpa);
1857 defer deleted_decls.deinit();
1858 try deleted_decls.ensureCapacity(self.decl_table.items().len);
1859 for (self.decl_table.items()) |entry| {
1860 deleted_decls.putAssumeCapacityNoClobber(entry.value, {});
1861 }
1862
1863 for (src_module.decls) |src_decl, decl_i| {
1864 const name_hash = root_scope.fullyQualifiedNameHash(src_decl.name);
1865 if (self.decl_table.get(name_hash)) |decl| {
1866 deleted_decls.removeAssertDiscard(decl);
1867 if (!srcHashEql(src_decl.contents_hash, decl.contents_hash)) {
1868 try self.markOutdatedDecl(decl);
1869 decl.contents_hash = src_decl.contents_hash;
1870 }
1871 } else {
1872 const new_decl = try self.createNewDecl(
1873 &root_scope.base,
1874 src_decl.name,
1875 decl_i,
1876 name_hash,
1877 src_decl.contents_hash,
1878 );
1879 root_scope.decls.appendAssumeCapacity(new_decl);
1880 if (src_decl.inst.cast(zir.Inst.Export)) |export_inst| {
1881 try exports_to_resolve.append(src_decl);
1882 }
1883 }
1884 }
1885 for (exports_to_resolve.items) |export_decl| {
1886 _ = try zir_sema.resolveZirDecl(self, &root_scope.base, export_decl);
1887 }
1888 // Handle explicitly deleted decls from the source code. Not to be confused
1889 // with when we delete decls because they are no longer referenced.
1890 for (deleted_decls.items()) |entry| {
1891 log.debug("noticed '{s}' deleted from source\n", .{entry.key.name});
1892 try self.deleteDecl(entry.key);
1893 }
1894}
1895
18961700pub fn deleteDecl(self: *Module, decl: *Decl) !void {
18971701 try self.deletion_set.ensureCapacity(self.gpa, self.deletion_set.items.len + decl.dependencies.items().len);
18981702
18991703 // Remove from the namespace it resides in. In the case of an anonymous Decl it will
19001704 // not be present in the set, and this does nothing.
1901 decl.scope.removeDecl(decl);
1705 decl.container.removeDecl(decl);
19021706
19031707 log.debug("deleting decl '{s}'\n", .{decl.name});
19041708 const name_hash = decl.fullyQualifiedNameHash();
......@@ -1929,9 +1733,7 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void {
19291733 if (self.emit_h_failed_decls.swapRemove(decl)) |entry| {
19301734 entry.value.destroy(self.gpa);
19311735 }
1932 if (self.compile_log_decls.swapRemove(decl)) |*entry| {
1933 entry.value.deinit(self.gpa);
1934 }
1736 _ = self.compile_log_decls.swapRemove(decl);
19351737 self.deleteDeclExports(decl);
19361738 self.comp.bin_file.freeDecl(decl);
19371739
......@@ -1993,7 +1795,8 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
19931795 .parent = null,
19941796 .inst_table = &inst_table,
19951797 .func = func,
1996 .decl = decl,
1798 .owner_decl = decl,
1799 .src_decl = decl,
19971800 .instructions = .{},
19981801 .arena = &arena.allocator,
19991802 .inlining = null,
......@@ -2022,9 +1825,7 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {
20221825 if (self.emit_h_failed_decls.swapRemove(decl)) |entry| {
20231826 entry.value.destroy(self.gpa);
20241827 }
2025 if (self.compile_log_decls.swapRemove(decl)) |*entry| {
2026 entry.value.deinit(self.gpa);
2027 }
1828 _ = self.compile_log_decls.swapRemove(decl);
20281829 decl.analysis = .outdated;
20291830}
20301831
......@@ -2046,7 +1847,7 @@ fn allocateNewDecl(
20461847
20471848 new_decl.* = .{
20481849 .name = "",
2049 .scope = scope.namespace(),
1850 .container = scope.namespace(),
20501851 .src_index = src_index,
20511852 .typed_value = .{ .never_succeeded = {} },
20521853 .analysis = .unreferenced,
......@@ -2129,34 +1930,34 @@ pub fn resolveDefinedValue(self: *Module, scope: *Scope, base: *Inst) !?Value {
21291930}
21301931
21311932pub fn analyzeExport(
2132 self: *Module,
1933 mod: *Module,
21331934 scope: *Scope,
21341935 src: usize,
21351936 borrowed_symbol_name: []const u8,
21361937 exported_decl: *Decl,
21371938) !void {
2138 try self.ensureDeclAnalyzed(exported_decl);
1939 try mod.ensureDeclAnalyzed(exported_decl);
21391940 const typed_value = exported_decl.typed_value.most_recent.typed_value;
21401941 switch (typed_value.ty.zigTypeTag()) {
21411942 .Fn => {},
2142 else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
1943 else => return mod.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
21431944 }
21441945
2145 try self.decl_exports.ensureCapacity(self.gpa, self.decl_exports.items().len + 1);
2146 try self.export_owners.ensureCapacity(self.gpa, self.export_owners.items().len + 1);
1946 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);
1947 try mod.export_owners.ensureCapacity(mod.gpa, mod.export_owners.items().len + 1);
21471948
2148 const new_export = try self.gpa.create(Export);
2149 errdefer self.gpa.destroy(new_export);
1949 const new_export = try mod.gpa.create(Export);
1950 errdefer mod.gpa.destroy(new_export);
21501951
2151 const symbol_name = try self.gpa.dupe(u8, borrowed_symbol_name);
2152 errdefer self.gpa.free(symbol_name);
1952 const symbol_name = try mod.gpa.dupe(u8, borrowed_symbol_name);
1953 errdefer mod.gpa.free(symbol_name);
21531954
2154 const owner_decl = scope.decl().?;
1955 const owner_decl = scope.ownerDecl().?;
21551956
21561957 new_export.* = .{
21571958 .options = .{ .name = symbol_name },
21581959 .src = src,
2159 .link = switch (self.comp.bin_file.tag) {
1960 .link = switch (mod.comp.bin_file.tag) {
21601961 .coff => .{ .coff = {} },
21611962 .elf => .{ .elf = link.File.Elf.Export{} },
21621963 .macho => .{ .macho = link.File.MachO.Export{} },
......@@ -2169,48 +1970,53 @@ pub fn analyzeExport(
21691970 };
21701971
21711972 // Add to export_owners table.
2172 const eo_gop = self.export_owners.getOrPutAssumeCapacity(owner_decl);
1973 const eo_gop = mod.export_owners.getOrPutAssumeCapacity(owner_decl);
21731974 if (!eo_gop.found_existing) {
21741975 eo_gop.entry.value = &[0]*Export{};
21751976 }
2176 eo_gop.entry.value = try self.gpa.realloc(eo_gop.entry.value, eo_gop.entry.value.len + 1);
1977 eo_gop.entry.value = try mod.gpa.realloc(eo_gop.entry.value, eo_gop.entry.value.len + 1);
21771978 eo_gop.entry.value[eo_gop.entry.value.len - 1] = new_export;
2178 errdefer eo_gop.entry.value = self.gpa.shrink(eo_gop.entry.value, eo_gop.entry.value.len - 1);
1979 errdefer eo_gop.entry.value = mod.gpa.shrink(eo_gop.entry.value, eo_gop.entry.value.len - 1);
21791980
21801981 // Add to exported_decl table.
2181 const de_gop = self.decl_exports.getOrPutAssumeCapacity(exported_decl);
1982 const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl);
21821983 if (!de_gop.found_existing) {
21831984 de_gop.entry.value = &[0]*Export{};
21841985 }
2185 de_gop.entry.value = try self.gpa.realloc(de_gop.entry.value, de_gop.entry.value.len + 1);
1986 de_gop.entry.value = try mod.gpa.realloc(de_gop.entry.value, de_gop.entry.value.len + 1);
21861987 de_gop.entry.value[de_gop.entry.value.len - 1] = new_export;
2187 errdefer de_gop.entry.value = self.gpa.shrink(de_gop.entry.value, de_gop.entry.value.len - 1);
1988 errdefer de_gop.entry.value = mod.gpa.shrink(de_gop.entry.value, de_gop.entry.value.len - 1);
21881989
2189 if (self.symbol_exports.get(symbol_name)) |_| {
2190 try self.failed_exports.ensureCapacity(self.gpa, self.failed_exports.items().len + 1);
2191 self.failed_exports.putAssumeCapacityNoClobber(new_export, try Compilation.ErrorMsg.create(
2192 self.gpa,
1990 if (mod.symbol_exports.get(symbol_name)) |other_export| {
1991 new_export.status = .failed_retryable;
1992 try mod.failed_exports.ensureCapacity(mod.gpa, mod.failed_exports.items().len + 1);
1993 const msg = try mod.errMsg(
1994 scope,
21931995 src,
21941996 "exported symbol collision: {s}",
21951997 .{symbol_name},
2196 ));
2197 // TODO: add a note
1998 );
1999 errdefer msg.destroy(mod.gpa);
2000 try mod.errNote(
2001 &other_export.owner_decl.container.base,
2002 other_export.src,
2003 msg,
2004 "other symbol here",
2005 .{},
2006 );
2007 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
21982008 new_export.status = .failed;
21992009 return;
22002010 }
22012011
2202 try self.symbol_exports.putNoClobber(self.gpa, symbol_name, new_export);
2203 self.comp.bin_file.updateDeclExports(self, exported_decl, de_gop.entry.value) catch |err| switch (err) {
2012 try mod.symbol_exports.putNoClobber(mod.gpa, symbol_name, new_export);
2013 mod.comp.bin_file.updateDeclExports(mod, exported_decl, de_gop.entry.value) catch |err| switch (err) {
22042014 error.OutOfMemory => return error.OutOfMemory,
22052015 else => {
2206 try self.failed_exports.ensureCapacity(self.gpa, self.failed_exports.items().len + 1);
2207 self.failed_exports.putAssumeCapacityNoClobber(new_export, try Compilation.ErrorMsg.create(
2208 self.gpa,
2209 src,
2210 "unable to export: {s}",
2211 .{@errorName(err)},
2212 ));
22132016 new_export.status = .failed_retryable;
2017 try mod.failed_exports.ensureCapacity(mod.gpa, mod.failed_exports.items().len + 1);
2018 const msg = try mod.errMsg(scope, src, "unable to export: {s}", .{@errorName(err)});
2019 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
22142020 },
22152021 };
22162022}
......@@ -2476,7 +2282,7 @@ pub fn createAnonymousDecl(
24762282 typed_value: TypedValue,
24772283) !*Decl {
24782284 const name_index = self.getNextAnonNameIndex();
2479 const scope_decl = scope.decl().?;
2285 const scope_decl = scope.ownerDecl().?;
24802286 const name = try std.fmt.allocPrint(self.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
24812287 defer self.gpa.free(name);
24822288 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
......@@ -2512,7 +2318,7 @@ pub fn createContainerDecl(
25122318 decl_arena: *std.heap.ArenaAllocator,
25132319 typed_value: TypedValue,
25142320) !*Decl {
2515 const scope_decl = scope.decl().?;
2321 const scope_decl = scope.ownerDecl().?;
25162322 const name = try self.getAnonTypeName(scope, base_token);
25172323 defer self.gpa.free(name);
25182324 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
......@@ -2558,14 +2364,14 @@ pub fn lookupDeclName(self: *Module, scope: *Scope, ident_name: []const u8) ?*De
25582364}
25592365
25602366pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
2561 const scope_decl = scope.decl().?;
2367 const scope_decl = scope.ownerDecl().?;
25622368 try self.declareDeclDependency(scope_decl, decl);
25632369 self.ensureDeclAnalyzed(decl) catch |err| {
25642370 if (scope.cast(Scope.Block)) |block| {
25652371 if (block.func) |func| {
25662372 func.state = .dependency_failure;
25672373 } else {
2568 block.decl.analysis = .dependency_failure;
2374 block.owner_decl.analysis = .dependency_failure;
25692375 }
25702376 } else {
25712377 scope_decl.analysis = .dependency_failure;
......@@ -3217,10 +3023,51 @@ fn coerceArrayPtrToMany(self: *Module, scope: *Scope, dest_type: Type, inst: *In
32173023 return self.fail(scope, inst.src, "TODO implement coerceArrayPtrToMany runtime instruction", .{});
32183024}
32193025
3220pub fn fail(self: *Module, scope: *Scope, src: usize, comptime format: []const u8, args: anytype) InnerError {
3221 @setCold(true);
3222 const err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args);
3223 return self.failWithOwnedErrorMsg(scope, src, err_msg);
3026/// We don't return a pointer to the new error note because the pointer
3027/// becomes invalid when you add another one.
3028pub fn errNote(
3029 mod: *Module,
3030 scope: *Scope,
3031 src: usize,
3032 parent: *ErrorMsg,
3033 comptime format: []const u8,
3034 args: anytype,
3035) error{OutOfMemory}!void {
3036 const msg = try std.fmt.allocPrint(mod.gpa, format, args);
3037 errdefer mod.gpa.free(msg);
3038
3039 parent.notes = try mod.gpa.realloc(parent.notes, parent.notes.len + 1);
3040 parent.notes[parent.notes.len - 1] = .{
3041 .src_loc = .{
3042 .file_scope = scope.getFileScope(),
3043 .byte_offset = src,
3044 },
3045 .msg = msg,
3046 };
3047}
3048
3049pub fn errMsg(
3050 mod: *Module,
3051 scope: *Scope,
3052 src_byte_offset: usize,
3053 comptime format: []const u8,
3054 args: anytype,
3055) error{OutOfMemory}!*ErrorMsg {
3056 return ErrorMsg.create(mod.gpa, .{
3057 .file_scope = scope.getFileScope(),
3058 .byte_offset = src_byte_offset,
3059 }, format, args);
3060}
3061
3062pub fn fail(
3063 mod: *Module,
3064 scope: *Scope,
3065 src_byte_offset: usize,
3066 comptime format: []const u8,
3067 args: anytype,
3068) InnerError {
3069 const err_msg = try mod.errMsg(scope, src_byte_offset, format, args);
3070 return mod.failWithOwnedErrorMsg(scope, err_msg);
32243071}
32253072
32263073pub fn failTok(
......@@ -3230,7 +3077,6 @@ pub fn failTok(
32303077 comptime format: []const u8,
32313078 args: anytype,
32323079) InnerError {
3233 @setCold(true);
32343080 const src = scope.tree().token_locs[token_index].start;
32353081 return self.fail(scope, src, format, args);
32363082}
......@@ -3242,80 +3088,36 @@ pub fn failNode(
32423088 comptime format: []const u8,
32433089 args: anytype,
32443090) InnerError {
3245 @setCold(true);
32463091 const src = scope.tree().token_locs[ast_node.firstToken()].start;
32473092 return self.fail(scope, src, format, args);
32483093}
32493094
3250fn addCompileLog(self: *Module, decl: *Decl, src: usize) error{OutOfMemory}!void {
3251 const entry = try self.compile_log_decls.getOrPutValue(self.gpa, decl, .{});
3252 try entry.value.append(self.gpa, src);
3253}
3254
3255pub fn failCompileLog(
3256 self: *Module,
3257 scope: *Scope,
3258 src: usize,
3259) InnerError!void {
3260 switch (scope.tag) {
3261 .decl => {
3262 const decl = scope.cast(Scope.DeclAnalysis).?.decl;
3263 try self.addCompileLog(decl, src);
3264 },
3265 .block => {
3266 const block = scope.cast(Scope.Block).?;
3267 try self.addCompileLog(block.decl, src);
3268 },
3269 .gen_zir => {
3270 const gen_zir = scope.cast(Scope.GenZIR).?;
3271 try self.addCompileLog(gen_zir.decl, src);
3272 },
3273 .local_val => {
3274 const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir;
3275 try self.addCompileLog(gen_zir.decl, src);
3276 },
3277 .local_ptr => {
3278 const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir;
3279 try self.addCompileLog(gen_zir.decl, src);
3280 },
3281 .zir_module,
3282 .file,
3283 .container,
3284 => unreachable,
3285 }
3286}
3287
3288fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError {
3095pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) InnerError {
3096 @setCold(true);
32893097 {
32903098 errdefer err_msg.destroy(self.gpa);
32913099 try self.failed_decls.ensureCapacity(self.gpa, self.failed_decls.items().len + 1);
32923100 try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1);
32933101 }
32943102 switch (scope.tag) {
3295 .decl => {
3296 const decl = scope.cast(Scope.DeclAnalysis).?.decl;
3297 decl.analysis = .sema_failure;
3298 decl.generation = self.generation;
3299 self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);
3300 },
33013103 .block => {
33023104 const block = scope.cast(Scope.Block).?;
33033105 if (block.inlining) |inlining| {
33043106 if (inlining.shared.caller) |func| {
33053107 func.state = .sema_failure;
33063108 } else {
3307 block.decl.analysis = .sema_failure;
3308 block.decl.generation = self.generation;
3109 block.owner_decl.analysis = .sema_failure;
3110 block.owner_decl.generation = self.generation;
33093111 }
33103112 } else {
33113113 if (block.func) |func| {
33123114 func.state = .sema_failure;
33133115 } else {
3314 block.decl.analysis = .sema_failure;
3315 block.decl.generation = self.generation;
3116 block.owner_decl.analysis = .sema_failure;
3117 block.owner_decl.generation = self.generation;
33163118 }
33173119 }
3318 self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);
3120 self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg);
33193121 },
33203122 .gen_zir => {
33213123 const gen_zir = scope.cast(Scope.GenZIR).?;
......@@ -3335,11 +3137,6 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Com
33353137 gen_zir.decl.generation = self.generation;
33363138 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
33373139 },
3338 .zir_module => {
3339 const zir_module = scope.cast(Scope.ZIRModule).?;
3340 zir_module.status = .loaded_sema_failure;
3341 self.failed_files.putAssumeCapacityNoClobber(scope, err_msg);
3342 },
33433140 .file => unreachable,
33443141 .container => unreachable,
33453142 }
......@@ -3671,7 +3468,8 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic
36713468 .parent = parent_block,
36723469 .inst_table = parent_block.inst_table,
36733470 .func = parent_block.func,
3674 .decl = parent_block.decl,
3471 .owner_decl = parent_block.owner_decl,
3472 .src_decl = parent_block.src_decl,
36753473 .instructions = .{},
36763474 .arena = parent_block.arena,
36773475 .inlining = parent_block.inlining,
src/astgen.zig+56-21
......@@ -318,7 +318,7 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as
318318 // Make a scope to collect generated instructions in the sub-expression.
319319 var block_scope: Scope.GenZIR = .{
320320 .parent = parent_scope,
321 .decl = parent_scope.decl().?,
321 .decl = parent_scope.ownerDecl().?,
322322 .arena = parent_scope.arena(),
323323 .instructions = .{},
324324 };
......@@ -474,7 +474,7 @@ fn labeledBlockExpr(
474474
475475 var block_scope: Scope.GenZIR = .{
476476 .parent = parent_scope,
477 .decl = parent_scope.decl().?,
477 .decl = parent_scope.ownerDecl().?,
478478 .arena = gen_zir.arena,
479479 .instructions = .{},
480480 .break_result_loc = rl,
......@@ -899,7 +899,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
899899
900900 var gen_scope: Scope.GenZIR = .{
901901 .parent = scope,
902 .decl = scope.decl().?,
902 .decl = scope.ownerDecl().?,
903903 .arena = scope.arena(),
904904 .instructions = .{},
905905 };
......@@ -1028,7 +1028,13 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
10281028 .ty = Type.initTag(.type),
10291029 .val = val,
10301030 });
1031 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
1031 if (rl == .ref) {
1032 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});
1033 } else {
1034 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{
1035 .decl = decl,
1036 }, .{}));
1037 }
10321038}
10331039
10341040fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
......@@ -1084,7 +1090,7 @@ fn orelseCatchExpr(
10841090
10851091 var block_scope: Scope.GenZIR = .{
10861092 .parent = scope,
1087 .decl = scope.decl().?,
1093 .decl = scope.ownerDecl().?,
10881094 .arena = scope.arena(),
10891095 .instructions = .{},
10901096 };
......@@ -1266,7 +1272,7 @@ fn boolBinOp(
12661272
12671273 var block_scope: Scope.GenZIR = .{
12681274 .parent = scope,
1269 .decl = scope.decl().?,
1275 .decl = scope.ownerDecl().?,
12701276 .arena = scope.arena(),
12711277 .instructions = .{},
12721278 };
......@@ -1412,7 +1418,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
14121418 }
14131419 var block_scope: Scope.GenZIR = .{
14141420 .parent = scope,
1415 .decl = scope.decl().?,
1421 .decl = scope.ownerDecl().?,
14161422 .arena = scope.arena(),
14171423 .instructions = .{},
14181424 };
......@@ -1513,7 +1519,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
15131519
15141520 var expr_scope: Scope.GenZIR = .{
15151521 .parent = scope,
1516 .decl = scope.decl().?,
1522 .decl = scope.ownerDecl().?,
15171523 .arena = scope.arena(),
15181524 .instructions = .{},
15191525 };
......@@ -1649,7 +1655,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
16491655
16501656 var for_scope: Scope.GenZIR = .{
16511657 .parent = scope,
1652 .decl = scope.decl().?,
1658 .decl = scope.ownerDecl().?,
16531659 .arena = scope.arena(),
16541660 .instructions = .{},
16551661 };
......@@ -1843,7 +1849,7 @@ fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp {
18431849fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.Switch) InnerError!*zir.Inst {
18441850 var block_scope: Scope.GenZIR = .{
18451851 .parent = scope,
1846 .decl = scope.decl().?,
1852 .decl = scope.ownerDecl().?,
18471853 .arena = scope.arena(),
18481854 .instructions = .{},
18491855 };
......@@ -1885,7 +1891,7 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node
18851891
18861892 var item_scope: Scope.GenZIR = .{
18871893 .parent = scope,
1888 .decl = scope.decl().?,
1894 .decl = scope.ownerDecl().?,
18891895 .arena = scope.arena(),
18901896 .instructions = .{},
18911897 };
......@@ -1922,8 +1928,15 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node
19221928 // Check for else/_ prong, those are handled last.
19231929 if (case.items_len == 1 and case.items()[0].tag == .SwitchElse) {
19241930 if (else_src) |src| {
1925 return mod.fail(scope, case_src, "multiple else prongs in switch expression", .{});
1926 // TODO notes "previous else prong is here"
1931 const msg = try mod.errMsg(
1932 scope,
1933 case_src,
1934 "multiple else prongs in switch expression",
1935 .{},
1936 );
1937 errdefer msg.destroy(mod.gpa);
1938 try mod.errNote(scope, src, msg, "previous else prong is here", .{});
1939 return mod.failWithOwnedErrorMsg(scope, msg);
19271940 }
19281941 else_src = case_src;
19291942 special_case = case;
......@@ -1932,8 +1945,15 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node
19321945 mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_"))
19331946 {
19341947 if (underscore_src) |src| {
1935 return mod.fail(scope, case_src, "multiple '_' prongs in switch expression", .{});
1936 // TODO notes "previous '_' prong is here"
1948 const msg = try mod.errMsg(
1949 scope,
1950 case_src,
1951 "multiple '_' prongs in switch expression",
1952 .{},
1953 );
1954 errdefer msg.destroy(mod.gpa);
1955 try mod.errNote(scope, src, msg, "previous '_' prong is here", .{});
1956 return mod.failWithOwnedErrorMsg(scope, msg);
19371957 }
19381958 underscore_src = case_src;
19391959 special_case = case;
......@@ -1942,9 +1962,16 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node
19421962
19431963 if (else_src) |some_else| {
19441964 if (underscore_src) |some_underscore| {
1945 return mod.fail(scope, switch_src, "else and '_' prong in switch expression", .{});
1946 // TODO notes "else prong is here"
1947 // TODO notes "'_' prong is here"
1965 const msg = try mod.errMsg(
1966 scope,
1967 switch_src,
1968 "else and '_' prong in switch expression",
1969 .{},
1970 );
1971 errdefer msg.destroy(mod.gpa);
1972 try mod.errNote(scope, some_else, msg, "else prong is here", .{});
1973 try mod.errNote(scope, some_underscore, msg, "'_' prong is here", .{});
1974 return mod.failWithOwnedErrorMsg(scope, msg);
19481975 }
19491976 }
19501977
......@@ -2162,7 +2189,13 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
21622189 }
21632190
21642191 if (mod.lookupDeclName(scope, ident_name)) |decl| {
2165 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
2192 if (rl == .ref) {
2193 return addZIRInst(mod, scope, src, zir.Inst.DeclRef, .{ .decl = decl }, .{});
2194 } else {
2195 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclVal, .{
2196 .decl = decl,
2197 }, .{}));
2198 }
21662199 }
21672200
21682201 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{s}'", .{ident_name});
......@@ -2927,6 +2960,8 @@ fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, resul
29272960 return rlWrap(mod, scope, rl, void_inst);
29282961}
29292962
2963/// TODO go over all the callsites and see where we can introduce "by-value" ZIR instructions
2964/// to save ZIR memory. For example, see DeclVal vs DeclRef.
29302965fn rlWrapPtr(mod: *Module, scope: *Scope, rl: ResultLoc, ptr: *zir.Inst) InnerError!*zir.Inst {
29312966 if (rl == .ref) return ptr;
29322967
......@@ -3032,7 +3067,7 @@ pub fn addZIRInstBlock(
30323067 scope: *Scope,
30333068 src: usize,
30343069 tag: zir.Inst.Tag,
3035 body: zir.Module.Body,
3070 body: zir.Body,
30363071) !*zir.Inst.Block {
30373072 const gen_zir = scope.getGenZIR();
30383073 try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
......@@ -3070,7 +3105,7 @@ pub fn addZIRInstConst(mod: *Module, scope: *Scope, src: usize, typed_value: Typ
30703105}
30713106
30723107/// TODO The existence of this function is a workaround for a bug in stage1.
3073pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop {
3108pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Body) !*zir.Inst.Loop {
30743109 const P = std.meta.fieldInfo(zir.Inst.Loop, .positionals).field_type;
30753110 return addZIRInstSpecial(mod, scope, src, zir.Inst.Loop, P{ .body = body }, .{});
30763111}
src/codegen.zig+87-79
......@@ -9,7 +9,7 @@ const TypedValue = @import("TypedValue.zig");
99const link = @import("link.zig");
1010const Module = @import("Module.zig");
1111const Compilation = @import("Compilation.zig");
12const ErrorMsg = Compilation.ErrorMsg;
12const ErrorMsg = Module.ErrorMsg;
1313const Target = std.Target;
1414const Allocator = mem.Allocator;
1515const trace = @import("tracy.zig").trace;
......@@ -74,7 +74,7 @@ pub const DebugInfoOutput = union(enum) {
7474
7575pub fn generateSymbol(
7676 bin_file: *link.File,
77 src: usize,
77 src_loc: Module.SrcLoc,
7878 typed_value: TypedValue,
7979 code: *std.ArrayList(u8),
8080 debug_output: DebugInfoOutput,
......@@ -87,56 +87,56 @@ pub fn generateSymbol(
8787 switch (bin_file.options.target.cpu.arch) {
8888 .wasm32 => unreachable, // has its own code path
8989 .wasm64 => unreachable, // has its own code path
90 .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, debug_output),
91 .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
92 .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, debug_output),
93 .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, debug_output),
94 .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, debug_output),
95 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, debug_output),
96 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, debug_output),
97 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, debug_output),
98 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
99 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, debug_output),
100 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, debug_output),
101 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, debug_output),
102 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, debug_output),
103 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, debug_output),
104 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, debug_output),
105 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, debug_output),
106 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, debug_output),
107 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, debug_output),
108 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, debug_output),
109 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, debug_output),
110 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, debug_output),
111 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, debug_output),
112 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, debug_output),
113 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, debug_output),
114 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, debug_output),
115 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, debug_output),
116 .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src, typed_value, code, debug_output),
117 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, debug_output),
118 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, debug_output),
119 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, debug_output),
120 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
121 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, debug_output),
122 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, debug_output),
123 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, debug_output),
124 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, debug_output),
125 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, debug_output),
126 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, debug_output),
127 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, debug_output),
128 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, debug_output),
129 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, debug_output),
130 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, debug_output),
131 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, debug_output),
132 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, debug_output),
133 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, debug_output),
134 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, debug_output),
135 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, debug_output),
136 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, debug_output),
137 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, debug_output),
138 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, debug_output),
139 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, debug_output),
90 .arm => return Function(.arm).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
91 .armeb => return Function(.armeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
92 .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
93 .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
94 .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
95 //.arc => return Function(.arc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
96 //.avr => return Function(.avr).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
97 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
98 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
99 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
100 //.mips => return Function(.mips).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
101 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
102 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
103 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
104 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
105 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
106 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
107 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
108 //.r600 => return Function(.r600).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
109 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
110 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
111 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
112 //.sparc => return Function(.sparc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
113 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
114 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
115 //.s390x => return Function(.s390x).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
116 .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
117 //.tce => return Function(.tce).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
118 //.tcele => return Function(.tcele).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
119 //.thumb => return Function(.thumb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
120 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
121 //.i386 => return Function(.i386).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
122 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
123 //.xcore => return Function(.xcore).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
124 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
125 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
126 //.le32 => return Function(.le32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
127 //.le64 => return Function(.le64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
128 //.amdil => return Function(.amdil).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
129 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
130 //.hsail => return Function(.hsail).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
131 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
132 //.spir => return Function(.spir).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
133 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
134 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
135 //.shave => return Function(.shave).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
136 //.lanai => return Function(.lanai).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
137 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
138 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
139 //.ve => return Function(.ve).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
140140 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
141141 }
142142 },
......@@ -147,7 +147,7 @@ pub fn generateSymbol(
147147 try code.ensureCapacity(code.items.len + payload.data.len + 1);
148148 code.appendSliceAssumeCapacity(payload.data);
149149 const prev_len = code.items.len;
150 switch (try generateSymbol(bin_file, src, .{
150 switch (try generateSymbol(bin_file, src_loc, .{
151151 .ty = typed_value.ty.elemType(),
152152 .val = sentinel,
153153 }, code, debug_output)) {
......@@ -165,7 +165,7 @@ pub fn generateSymbol(
165165 return Result{
166166 .fail = try ErrorMsg.create(
167167 bin_file.allocator,
168 src,
168 src_loc,
169169 "TODO implement generateSymbol for more kinds of arrays",
170170 .{},
171171 ),
......@@ -200,7 +200,7 @@ pub fn generateSymbol(
200200 return Result{
201201 .fail = try ErrorMsg.create(
202202 bin_file.allocator,
203 src,
203 src_loc,
204204 "TODO implement generateSymbol for pointer {}",
205205 .{typed_value.val},
206206 ),
......@@ -217,7 +217,7 @@ pub fn generateSymbol(
217217 return Result{
218218 .fail = try ErrorMsg.create(
219219 bin_file.allocator,
220 src,
220 src_loc,
221221 "TODO implement generateSymbol for int type '{}'",
222222 .{typed_value.ty},
223223 ),
......@@ -227,7 +227,7 @@ pub fn generateSymbol(
227227 return Result{
228228 .fail = try ErrorMsg.create(
229229 bin_file.allocator,
230 src,
230 src_loc,
231231 "TODO implement generateSymbol for type '{s}'",
232232 .{@tagName(t)},
233233 ),
......@@ -259,7 +259,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
259259 ret_mcv: MCValue,
260260 fn_type: Type,
261261 arg_index: usize,
262 src: usize,
262 src_loc: Module.SrcLoc,
263263 stack_align: u32,
264264
265265 /// Byte offset within the source file.
......@@ -428,7 +428,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
428428
429429 fn generateSymbol(
430430 bin_file: *link.File,
431 src: usize,
431 src_loc: Module.SrcLoc,
432432 typed_value: TypedValue,
433433 code: *std.ArrayList(u8),
434434 debug_output: DebugInfoOutput,
......@@ -450,19 +450,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
450450 try branch_stack.append(.{});
451451
452452 const src_data: struct { lbrace_src: usize, rbrace_src: usize, source: []const u8 } = blk: {
453 if (module_fn.owner_decl.scope.cast(Module.Scope.Container)) |container_scope| {
454 const tree = container_scope.file_scope.contents.tree;
455 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;
456 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
457 const lbrace_src = tree.token_locs[block.lbrace].start;
458 const rbrace_src = tree.token_locs[block.rbrace].start;
459 break :blk .{ .lbrace_src = lbrace_src, .rbrace_src = rbrace_src, .source = tree.source };
460 } else if (module_fn.owner_decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| {
461 const byte_off = zir_module.contents.module.decls[module_fn.owner_decl.src_index].inst.src;
462 break :blk .{ .lbrace_src = byte_off, .rbrace_src = byte_off, .source = zir_module.source.bytes };
463 } else {
464 unreachable;
465 }
453 const container_scope = module_fn.owner_decl.container;
454 const tree = container_scope.file_scope.contents.tree;
455 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;
456 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
457 const lbrace_src = tree.token_locs[block.lbrace].start;
458 const rbrace_src = tree.token_locs[block.rbrace].start;
459 break :blk .{
460 .lbrace_src = lbrace_src,
461 .rbrace_src = rbrace_src,
462 .source = tree.source,
463 };
466464 };
467465
468466 var function = Self{
......@@ -478,7 +476,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
478476 .fn_type = fn_type,
479477 .arg_index = 0,
480478 .branch_stack = &branch_stack,
481 .src = src,
479 .src_loc = src_loc,
482480 .stack_align = undefined,
483481 .prev_di_pc = 0,
484482 .prev_di_src = src_data.lbrace_src,
......@@ -489,7 +487,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
489487 defer function.stack.deinit(bin_file.allocator);
490488 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
491489
492 var call_info = function.resolveCallingConventionValues(src, fn_type) catch |err| switch (err) {
490 var call_info = function.resolveCallingConventionValues(src_loc.byte_offset, fn_type) catch |err| switch (err) {
493491 error.CodegenFail => return Result{ .fail = function.err_msg.? },
494492 else => |e| return e,
495493 };
......@@ -536,12 +534,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
536534
537535 const stack_end = self.max_end_stack;
538536 if (stack_end > math.maxInt(i32))
539 return self.fail(self.src, "too much stack used in call parameters", .{});
537 return self.failSymbol("too much stack used in call parameters", .{});
540538 const aligned_stack_end = mem.alignForward(stack_end, self.stack_align);
541539 mem.writeIntLittle(u32, self.code.items[reloc_index..][0..4], @intCast(u32, aligned_stack_end));
542540
543541 if (self.code.items.len >= math.maxInt(i32)) {
544 return self.fail(self.src, "unable to perform relocation: jump too far", .{});
542 return self.failSymbol("unable to perform relocation: jump too far", .{});
545543 }
546544 if (self.exitlude_jump_relocs.items.len == 1) {
547545 self.code.items.len -= 5;
......@@ -598,7 +596,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
598596 if (Instruction.Operand.fromU32(@intCast(u32, aligned_stack_end))) |op| {
599597 writeInt(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.al, .sp, .sp, op).toU32());
600598 } else {
601 return self.fail(self.src, "TODO ARM: allow larger stacks", .{});
599 return self.failSymbol("TODO ARM: allow larger stacks", .{});
602600 }
603601
604602 try self.dbgSetEpilogueBegin();
......@@ -624,7 +622,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
624622 if (math.cast(i26, amt)) |offset| {
625623 writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(.al, offset).toU32());
626624 } else |err| {
627 return self.fail(self.src, "exitlude jump is too large", .{});
625 return self.failSymbol("exitlude jump is too large", .{});
628626 }
629627 }
630628 }
......@@ -3678,7 +3676,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
36783676 fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) InnerError {
36793677 @setCold(true);
36803678 assert(self.err_msg == null);
3681 self.err_msg = try ErrorMsg.create(self.bin_file.allocator, src, format, args);
3679 self.err_msg = try ErrorMsg.create(self.bin_file.allocator, .{
3680 .file_scope = self.src_loc.file_scope,
3681 .byte_offset = src,
3682 }, format, args);
3683 return error.CodegenFail;
3684 }
3685
3686 fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError {
3687 @setCold(true);
3688 assert(self.err_msg == null);
3689 self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args);
36823690 return error.CodegenFail;
36833691 }
36843692
src/codegen/c.zig+5-2
......@@ -114,10 +114,13 @@ pub const DeclGen = struct {
114114 module: *Module,
115115 decl: *Decl,
116116 fwd_decl: std.ArrayList(u8),
117 error_msg: ?*Compilation.ErrorMsg,
117 error_msg: ?*Module.ErrorMsg,
118118
119119 fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
120 dg.error_msg = try Compilation.ErrorMsg.create(dg.module.gpa, src, format, args);
120 dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{
121 .file_scope = dg.decl.getFileScope(),
122 .byte_offset = src,
123 }, format, args);
121124 return error.AnalysisFail;
122125 }
123126
src/codegen/llvm.zig+11-2
......@@ -148,7 +148,7 @@ pub const LLVMIRModule = struct {
148148 object_path: []const u8,
149149
150150 gpa: *Allocator,
151 err_msg: ?*Compilation.ErrorMsg = null,
151 err_msg: ?*Module.ErrorMsg = null,
152152
153153 // TODO: The fields below should really move into a different struct,
154154 // because they are only valid when generating a function
......@@ -177,6 +177,8 @@ pub const LLVMIRModule = struct {
177177 break_vals: *BreakValues,
178178 }) = .{},
179179
180 src_loc: Module.SrcLoc,
181
180182 const BreakBasicBlocks = std.ArrayListUnmanaged(*const llvm.BasicBlock);
181183 const BreakValues = std.ArrayListUnmanaged(*const llvm.Value);
182184
......@@ -254,6 +256,8 @@ pub const LLVMIRModule = struct {
254256 .builder = builder,
255257 .object_path = object_path,
256258 .gpa = gpa,
259 // TODO move this field into a struct that is only instantiated per gen() call
260 .src_loc = undefined,
257261 };
258262 return self;
259263 }
......@@ -335,6 +339,8 @@ pub const LLVMIRModule = struct {
335339 const typed_value = decl.typed_value.most_recent.typed_value;
336340 const src = decl.src();
337341
342 self.src_loc = decl.srcLoc();
343
338344 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });
339345
340346 if (typed_value.val.castTag(.function)) |func_payload| {
......@@ -853,7 +859,10 @@ pub const LLVMIRModule = struct {
853859 pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
854860 @setCold(true);
855861 assert(self.err_msg == null);
856 self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args);
862 self.err_msg = try Module.ErrorMsg.create(self.gpa, .{
863 .file_scope = self.src_loc.file_scope,
864 .byte_offset = src,
865 }, format, args);
857866 return error.CodegenFail;
858867 }
859868};
src/link/Coff.zig+3-3
......@@ -670,7 +670,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
670670 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
671671 defer code_buffer.deinit();
672672
673 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);
673 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);
674674 const code = switch (res) {
675675 .externally_managed => |x| x,
676676 .appended => code_buffer.items,
......@@ -732,7 +732,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
732732 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
733733 module.failed_exports.putAssumeCapacityNoClobber(
734734 exp,
735 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
735 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: ExportOptions.section", .{}),
736736 );
737737 continue;
738738 }
......@@ -743,7 +743,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
743743 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
744744 module.failed_exports.putAssumeCapacityNoClobber(
745745 exp,
746 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: Exports other than '_start'", .{}),
746 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: Exports other than '_start'", .{}),
747747 );
748748 continue;
749749 }
src/link/Elf.zig+12-21
......@@ -2189,22 +2189,14 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
21892189 try dbg_line_buffer.ensureCapacity(26);
21902190
21912191 const line_off: u28 = blk: {
2192 if (decl.scope.cast(Module.Scope.Container)) |container_scope| {
2193 const tree = container_scope.file_scope.contents.tree;
2194 const file_ast_decls = tree.root_node.decls();
2195 // TODO Look into improving the performance here by adding a token-index-to-line
2196 // lookup table. Currently this involves scanning over the source code for newlines.
2197 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
2198 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
2199 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
2200 break :blk @intCast(u28, line_delta);
2201 } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| {
2202 const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src;
2203 const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off);
2204 break :blk @intCast(u28, line_delta);
2205 } else {
2206 unreachable;
2207 }
2192 const tree = decl.container.file_scope.contents.tree;
2193 const file_ast_decls = tree.root_node.decls();
2194 // TODO Look into improving the performance here by adding a token-index-to-line
2195 // lookup table. Currently this involves scanning over the source code for newlines.
2196 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
2197 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
2198 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
2199 break :blk @intCast(u28, line_delta);
22082200 };
22092201
22102202 const ptr_width_bytes = self.ptrWidthBytes();
......@@ -2268,7 +2260,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
22682260 } else {
22692261 // TODO implement .debug_info for global variables
22702262 }
2271 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{
2263 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
22722264 .dwarf = .{
22732265 .dbg_line = &dbg_line_buffer,
22742266 .dbg_info = &dbg_info_buffer,
......@@ -2642,7 +2634,7 @@ pub fn updateDeclExports(
26422634 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
26432635 module.failed_exports.putAssumeCapacityNoClobber(
26442636 exp,
2645 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
2637 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: ExportOptions.section", .{}),
26462638 );
26472639 continue;
26482640 }
......@@ -2660,7 +2652,7 @@ pub fn updateDeclExports(
26602652 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
26612653 module.failed_exports.putAssumeCapacityNoClobber(
26622654 exp,
2663 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
2655 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: GlobalLinkage.LinkOnce", .{}),
26642656 );
26652657 continue;
26662658 },
......@@ -2703,8 +2695,7 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
27032695
27042696 if (self.llvm_ir_module) |_| return;
27052697
2706 const container_scope = decl.scope.cast(Module.Scope.Container).?;
2707 const tree = container_scope.file_scope.contents.tree;
2698 const tree = decl.container.file_scope.contents.tree;
27082699 const file_ast_decls = tree.root_node.decls();
27092700 // TODO Look into improving the performance here by adding a token-index-to-line
27102701 // lookup table. Currently this involves scanning over the source code for newlines.
src/link/MachO.zig+4-4
......@@ -1148,7 +1148,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11481148 }
11491149
11501150 const res = if (debug_buffers) |*dbg|
1151 try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{
1151 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
11521152 .dwarf = .{
11531153 .dbg_line = &dbg.dbg_line_buffer,
11541154 .dbg_info = &dbg.dbg_info_buffer,
......@@ -1156,7 +1156,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
11561156 },
11571157 })
11581158 else
1159 try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);
1159 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);
11601160
11611161 const code = switch (res) {
11621162 .externally_managed => |x| x,
......@@ -1316,7 +1316,7 @@ pub fn updateDeclExports(
13161316 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
13171317 module.failed_exports.putAssumeCapacityNoClobber(
13181318 exp,
1319 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
1319 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: ExportOptions.section", .{}),
13201320 );
13211321 continue;
13221322 }
......@@ -1334,7 +1334,7 @@ pub fn updateDeclExports(
13341334 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
13351335 module.failed_exports.putAssumeCapacityNoClobber(
13361336 exp,
1337 try Compilation.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
1337 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: GlobalLinkage.LinkOnce", .{}),
13381338 );
13391339 continue;
13401340 },
src/link/MachO/DebugSymbols.zig+9-18
......@@ -906,8 +906,7 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M
906906 const tracy = trace(@src());
907907 defer tracy.end();
908908
909 const container_scope = decl.scope.cast(Module.Scope.Container).?;
910 const tree = container_scope.file_scope.contents.tree;
909 const tree = decl.container.file_scope.contents.tree;
911910 const file_ast_decls = tree.root_node.decls();
912911 // TODO Look into improving the performance here by adding a token-index-to-line
913912 // lookup table. Currently this involves scanning over the source code for newlines.
......@@ -951,22 +950,14 @@ pub fn initDeclDebugBuffers(
951950 try dbg_line_buffer.ensureCapacity(26);
952951
953952 const line_off: u28 = blk: {
954 if (decl.scope.cast(Module.Scope.Container)) |container_scope| {
955 const tree = container_scope.file_scope.contents.tree;
956 const file_ast_decls = tree.root_node.decls();
957 // TODO Look into improving the performance here by adding a token-index-to-line
958 // lookup table. Currently this involves scanning over the source code for newlines.
959 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
960 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
961 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
962 break :blk @intCast(u28, line_delta);
963 } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| {
964 const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src;
965 const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off);
966 break :blk @intCast(u28, line_delta);
967 } else {
968 unreachable;
969 }
953 const tree = decl.container.file_scope.contents.tree;
954 const file_ast_decls = tree.root_node.decls();
955 // TODO Look into improving the performance here by adding a token-index-to-line
956 // lookup table. Currently this involves scanning over the source code for newlines.
957 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
958 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
959 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
960 break :blk @intCast(u28, line_delta);
970961 };
971962
972963 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
src/main.zig+14-33
......@@ -221,7 +221,6 @@ const usage_build_generic =
221221 \\
222222 \\Supported file types:
223223 \\ .zig Zig source code
224 \\ .zir Zig Intermediate Representation code
225224 \\ .o ELF object file
226225 \\ .o MACH-O (macOS) object file
227226 \\ .obj COFF (Windows) object file
......@@ -245,8 +244,6 @@ const usage_build_generic =
245244 \\ -fno-emit-bin Do not output machine code
246245 \\ -femit-asm[=path] Output .s (assembly code)
247246 \\ -fno-emit-asm (default) Do not output .s (assembly code)
248 \\ -femit-zir[=path] Produce a .zir file with Zig IR
249 \\ -fno-emit-zir (default) Do not produce a .zir file with Zig IR
250247 \\ -femit-llvm-ir[=path] Produce a .ll file with LLVM IR (requires LLVM extensions)
251248 \\ -fno-emit-llvm-ir (default) Do not produce a .ll file with LLVM IR
252249 \\ -femit-h[=path] Generate a C header file (.h)
......@@ -1631,18 +1628,12 @@ fn buildOutputType(
16311628 var emit_docs_resolved = try emit_docs.resolve("docs");
16321629 defer emit_docs_resolved.deinit();
16331630
1634 const zir_out_path: ?[]const u8 = switch (emit_zir) {
1635 .no => null,
1636 .yes_default_path => blk: {
1637 if (root_src_file) |rsf| {
1638 if (mem.endsWith(u8, rsf, ".zir")) {
1639 break :blk try std.fmt.allocPrint(arena, "{s}.out.zir", .{root_name});
1640 }
1641 }
1642 break :blk try std.fmt.allocPrint(arena, "{s}.zir", .{root_name});
1631 switch (emit_zir) {
1632 .no => {},
1633 .yes_default_path, .yes => {
1634 fatal("The -femit-zir implementation has been intentionally deleted so that it can be rewritten as a proper backend.", .{});
16431635 },
1644 .yes => |p| p,
1645 };
1636 }
16461637
16471638 const root_pkg: ?*Package = if (root_src_file) |src_path| blk: {
16481639 if (main_pkg_path) |p| {
......@@ -1753,7 +1744,7 @@ fn buildOutputType(
17531744 .dll_export_fns = dll_export_fns,
17541745 .object_format = object_format,
17551746 .optimize_mode = optimize_mode,
1756 .keep_source_files_loaded = zir_out_path != null,
1747 .keep_source_files_loaded = false,
17571748 .clang_argv = clang_argv.items,
17581749 .lld_argv = lld_argv.items,
17591750 .lib_dirs = lib_dirs.items,
......@@ -1845,7 +1836,7 @@ fn buildOutputType(
18451836 }
18461837 };
18471838
1848 updateModule(gpa, comp, zir_out_path, hook) catch |err| switch (err) {
1839 updateModule(gpa, comp, hook) catch |err| switch (err) {
18491840 error.SemanticAnalyzeFail => if (!watch) process.exit(1),
18501841 else => |e| return e,
18511842 };
......@@ -1980,7 +1971,7 @@ fn buildOutputType(
19801971 if (output_mode == .Exe) {
19811972 try comp.makeBinFileWritable();
19821973 }
1983 updateModule(gpa, comp, zir_out_path, hook) catch |err| switch (err) {
1974 updateModule(gpa, comp, hook) catch |err| switch (err) {
19841975 error.SemanticAnalyzeFail => continue,
19851976 else => |e| return e,
19861977 };
......@@ -2003,7 +1994,7 @@ const AfterUpdateHook = union(enum) {
20031994 update: []const u8,
20041995};
20051996
2006fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8, hook: AfterUpdateHook) !void {
1997fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !void {
20071998 try comp.update();
20081999
20092000 var errors = try comp.getAllErrorsAlloc();
......@@ -2013,6 +2004,10 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8,
20132004 for (errors.list) |full_err_msg| {
20142005 full_err_msg.renderToStdErr();
20152006 }
2007 const log_text = comp.getCompileLogOutput();
2008 if (log_text.len != 0) {
2009 std.debug.print("\nCompile Log Output:\n{s}", .{log_text});
2010 }
20162011 return error.SemanticAnalyzeFail;
20172012 } else switch (hook) {
20182013 .none => {},
......@@ -2024,20 +2019,6 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8,
20242019 .{},
20252020 ),
20262021 }
2027
2028 if (zir_out_path) |zop| {
2029 const module = comp.bin_file.options.module orelse
2030 fatal("-femit-zir with no zig source code", .{});
2031 var new_zir_module = try zir.emit(gpa, module);
2032 defer new_zir_module.deinit(gpa);
2033
2034 const baf = try io.BufferedAtomicFile.create(gpa, fs.cwd(), zop, .{});
2035 defer baf.destroy();
2036
2037 try new_zir_module.writeToStream(gpa, baf.writer());
2038
2039 try baf.finish();
2040 }
20412022}
20422023
20432024fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !void {
......@@ -2506,7 +2487,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
25062487 };
25072488 defer comp.destroy();
25082489
2509 try updateModule(gpa, comp, null, .none);
2490 try updateModule(gpa, comp, .none);
25102491 try comp.makeBinFileExecutable();
25112492
25122493 child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join(
src/test.zig+124-88
......@@ -15,6 +15,8 @@ const CrossTarget = std.zig.CrossTarget;
1515
1616const zig_h = link.File.C.zig_h;
1717
18const hr = "=" ** 40;
19
1820test "self-hosted" {
1921 var ctx = TestContext.init();
2022 defer ctx.deinit();
......@@ -29,23 +31,32 @@ const ErrorMsg = union(enum) {
2931 msg: []const u8,
3032 line: u32,
3133 column: u32,
34 kind: Kind,
3235 },
3336 plain: struct {
3437 msg: []const u8,
38 kind: Kind,
3539 },
3640
37 fn init(other: Compilation.AllErrors.Message) ErrorMsg {
41 const Kind = enum {
42 @"error",
43 note,
44 };
45
46 fn init(other: Compilation.AllErrors.Message, kind: Kind) ErrorMsg {
3847 switch (other) {
3948 .src => |src| return .{
4049 .src = .{
4150 .msg = src.msg,
4251 .line = @intCast(u32, src.line),
4352 .column = @intCast(u32, src.column),
53 .kind = kind,
4454 },
4555 },
4656 .plain => |plain| return .{
4757 .plain = .{
4858 .msg = plain.msg,
59 .kind = kind,
4960 },
5061 },
5162 }
......@@ -59,14 +70,15 @@ const ErrorMsg = union(enum) {
5970 ) !void {
6071 switch (self) {
6172 .src => |src| {
62 return writer.print(":{d}:{d}: error: {s}", .{
73 return writer.print(":{d}:{d}: {s}: {s}", .{
6374 src.line + 1,
6475 src.column + 1,
76 @tagName(src.kind),
6577 src.msg,
6678 });
6779 },
6880 .plain => |plain| {
69 return writer.print("error: {s}", .{plain.msg});
81 return writer.print("{s}: {s}", .{ plain.msg, @tagName(plain.kind) });
7082 },
7183 }
7284 }
......@@ -86,9 +98,6 @@ pub const TestContext = struct {
8698 /// effects of the incremental compilation.
8799 src: [:0]const u8,
88100 case: union(enum) {
89 /// A transformation update transforms the input and tests against
90 /// the expected output ZIR.
91 Transformation: [:0]const u8,
92101 /// Check the main binary output file against an expected set of bytes.
93102 /// This is most useful with, for example, `-ofmt=c`.
94103 CompareObjectFile: []const u8,
......@@ -139,15 +148,6 @@ pub const TestContext = struct {
139148
140149 files: std.ArrayList(File),
141150
142 /// Adds a subcase in which the module is updated with `src`, and the
143 /// resulting ZIR is validated against `result`.
144 pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void {
145 self.updates.append(.{
146 .src = src,
147 .case = .{ .Transformation = result },
148 }) catch unreachable;
149 }
150
151151 /// Adds a subcase in which the module is updated with `src`, and a C
152152 /// header is generated.
153153 pub fn addHeader(self: *Case, src: [:0]const u8, result: [:0]const u8) void {
......@@ -182,31 +182,37 @@ pub const TestContext = struct {
182182 /// the form `:line:column: error: message`.
183183 pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void {
184184 var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch unreachable;
185 for (errors) |e, i| {
186 if (e[0] != ':') {
187 array[i] = .{ .plain = .{ .msg = e } };
185 for (errors) |err_msg_line, i| {
186 if (std.mem.startsWith(u8, err_msg_line, "error: ")) {
187 array[i] = .{
188 .plain = .{ .msg = err_msg_line["error: ".len..], .kind = .@"error" },
189 };
190 continue;
191 } else if (std.mem.startsWith(u8, err_msg_line, "note: ")) {
192 array[i] = .{
193 .plain = .{ .msg = err_msg_line["note: ".len..], .kind = .note },
194 };
188195 continue;
189196 }
190 var cur = e[1..];
191 var line_index = std.mem.indexOf(u8, cur, ":");
192 if (line_index == null) {
193 @panic("Invalid test: error must be specified as follows:\n:line:column: error: message\n=========\n");
194 }
195 const line = std.fmt.parseInt(u32, cur[0..line_index.?], 10) catch @panic("Unable to parse line number");
196 cur = cur[line_index.? + 1 ..];
197 const column_index = std.mem.indexOf(u8, cur, ":");
198 if (column_index == null) {
199 @panic("Invalid test: error must be specified as follows:\n:line:column: error: message\n=========\n");
200 }
201 const column = std.fmt.parseInt(u32, cur[0..column_index.?], 10) catch @panic("Unable to parse column number");
202 cur = cur[column_index.? + 2 ..];
203 if (!std.mem.eql(u8, cur[0..7], "error: ")) {
204 @panic("Invalid test: error must be specified as follows:\n:line:column: error: message\n=========\n");
205 }
206 const msg = cur[7..];
197 // example: ":1:2: error: bad thing happened"
198 var it = std.mem.split(err_msg_line, ":");
199 _ = it.next() orelse @panic("missing colon");
200 const line_text = it.next() orelse @panic("missing line");
201 const col_text = it.next() orelse @panic("missing column");
202 const kind_text = it.next() orelse @panic("missing 'error'/'note'");
203 const msg = it.rest()[1..]; // skip over the space at end of "error: "
204
205 const line = std.fmt.parseInt(u32, line_text, 10) catch @panic("bad line number");
206 const column = std.fmt.parseInt(u32, col_text, 10) catch @panic("bad column number");
207 const kind: ErrorMsg.Kind = if (std.mem.eql(u8, kind_text, " error"))
208 .@"error"
209 else if (std.mem.eql(u8, kind_text, " note"))
210 .note
211 else
212 @panic("expected 'error'/'note'");
207213
208214 if (line == 0 or column == 0) {
209 @panic("Invalid test: error line and column must be specified starting at one!");
215 @panic("line and column must be specified starting at one");
210216 }
211217
212218 array[i] = .{
......@@ -214,6 +220,7 @@ pub const TestContext = struct {
214220 .msg = msg,
215221 .line = line - 1,
216222 .column = column - 1,
223 .kind = kind,
217224 },
218225 };
219226 }
......@@ -689,25 +696,20 @@ pub const TestContext = struct {
689696 var all_errors = try comp.getAllErrorsAlloc();
690697 defer all_errors.deinit(allocator);
691698 if (all_errors.list.len != 0) {
692 std.debug.print("\nErrors occurred updating the compilation:\n================\n", .{});
699 std.debug.print("\nErrors occurred updating the compilation:\n{s}\n", .{hr});
693700 for (all_errors.list) |err_msg| {
694701 switch (err_msg) {
695702 .src => |src| {
696 std.debug.print(":{d}:{d}: error: {s}\n================\n", .{
697 src.line + 1, src.column + 1, src.msg,
703 std.debug.print(":{d}:{d}: error: {s}\n{s}\n", .{
704 src.line + 1, src.column + 1, src.msg, hr,
698705 });
699706 },
700707 .plain => |plain| {
701 std.debug.print("error: {s}\n================\n", .{plain.msg});
708 std.debug.print("error: {s}\n{s}\n", .{ plain.msg, hr });
702709 },
703710 }
704711 }
705712 // TODO print generated C code
706 //if (comp.bin_file.cast(link.File.C)) |c_file| {
707 // std.debug.print("Generated C: \n===============\n{s}\n\n===========\n\n", .{
708 // c_file.main.items,
709 // });
710 //}
711713 std.debug.print("Test failed.\n", .{});
712714 std.process.exit(1);
713715 }
......@@ -728,48 +730,74 @@ pub const TestContext = struct {
728730
729731 std.testing.expectEqualStrings(expected_output, out);
730732 },
731 .Transformation => |expected_output| {
732 update_node.setEstimatedTotalItems(5);
733 var emit_node = update_node.start("emit", 0);
734 emit_node.activate();
735 var new_zir_module = try zir.emit(allocator, comp.bin_file.options.module.?);
736 defer new_zir_module.deinit(allocator);
737 emit_node.end();
738
739 var write_node = update_node.start("write", 0);
740 write_node.activate();
741 var out_zir = std.ArrayList(u8).init(allocator);
742 defer out_zir.deinit();
743 try new_zir_module.writeToStream(allocator, out_zir.writer());
744 write_node.end();
745
733 .Error => |case_error_list| {
746734 var test_node = update_node.start("assert", 0);
747735 test_node.activate();
748736 defer test_node.end();
749737
750 std.testing.expectEqualStrings(expected_output, out_zir.items);
751 },
752 .Error => |e| {
753 var test_node = update_node.start("assert", 0);
754 test_node.activate();
755 defer test_node.end();
756 var handled_errors = try arena.alloc(bool, e.len);
757 for (handled_errors) |*handled| {
758 handled.* = false;
738 const handled_errors = try arena.alloc(bool, case_error_list.len);
739 std.mem.set(bool, handled_errors, false);
740
741 var actual_errors = try comp.getAllErrorsAlloc();
742 defer actual_errors.deinit(allocator);
743
744 var any_failed = false;
745 var notes_to_check = std.ArrayList(*const Compilation.AllErrors.Message).init(allocator);
746 defer notes_to_check.deinit();
747
748 for (actual_errors.list) |actual_error| {
749 for (case_error_list) |case_msg, i| {
750 const ex_tag: @TagType(@TypeOf(case_msg)) = case_msg;
751 switch (actual_error) {
752 .src => |actual_msg| {
753 for (actual_msg.notes) |*note| {
754 try notes_to_check.append(note);
755 }
756
757 if (ex_tag != .src) continue;
758
759 if (actual_msg.line == case_msg.src.line and
760 actual_msg.column == case_msg.src.column and
761 std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and
762 case_msg.src.kind == .@"error")
763 {
764 handled_errors[i] = true;
765 break;
766 }
767 },
768 .plain => |plain| {
769 if (ex_tag != .plain) continue;
770
771 if (std.mem.eql(u8, case_msg.plain.msg, plain.msg) and
772 case_msg.plain.kind == .@"error")
773 {
774 handled_errors[i] = true;
775 break;
776 }
777 },
778 }
779 } else {
780 std.debug.print(
781 "\nUnexpected error:\n{s}\n{}\n{s}",
782 .{ hr, ErrorMsg.init(actual_error, .@"error"), hr },
783 );
784 any_failed = true;
785 }
759786 }
760 var all_errors = try comp.getAllErrorsAlloc();
761 defer all_errors.deinit(allocator);
762 for (all_errors.list) |a| {
763 for (e) |ex, i| {
764 const a_tag: @TagType(@TypeOf(a)) = a;
765 const ex_tag: @TagType(@TypeOf(ex)) = ex;
766 switch (a) {
767 .src => |src| {
787 while (notes_to_check.popOrNull()) |note| {
788 for (case_error_list) |case_msg, i| {
789 const ex_tag: @TagType(@TypeOf(case_msg)) = case_msg;
790 switch (note.*) {
791 .src => |actual_msg| {
792 for (actual_msg.notes) |*sub_note| {
793 try notes_to_check.append(sub_note);
794 }
768795 if (ex_tag != .src) continue;
769796
770 if (src.line == ex.src.line and
771 src.column == ex.src.column and
772 std.mem.eql(u8, ex.src.msg, src.msg))
797 if (actual_msg.line == case_msg.src.line and
798 actual_msg.column == case_msg.src.column and
799 std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and
800 case_msg.src.kind == .note)
773801 {
774802 handled_errors[i] = true;
775803 break;
......@@ -778,7 +806,9 @@ pub const TestContext = struct {
778806 .plain => |plain| {
779807 if (ex_tag != .plain) continue;
780808
781 if (std.mem.eql(u8, ex.plain.msg, plain.msg)) {
809 if (std.mem.eql(u8, case_msg.plain.msg, plain.msg) and
810 case_msg.plain.kind == .note)
811 {
782812 handled_errors[i] = true;
783813 break;
784814 }
......@@ -786,23 +816,29 @@ pub const TestContext = struct {
786816 }
787817 } else {
788818 std.debug.print(
789 "{s}\nUnexpected error:\n================\n{}\n================\nTest failed.\n",
790 .{ case.name, ErrorMsg.init(a) },
819 "\nUnexpected note:\n{s}\n{}\n{s}",
820 .{ hr, ErrorMsg.init(note.*, .note), hr },
791821 );
792 std.process.exit(1);
822 any_failed = true;
793823 }
794824 }
795825
796826 for (handled_errors) |handled, i| {
797827 if (!handled) {
798 const er = e[i];
799828 std.debug.print(
800 "{s}\nDid not receive error:\n================\n{}\n================\nTest failed.\n",
801 .{ case.name, er },
829 "\nExpected error not found:\n{s}\n{}\n{s}",
830 .{ hr, case_error_list[i], hr },
802831 );
803 std.process.exit(1);
832 any_failed = true;
804833 }
805834 }
835
836 if (any_failed) {
837 std.debug.print("\nTest case '{s}' failed, update_index={d}.\n", .{
838 case.name, update_index,
839 });
840 std.process.exit(1);
841 }
806842 },
807843 .Execution => |expected_stdout| {
808844 update_node.setEstimatedTotalItems(4);
src/type/Enum.zig+1-1
......@@ -21,7 +21,7 @@ pub const Field = struct {
2121};
2222
2323pub const Zir = struct {
24 body: zir.Module.Body,
24 body: zir.Body,
2525 inst: *zir.Inst,
2626};
2727
src/type/Struct.zig+1-1
......@@ -24,7 +24,7 @@ pub const Field = struct {
2424};
2525
2626pub const Zir = struct {
27 body: zir.Module.Body,
27 body: zir.Body,
2828 inst: *zir.Inst,
2929};
3030
src/type/Union.zig+1-1
......@@ -24,7 +24,7 @@ pub const Field = struct {
2424};
2525
2626pub const Zir = struct {
27 body: zir.Module.Body,
27 body: zir.Body,
2828 inst: *zir.Inst,
2929};
3030
src/zir.zig+27-1583
......@@ -12,17 +12,6 @@ const TypedValue = @import("TypedValue.zig");
1212const ir = @import("ir.zig");
1313const IrModule = @import("Module.zig");
1414
15/// This struct is relevent only for the ZIR Module text format. It is not used for
16/// semantic analysis of Zig source code.
17pub const Decl = struct {
18 name: []const u8,
19
20 /// Hash of slice into the source of the part after the = and before the next instruction.
21 contents_hash: std.zig.SrcHash,
22
23 inst: *Inst,
24};
25
2615/// These are instructions that correspond to the ZIR text format. See `ir.Inst` for
2716/// in-memory, analyzed instructions with types and values.
2817/// We use a table to map these instruction to their respective semantically analyzed
......@@ -141,15 +130,12 @@ pub const Inst = struct {
141130 container_field,
142131 /// Declares the beginning of a statement. Used for debug info.
143132 dbg_stmt,
144 /// Represents a pointer to a global decl by name.
133 /// Represents a pointer to a global decl.
145134 declref,
146135 /// Represents a pointer to a global decl by string name.
147136 declref_str,
148 /// The syntax `@foo` is equivalent to `declval("foo")`.
149 /// declval is equivalent to declref followed by deref.
137 /// Equivalent to a declref followed by deref.
150138 declval,
151 /// Same as declval but the parameter is a `*Module.Decl` rather than a name.
152 declval_in_module,
153139 /// Load the value from a pointer.
154140 deref,
155141 /// Arithmetic division. Asserts no integer overflow.
......@@ -419,7 +405,6 @@ pub const Inst = struct {
419405 .declref => DeclRef,
420406 .declref_str => DeclRefStr,
421407 .declval => DeclVal,
422 .declval_in_module => DeclValInModule,
423408 .coerce_result_block_ptr => CoerceResultBlockPtr,
424409 .compilelog => CompileLog,
425410 .loop => Loop,
......@@ -496,7 +481,6 @@ pub const Inst = struct {
496481 .declref,
497482 .declref_str,
498483 .declval,
499 .declval_in_module,
500484 .deref,
501485 .div,
502486 .elemptr,
......@@ -650,7 +634,7 @@ pub const Inst = struct {
650634 base: Inst,
651635
652636 positionals: struct {
653 body: Module.Body,
637 body: Body,
654638 },
655639 kw_args: struct {},
656640 };
......@@ -705,7 +689,7 @@ pub const Inst = struct {
705689 base: Inst,
706690
707691 positionals: struct {
708 name: []const u8,
692 decl: *IrModule.Decl,
709693 },
710694 kw_args: struct {},
711695 };
......@@ -724,16 +708,6 @@ pub const Inst = struct {
724708 pub const base_tag = Tag.declval;
725709 base: Inst,
726710
727 positionals: struct {
728 name: []const u8,
729 },
730 kw_args: struct {},
731 };
732
733 pub const DeclValInModule = struct {
734 pub const base_tag = Tag.declval_in_module;
735 base: Inst,
736
737711 positionals: struct {
738712 decl: *IrModule.Decl,
739713 },
......@@ -758,10 +732,7 @@ pub const Inst = struct {
758732 positionals: struct {
759733 to_log: []*Inst,
760734 },
761 kw_args: struct {
762 /// If we have seen it already so don't make another error
763 seen: bool = false,
764 },
735 kw_args: struct {},
765736 };
766737
767738 pub const Const = struct {
......@@ -799,7 +770,7 @@ pub const Inst = struct {
799770 base: Inst,
800771
801772 positionals: struct {
802 body: Module.Body,
773 body: Body,
803774 },
804775 kw_args: struct {},
805776 };
......@@ -838,7 +809,7 @@ pub const Inst = struct {
838809
839810 positionals: struct {
840811 fn_type: *Inst,
841 body: Module.Body,
812 body: Body,
842813 },
843814 kw_args: struct {
844815 is_inline: bool = false,
......@@ -998,8 +969,8 @@ pub const Inst = struct {
998969
999970 positionals: struct {
1000971 condition: *Inst,
1001 then_body: Module.Body,
1002 else_body: Module.Body,
972 then_body: Body,
973 else_body: Body,
1003974 },
1004975 kw_args: struct {},
1005976 };
......@@ -1078,7 +1049,7 @@ pub const Inst = struct {
10781049 /// List of all individual items and ranges
10791050 items: []*Inst,
10801051 cases: []Case,
1081 else_body: Module.Body,
1052 else_body: Body,
10821053 },
10831054 kw_args: struct {
10841055 /// Pointer to first range if such exists.
......@@ -1092,7 +1063,7 @@ pub const Inst = struct {
10921063
10931064 pub const Case = struct {
10941065 item: *Inst,
1095 body: Module.Body,
1066 body: Body,
10961067 };
10971068 };
10981069 pub const TypeOfPeer = struct {
......@@ -1192,6 +1163,10 @@ pub const ErrorMsg = struct {
11921163 msg: []const u8,
11931164};
11941165
1166pub const Body = struct {
1167 instructions: []*Inst,
1168};
1169
11951170pub const Module = struct {
11961171 decls: []*Decl,
11971172 arena: std.heap.ArenaAllocator,
......@@ -1199,6 +1174,15 @@ pub const Module = struct {
11991174 metadata: std.AutoHashMap(*Inst, MetaData),
12001175 body_metadata: std.AutoHashMap(*Body, BodyMetaData),
12011176
1177 pub const Decl = struct {
1178 name: []const u8,
1179
1180 /// Hash of slice into the source of the part after the = and before the next instruction.
1181 contents_hash: std.zig.SrcHash,
1182
1183 inst: *Inst,
1184 };
1185
12021186 pub const MetaData = struct {
12031187 deaths: ir.Inst.DeathsInt,
12041188 addr: usize,
......@@ -1208,10 +1192,6 @@ pub const Module = struct {
12081192 deaths: []*Inst,
12091193 };
12101194
1211 pub const Body = struct {
1212 instructions: []*Inst,
1213 };
1214
12151195 pub fn deinit(self: *Module, allocator: *Allocator) void {
12161196 self.metadata.deinit();
12171197 self.body_metadata.deinit();
......@@ -1369,7 +1349,7 @@ const Writer = struct {
13691349 }
13701350 try stream.writeByte(']');
13711351 },
1372 Module.Body => {
1352 Body => {
13731353 try stream.writeAll("{\n");
13741354 if (self.module.body_metadata.get(param_ptr)) |metadata| {
13751355 if (metadata.deaths.len > 0) {
......@@ -1468,8 +1448,6 @@ const Writer = struct {
14681448 try stream.print("@{s}", .{info.name});
14691449 }
14701450 } else if (inst.cast(Inst.DeclVal)) |decl_val| {
1471 try stream.print("@{s}", .{decl_val.positionals.name});
1472 } else if (inst.cast(Inst.DeclValInModule)) |decl_val| {
14731451 try stream.print("@{s}", .{decl_val.positionals.decl.name});
14741452 } else {
14751453 // This should be unreachable in theory, but since ZIR is used for debugging the compiler
......@@ -1479,502 +1457,6 @@ const Writer = struct {
14791457 }
14801458};
14811459
1482pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module {
1483 var global_name_map = std.StringHashMap(*Inst).init(allocator);
1484 defer global_name_map.deinit();
1485
1486 var parser: Parser = .{
1487 .allocator = allocator,
1488 .arena = std.heap.ArenaAllocator.init(allocator),
1489 .i = 0,
1490 .source = source,
1491 .global_name_map = &global_name_map,
1492 .decls = .{},
1493 .unnamed_index = 0,
1494 .block_table = std.StringHashMap(*Inst.Block).init(allocator),
1495 .loop_table = std.StringHashMap(*Inst.Loop).init(allocator),
1496 };
1497 defer parser.block_table.deinit();
1498 defer parser.loop_table.deinit();
1499 errdefer parser.arena.deinit();
1500
1501 parser.parseRoot() catch |err| switch (err) {
1502 error.ParseFailure => {
1503 assert(parser.error_msg != null);
1504 },
1505 else => |e| return e,
1506 };
1507
1508 return Module{
1509 .decls = parser.decls.toOwnedSlice(allocator),
1510 .arena = parser.arena,
1511 .error_msg = parser.error_msg,
1512 .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(allocator),
1513 .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(allocator),
1514 };
1515}
1516
1517const Parser = struct {
1518 allocator: *Allocator,
1519 arena: std.heap.ArenaAllocator,
1520 i: usize,
1521 source: [:0]const u8,
1522 decls: std.ArrayListUnmanaged(*Decl),
1523 global_name_map: *std.StringHashMap(*Inst),
1524 error_msg: ?ErrorMsg = null,
1525 unnamed_index: usize,
1526 block_table: std.StringHashMap(*Inst.Block),
1527 loop_table: std.StringHashMap(*Inst.Loop),
1528
1529 const Body = struct {
1530 instructions: std.ArrayList(*Inst),
1531 name_map: *std.StringHashMap(*Inst),
1532 };
1533
1534 fn parseBody(self: *Parser, body_ctx: ?*Body) !Module.Body {
1535 var name_map = std.StringHashMap(*Inst).init(self.allocator);
1536 defer name_map.deinit();
1537
1538 var body_context = Body{
1539 .instructions = std.ArrayList(*Inst).init(self.allocator),
1540 .name_map = if (body_ctx) |bctx| bctx.name_map else &name_map,
1541 };
1542 defer body_context.instructions.deinit();
1543
1544 try requireEatBytes(self, "{");
1545 skipSpace(self);
1546
1547 while (true) : (self.i += 1) switch (self.source[self.i]) {
1548 ';' => _ = try skipToAndOver(self, '\n'),
1549 '%' => {
1550 self.i += 1;
1551 const ident = try skipToAndOver(self, ' ');
1552 skipSpace(self);
1553 try requireEatBytes(self, "=");
1554 skipSpace(self);
1555 const decl = try parseInstruction(self, &body_context, ident);
1556 const ident_index = body_context.instructions.items.len;
1557 if (try body_context.name_map.fetchPut(ident, decl.inst)) |_| {
1558 return self.fail("redefinition of identifier '{s}'", .{ident});
1559 }
1560 try body_context.instructions.append(decl.inst);
1561 continue;
1562 },
1563 ' ', '\n' => continue,
1564 '}' => {
1565 self.i += 1;
1566 break;
1567 },
1568 else => |byte| return self.failByte(byte),
1569 };
1570
1571 // Move the instructions to the arena
1572 const instrs = try self.arena.allocator.alloc(*Inst, body_context.instructions.items.len);
1573 mem.copy(*Inst, instrs, body_context.instructions.items);
1574 return Module.Body{ .instructions = instrs };
1575 }
1576
1577 fn parseStringLiteral(self: *Parser) ![]u8 {
1578 const start = self.i;
1579 try self.requireEatBytes("\"");
1580
1581 while (true) : (self.i += 1) switch (self.source[self.i]) {
1582 '"' => {
1583 self.i += 1;
1584 const span = self.source[start..self.i];
1585 var bad_index: usize = undefined;
1586 const parsed = std.zig.parseStringLiteral(&self.arena.allocator, span, &bad_index) catch |err| switch (err) {
1587 error.InvalidCharacter => {
1588 self.i = start + bad_index;
1589 const bad_byte = self.source[self.i];
1590 return self.fail("invalid string literal character: '{c}'\n", .{bad_byte});
1591 },
1592 else => |e| return e,
1593 };
1594 return parsed;
1595 },
1596 '\\' => {
1597 self.i += 1;
1598 continue;
1599 },
1600 0 => return self.failByte(0),
1601 else => continue,
1602 };
1603 }
1604
1605 fn parseIntegerLiteral(self: *Parser) !BigIntConst {
1606 const start = self.i;
1607 if (self.source[self.i] == '-') self.i += 1;
1608 while (true) : (self.i += 1) switch (self.source[self.i]) {
1609 '0'...'9' => continue,
1610 else => break,
1611 };
1612 const number_text = self.source[start..self.i];
1613 const base = 10;
1614 // TODO reuse the same array list for this
1615 const limbs_buffer_len = std.math.big.int.calcSetStringLimbsBufferLen(base, number_text.len);
1616 const limbs_buffer = try self.allocator.alloc(std.math.big.Limb, limbs_buffer_len);
1617 defer self.allocator.free(limbs_buffer);
1618 const limb_len = std.math.big.int.calcSetStringLimbCount(base, number_text.len);
1619 const limbs = try self.arena.allocator.alloc(std.math.big.Limb, limb_len);
1620 var result = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
1621 result.setString(base, number_text, limbs_buffer, self.allocator) catch |err| switch (err) {
1622 error.InvalidCharacter => {
1623 self.i = start;
1624 return self.fail("invalid digit in integer literal", .{});
1625 },
1626 };
1627 return result.toConst();
1628 }
1629
1630 fn parseRoot(self: *Parser) !void {
1631 // The IR format is designed so that it can be tokenized and parsed at the same time.
1632 while (true) {
1633 switch (self.source[self.i]) {
1634 ';' => _ = try skipToAndOver(self, '\n'),
1635 '@' => {
1636 self.i += 1;
1637 const ident = try skipToAndOver(self, ' ');
1638 skipSpace(self);
1639 try requireEatBytes(self, "=");
1640 skipSpace(self);
1641 const decl = try parseInstruction(self, null, ident);
1642 const ident_index = self.decls.items.len;
1643 if (try self.global_name_map.fetchPut(ident, decl.inst)) |_| {
1644 return self.fail("redefinition of identifier '{s}'", .{ident});
1645 }
1646 try self.decls.append(self.allocator, decl);
1647 },
1648 ' ', '\n' => self.i += 1,
1649 0 => break,
1650 else => |byte| return self.fail("unexpected byte: '{c}'", .{byte}),
1651 }
1652 }
1653 }
1654
1655 fn eatByte(self: *Parser, byte: u8) bool {
1656 if (self.source[self.i] != byte) return false;
1657 self.i += 1;
1658 return true;
1659 }
1660
1661 fn skipSpace(self: *Parser) void {
1662 while (self.source[self.i] == ' ' or self.source[self.i] == '\n') {
1663 self.i += 1;
1664 }
1665 }
1666
1667 fn requireEatBytes(self: *Parser, bytes: []const u8) !void {
1668 const start = self.i;
1669 for (bytes) |byte| {
1670 if (self.source[self.i] != byte) {
1671 self.i = start;
1672 return self.fail("expected '{s}'", .{bytes});
1673 }
1674 self.i += 1;
1675 }
1676 }
1677
1678 fn skipToAndOver(self: *Parser, byte: u8) ![]const u8 {
1679 const start_i = self.i;
1680 while (self.source[self.i] != 0) : (self.i += 1) {
1681 if (self.source[self.i] == byte) {
1682 const result = self.source[start_i..self.i];
1683 self.i += 1;
1684 return result;
1685 }
1686 }
1687 return self.fail("unexpected EOF", .{});
1688 }
1689
1690 /// ParseFailure is an internal error code; handled in `parse`.
1691 const InnerError = error{ ParseFailure, OutOfMemory };
1692
1693 fn failByte(self: *Parser, byte: u8) InnerError {
1694 if (byte == 0) {
1695 return self.fail("unexpected EOF", .{});
1696 } else {
1697 return self.fail("unexpected byte: '{c}'", .{byte});
1698 }
1699 }
1700
1701 fn fail(self: *Parser, comptime format: []const u8, args: anytype) InnerError {
1702 @setCold(true);
1703 self.error_msg = ErrorMsg{
1704 .byte_offset = self.i,
1705 .msg = try std.fmt.allocPrint(&self.arena.allocator, format, args),
1706 };
1707 return error.ParseFailure;
1708 }
1709
1710 fn parseInstruction(self: *Parser, body_ctx: ?*Body, name: []const u8) InnerError!*Decl {
1711 const contents_start = self.i;
1712 const fn_name = try skipToAndOver(self, '(');
1713 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
1714 if (mem.eql(u8, field.name, fn_name)) {
1715 const tag = @field(Inst.Tag, field.name);
1716 return parseInstructionGeneric(self, field.name, tag.Type(), tag, body_ctx, name, contents_start);
1717 }
1718 }
1719 return self.fail("unknown instruction '{s}'", .{fn_name});
1720 }
1721
1722 fn parseInstructionGeneric(
1723 self: *Parser,
1724 comptime fn_name: []const u8,
1725 comptime InstType: type,
1726 tag: Inst.Tag,
1727 body_ctx: ?*Body,
1728 inst_name: []const u8,
1729 contents_start: usize,
1730 ) InnerError!*Decl {
1731 const inst_specific = try self.arena.allocator.create(InstType);
1732 inst_specific.base = .{
1733 .src = self.i,
1734 .tag = tag,
1735 };
1736
1737 if (InstType == Inst.Block) {
1738 try self.block_table.put(inst_name, inst_specific);
1739 } else if (InstType == Inst.Loop) {
1740 try self.loop_table.put(inst_name, inst_specific);
1741 }
1742
1743 if (@hasField(InstType, "ty")) {
1744 inst_specific.ty = opt_type orelse {
1745 return self.fail("instruction '" ++ fn_name ++ "' requires type", .{});
1746 };
1747 }
1748
1749 const Positionals = @TypeOf(inst_specific.positionals);
1750 inline for (@typeInfo(Positionals).Struct.fields) |arg_field| {
1751 if (self.source[self.i] == ',') {
1752 self.i += 1;
1753 skipSpace(self);
1754 } else if (self.source[self.i] == ')') {
1755 return self.fail("expected positional parameter '{s}'", .{arg_field.name});
1756 }
1757 @field(inst_specific.positionals, arg_field.name) = try parseParameterGeneric(
1758 self,
1759 arg_field.field_type,
1760 body_ctx,
1761 );
1762 skipSpace(self);
1763 }
1764
1765 const KW_Args = @TypeOf(inst_specific.kw_args);
1766 inst_specific.kw_args = .{}; // assign defaults
1767 skipSpace(self);
1768 while (eatByte(self, ',')) {
1769 skipSpace(self);
1770 const name = try skipToAndOver(self, '=');
1771 inline for (@typeInfo(KW_Args).Struct.fields) |arg_field| {
1772 const field_name = arg_field.name;
1773 if (mem.eql(u8, name, field_name)) {
1774 const NonOptional = switch (@typeInfo(arg_field.field_type)) {
1775 .Optional => |info| info.child,
1776 else => arg_field.field_type,
1777 };
1778 @field(inst_specific.kw_args, field_name) = try parseParameterGeneric(self, NonOptional, body_ctx);
1779 break;
1780 }
1781 } else {
1782 return self.fail("unrecognized keyword parameter: '{s}'", .{name});
1783 }
1784 skipSpace(self);
1785 }
1786 try requireEatBytes(self, ")");
1787
1788 const decl = try self.arena.allocator.create(Decl);
1789 decl.* = .{
1790 .name = inst_name,
1791 .contents_hash = std.zig.hashSrc(self.source[contents_start..self.i]),
1792 .inst = &inst_specific.base,
1793 };
1794
1795 return decl;
1796 }
1797
1798 fn parseParameterGeneric(self: *Parser, comptime T: type, body_ctx: ?*Body) !T {
1799 if (@typeInfo(T) == .Enum) {
1800 const start = self.i;
1801 while (true) : (self.i += 1) switch (self.source[self.i]) {
1802 ' ', '\n', ',', ')' => {
1803 const enum_name = self.source[start..self.i];
1804 return std.meta.stringToEnum(T, enum_name) orelse {
1805 return self.fail("tag '{s}' not a member of enum '{s}'", .{ enum_name, @typeName(T) });
1806 };
1807 },
1808 0 => return self.failByte(0),
1809 else => continue,
1810 };
1811 }
1812 switch (T) {
1813 Module.Body => return parseBody(self, body_ctx),
1814 bool => {
1815 const bool_value = switch (self.source[self.i]) {
1816 '0' => false,
1817 '1' => true,
1818 else => |byte| return self.fail("expected '0' or '1' for boolean value, found {c}", .{byte}),
1819 };
1820 self.i += 1;
1821 return bool_value;
1822 },
1823 []*Inst => {
1824 try requireEatBytes(self, "[");
1825 skipSpace(self);
1826 if (eatByte(self, ']')) return &[0]*Inst{};
1827
1828 var instructions = std.ArrayList(*Inst).init(&self.arena.allocator);
1829 while (true) {
1830 skipSpace(self);
1831 try instructions.append(try parseParameterInst(self, body_ctx));
1832 skipSpace(self);
1833 if (!eatByte(self, ',')) break;
1834 }
1835 try requireEatBytes(self, "]");
1836 return instructions.toOwnedSlice();
1837 },
1838 *Inst => return parseParameterInst(self, body_ctx),
1839 []u8, []const u8 => return self.parseStringLiteral(),
1840 BigIntConst => return self.parseIntegerLiteral(),
1841 usize => {
1842 const big_int = try self.parseIntegerLiteral();
1843 return big_int.to(usize) catch |err| return self.fail("integer literal: {s}", .{@errorName(err)});
1844 },
1845 TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),
1846 *IrModule.Decl => return self.fail("'declval_in_module' is a special instruction; not legal in ZIR text", .{}),
1847 *Inst.Block => {
1848 const name = try self.parseStringLiteral();
1849 return self.block_table.get(name).?;
1850 },
1851 *Inst.Loop => {
1852 const name = try self.parseStringLiteral();
1853 return self.loop_table.get(name).?;
1854 },
1855 [][]const u8 => {
1856 try requireEatBytes(self, "[");
1857 skipSpace(self);
1858 if (eatByte(self, ']')) return &[0][]const u8{};
1859
1860 var strings = std.ArrayList([]const u8).init(&self.arena.allocator);
1861 while (true) {
1862 skipSpace(self);
1863 try strings.append(try self.parseStringLiteral());
1864 skipSpace(self);
1865 if (!eatByte(self, ',')) break;
1866 }
1867 try requireEatBytes(self, "]");
1868 return strings.toOwnedSlice();
1869 },
1870 []Inst.SwitchBr.Case => {
1871 try requireEatBytes(self, "{");
1872 skipSpace(self);
1873 if (eatByte(self, '}')) return &[0]Inst.SwitchBr.Case{};
1874
1875 var cases = std.ArrayList(Inst.SwitchBr.Case).init(&self.arena.allocator);
1876 while (true) {
1877 const cur = try cases.addOne();
1878 skipSpace(self);
1879 cur.item = try self.parseParameterGeneric(*Inst, body_ctx);
1880 skipSpace(self);
1881 try requireEatBytes(self, "=>");
1882 cur.body = try self.parseBody(body_ctx);
1883 skipSpace(self);
1884 if (!eatByte(self, ',')) break;
1885 }
1886 skipSpace(self);
1887 try requireEatBytes(self, "}");
1888 return cases.toOwnedSlice();
1889 },
1890 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
1891 }
1892 return self.fail("TODO parse parameter {s}", .{@typeName(T)});
1893 }
1894
1895 fn parseParameterInst(self: *Parser, body_ctx: ?*Body) !*Inst {
1896 const local_ref = switch (self.source[self.i]) {
1897 '@' => false,
1898 '%' => true,
1899 else => |byte| return self.fail("unexpected byte: '{c}'", .{byte}),
1900 };
1901 const map = if (local_ref)
1902 if (body_ctx) |bc|
1903 bc.name_map
1904 else
1905 return self.fail("referencing a % instruction in global scope", .{})
1906 else
1907 self.global_name_map;
1908
1909 self.i += 1;
1910 const name_start = self.i;
1911 while (true) : (self.i += 1) switch (self.source[self.i]) {
1912 0, ' ', '\n', ',', ')', ']' => break,
1913 else => continue,
1914 };
1915 const ident = self.source[name_start..self.i];
1916 return map.get(ident) orelse {
1917 const bad_name = self.source[name_start - 1 .. self.i];
1918 const src = name_start - 1;
1919 if (local_ref) {
1920 self.i = src;
1921 return self.fail("unrecognized identifier: {s}", .{bad_name});
1922 } else {
1923 const declval = try self.arena.allocator.create(Inst.DeclVal);
1924 declval.* = .{
1925 .base = .{
1926 .src = src,
1927 .tag = Inst.DeclVal.base_tag,
1928 },
1929 .positionals = .{ .name = ident },
1930 .kw_args = .{},
1931 };
1932 return &declval.base;
1933 }
1934 };
1935 }
1936
1937 fn generateName(self: *Parser) ![]u8 {
1938 const result = try std.fmt.allocPrint(&self.arena.allocator, "unnamed${d}", .{self.unnamed_index});
1939 self.unnamed_index += 1;
1940 return result;
1941 }
1942};
1943
1944pub fn emit(allocator: *Allocator, old_module: *IrModule) !Module {
1945 var ctx: EmitZIR = .{
1946 .allocator = allocator,
1947 .decls = .{},
1948 .arena = std.heap.ArenaAllocator.init(allocator),
1949 .old_module = old_module,
1950 .next_auto_name = 0,
1951 .names = std.StringArrayHashMap(void).init(allocator),
1952 .primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator),
1953 .indent = 0,
1954 .block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator),
1955 .loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator),
1956 .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(allocator),
1957 .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(allocator),
1958 };
1959 errdefer ctx.metadata.deinit();
1960 errdefer ctx.body_metadata.deinit();
1961 defer ctx.block_table.deinit();
1962 defer ctx.loop_table.deinit();
1963 defer ctx.decls.deinit(allocator);
1964 defer ctx.names.deinit();
1965 defer ctx.primitive_table.deinit();
1966 errdefer ctx.arena.deinit();
1967
1968 try ctx.emit();
1969
1970 return Module{
1971 .decls = ctx.decls.toOwnedSlice(allocator),
1972 .arena = ctx.arena,
1973 .metadata = ctx.metadata,
1974 .body_metadata = ctx.body_metadata,
1975 };
1976}
1977
19781460/// For debugging purposes, prints a function representation to stderr.
19791461pub fn dumpFn(old_module: IrModule, module_fn: *IrModule.Fn) void {
19801462 const allocator = old_module.gpa;
......@@ -2374,1052 +1856,14 @@ const DumpTzir = struct {
23741856 }
23751857};
23761858
2377const EmitZIR = struct {
2378 allocator: *Allocator,
2379 arena: std.heap.ArenaAllocator,
2380 old_module: *const IrModule,
2381 decls: std.ArrayListUnmanaged(*Decl),
2382 names: std.StringArrayHashMap(void),
2383 next_auto_name: usize,
2384 primitive_table: std.AutoHashMap(Inst.Primitive.Builtin, *Decl),
2385 indent: usize,
2386 block_table: std.AutoHashMap(*ir.Inst.Block, *Inst.Block),
2387 loop_table: std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop),
2388 metadata: std.AutoHashMap(*Inst, Module.MetaData),
2389 body_metadata: std.AutoHashMap(*Module.Body, Module.BodyMetaData),
2390
2391 fn emit(self: *EmitZIR) !void {
2392 // Put all the Decls in a list and sort them by name to avoid nondeterminism introduced
2393 // by the hash table.
2394 var src_decls = std.ArrayList(*IrModule.Decl).init(self.allocator);
2395 defer src_decls.deinit();
2396 try src_decls.ensureCapacity(self.old_module.decl_table.items().len);
2397 try self.decls.ensureCapacity(self.allocator, self.old_module.decl_table.items().len);
2398 try self.names.ensureCapacity(self.old_module.decl_table.items().len);
2399
2400 for (self.old_module.decl_table.items()) |entry| {
2401 const decl = entry.value;
2402 src_decls.appendAssumeCapacity(decl);
2403 self.names.putAssumeCapacityNoClobber(mem.spanZ(decl.name), {});
2404 }
2405 std.sort.sort(*IrModule.Decl, src_decls.items, {}, (struct {
2406 fn lessThan(context: void, a: *IrModule.Decl, b: *IrModule.Decl) bool {
2407 return a.src_index < b.src_index;
2408 }
2409 }).lessThan);
2410
2411 // Emit all the decls.
2412 for (src_decls.items) |ir_decl| {
2413 switch (ir_decl.analysis) {
2414 .unreferenced => continue,
2415
2416 .complete => {},
2417 .codegen_failure => {}, // We still can emit the ZIR.
2418 .codegen_failure_retryable => {}, // We still can emit the ZIR.
2419
2420 .in_progress => unreachable,
2421 .outdated => unreachable,
2422
2423 .sema_failure,
2424 .sema_failure_retryable,
2425 .dependency_failure,
2426 => if (self.old_module.failed_decls.get(ir_decl)) |err_msg| {
2427 const fail_inst = try self.arena.allocator.create(Inst.UnOp);
2428 fail_inst.* = .{
2429 .base = .{
2430 .src = ir_decl.src(),
2431 .tag = .compileerror,
2432 },
2433 .positionals = .{
2434 .operand = blk: {
2435 const msg_str = try self.arena.allocator.dupe(u8, err_msg.msg);
2436
2437 const str_inst = try self.arena.allocator.create(Inst.Str);
2438 str_inst.* = .{
2439 .base = .{
2440 .src = ir_decl.src(),
2441 .tag = Inst.Str.base_tag,
2442 },
2443 .positionals = .{
2444 .bytes = err_msg.msg,
2445 },
2446 .kw_args = .{},
2447 };
2448 break :blk &str_inst.base;
2449 },
2450 },
2451 .kw_args = .{},
2452 };
2453 const decl = try self.arena.allocator.create(Decl);
2454 decl.* = .{
2455 .name = mem.spanZ(ir_decl.name),
2456 .contents_hash = undefined,
2457 .inst = &fail_inst.base,
2458 };
2459 try self.decls.append(self.allocator, decl);
2460 continue;
2461 },
2462 }
2463 if (self.old_module.export_owners.get(ir_decl)) |exports| {
2464 for (exports) |module_export| {
2465 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
2466 const export_inst = try self.arena.allocator.create(Inst.Export);
2467 export_inst.* = .{
2468 .base = .{
2469 .src = module_export.src,
2470 .tag = Inst.Export.base_tag,
2471 },
2472 .positionals = .{
2473 .symbol_name = symbol_name.inst,
2474 .decl_name = mem.spanZ(module_export.exported_decl.name),
2475 },
2476 .kw_args = .{},
2477 };
2478 _ = try self.emitUnnamedDecl(&export_inst.base);
2479 }
2480 }
2481 const new_decl = try self.emitTypedValue(ir_decl.src(), ir_decl.typed_value.most_recent.typed_value);
2482 new_decl.name = try self.arena.allocator.dupe(u8, mem.spanZ(ir_decl.name));
2483 }
2484 }
2485
2486 const ZirBody = struct {
2487 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
2488 instructions: *std.ArrayList(*Inst),
2489 };
2490
2491 fn resolveInst(self: *EmitZIR, new_body: ZirBody, inst: *ir.Inst) !*Inst {
2492 if (inst.cast(ir.Inst.Constant)) |const_inst| {
2493 const new_inst = if (const_inst.val.castTag(.function)) |func_pl| blk: {
2494 const owner_decl = func_pl.data.owner_decl;
2495 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
2496 } else if (const_inst.val.castTag(.decl_ref)) |declref| blk: {
2497 const decl_ref = try self.emitDeclRef(inst.src, declref.data);
2498 try new_body.instructions.append(decl_ref);
2499 break :blk decl_ref;
2500 } else if (const_inst.val.castTag(.variable)) |var_pl| blk: {
2501 const owner_decl = var_pl.data.owner_decl;
2502 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
2503 } else blk: {
2504 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;
2505 };
2506 _ = try new_body.inst_table.put(inst, new_inst);
2507 return new_inst;
2508 } else {
2509 return new_body.inst_table.get(inst).?;
2510 }
2511 }
2512
2513 fn emitDeclVal(self: *EmitZIR, src: usize, decl_name: []const u8) !*Inst {
2514 const declval = try self.arena.allocator.create(Inst.DeclVal);
2515 declval.* = .{
2516 .base = .{
2517 .src = src,
2518 .tag = Inst.DeclVal.base_tag,
2519 },
2520 .positionals = .{ .name = try self.arena.allocator.dupe(u8, decl_name) },
2521 .kw_args = .{},
2522 };
2523 return &declval.base;
2524 }
2525
2526 fn emitComptimeIntVal(self: *EmitZIR, src: usize, val: Value) !*Decl {
2527 const big_int_space = try self.arena.allocator.create(Value.BigIntSpace);
2528 const int_inst = try self.arena.allocator.create(Inst.Int);
2529 int_inst.* = .{
2530 .base = .{
2531 .src = src,
2532 .tag = Inst.Int.base_tag,
2533 },
2534 .positionals = .{
2535 .int = val.toBigInt(big_int_space),
2536 },
2537 .kw_args = .{},
2538 };
2539 return self.emitUnnamedDecl(&int_inst.base);
2540 }
2541
2542 fn emitDeclRef(self: *EmitZIR, src: usize, module_decl: *IrModule.Decl) !*Inst {
2543 const declref_inst = try self.arena.allocator.create(Inst.DeclRef);
2544 declref_inst.* = .{
2545 .base = .{
2546 .src = src,
2547 .tag = Inst.DeclRef.base_tag,
2548 },
2549 .positionals = .{
2550 .name = mem.spanZ(module_decl.name),
2551 },
2552 .kw_args = .{},
2553 };
2554 return &declref_inst.base;
2555 }
2556
2557 fn emitFn(self: *EmitZIR, module_fn: *IrModule.Fn, src: usize, ty: Type) Allocator.Error!*Decl {
2558 var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator);
2559 defer inst_table.deinit();
2560
2561 var instructions = std.ArrayList(*Inst).init(self.allocator);
2562 defer instructions.deinit();
2563
2564 switch (module_fn.state) {
2565 .queued => unreachable,
2566 .in_progress => unreachable,
2567 .inline_only => unreachable,
2568 .success => {
2569 try self.emitBody(module_fn.body, &inst_table, &instructions);
2570 },
2571 .sema_failure => {
2572 const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?;
2573 const fail_inst = try self.arena.allocator.create(Inst.UnOp);
2574 fail_inst.* = .{
2575 .base = .{
2576 .src = src,
2577 .tag = .compileerror,
2578 },
2579 .positionals = .{
2580 .operand = blk: {
2581 const msg_str = try self.arena.allocator.dupe(u8, err_msg.msg);
2582
2583 const str_inst = try self.arena.allocator.create(Inst.Str);
2584 str_inst.* = .{
2585 .base = .{
2586 .src = src,
2587 .tag = Inst.Str.base_tag,
2588 },
2589 .positionals = .{
2590 .bytes = msg_str,
2591 },
2592 .kw_args = .{},
2593 };
2594 break :blk &str_inst.base;
2595 },
2596 },
2597 .kw_args = .{},
2598 };
2599 try instructions.append(&fail_inst.base);
2600 },
2601 .dependency_failure => {
2602 const fail_inst = try self.arena.allocator.create(Inst.UnOp);
2603 fail_inst.* = .{
2604 .base = .{
2605 .src = src,
2606 .tag = .compileerror,
2607 },
2608 .positionals = .{
2609 .operand = blk: {
2610 const msg_str = try self.arena.allocator.dupe(u8, "depends on another failed Decl");
2611
2612 const str_inst = try self.arena.allocator.create(Inst.Str);
2613 str_inst.* = .{
2614 .base = .{
2615 .src = src,
2616 .tag = Inst.Str.base_tag,
2617 },
2618 .positionals = .{
2619 .bytes = msg_str,
2620 },
2621 .kw_args = .{},
2622 };
2623 break :blk &str_inst.base;
2624 },
2625 },
2626 .kw_args = .{},
2627 };
2628 try instructions.append(&fail_inst.base);
2629 },
2630 }
2631
2632 const fn_type = try self.emitType(src, ty);
2633
2634 const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len);
2635 mem.copy(*Inst, arena_instrs, instructions.items);
2636
2637 const fn_inst = try self.arena.allocator.create(Inst.Fn);
2638 fn_inst.* = .{
2639 .base = .{
2640 .src = src,
2641 .tag = Inst.Fn.base_tag,
2642 },
2643 .positionals = .{
2644 .fn_type = fn_type.inst,
2645 .body = .{ .instructions = arena_instrs },
2646 },
2647 .kw_args = .{
2648 .is_inline = module_fn.state == .inline_only,
2649 },
2650 };
2651 return self.emitUnnamedDecl(&fn_inst.base);
2652 }
2653
2654 fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl {
2655 const allocator = &self.arena.allocator;
2656 if (typed_value.val.castTag(.decl_ref)) |decl_ref| {
2657 const decl = decl_ref.data;
2658 return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl));
2659 } else if (typed_value.val.castTag(.variable)) |variable| {
2660 return self.emitTypedValue(src, .{
2661 .ty = typed_value.ty,
2662 .val = variable.data.init,
2663 });
2664 }
2665 if (typed_value.val.isUndef()) {
2666 const as_inst = try self.arena.allocator.create(Inst.BinOp);
2667 as_inst.* = .{
2668 .base = .{
2669 .tag = .as,
2670 .src = src,
2671 },
2672 .positionals = .{
2673 .lhs = (try self.emitType(src, typed_value.ty)).inst,
2674 .rhs = (try self.emitPrimitive(src, .@"undefined")).inst,
2675 },
2676 .kw_args = .{},
2677 };
2678 return self.emitUnnamedDecl(&as_inst.base);
2679 }
2680 switch (typed_value.ty.zigTypeTag()) {
2681 .Pointer => {
2682 const ptr_elem_type = typed_value.ty.elemType();
2683 switch (ptr_elem_type.zigTypeTag()) {
2684 .Array => {
2685 // TODO more checks to make sure this can be emitted as a string literal
2686 //const array_elem_type = ptr_elem_type.elemType();
2687 //if (array_elem_type.eql(Type.initTag(.u8)) and
2688 // ptr_elem_type.hasSentinel(Value.initTag(.zero)))
2689 //{
2690 //}
2691 const bytes = typed_value.val.toAllocatedBytes(allocator) catch |err| switch (err) {
2692 error.AnalysisFail => unreachable,
2693 else => |e| return e,
2694 };
2695 return self.emitStringLiteral(src, bytes);
2696 },
2697 else => |t| std.debug.panic("TODO implement emitTypedValue for pointer to {s}", .{@tagName(t)}),
2698 }
2699 },
2700 .ComptimeInt => return self.emitComptimeIntVal(src, typed_value.val),
2701 .Int => {
2702 const as_inst = try self.arena.allocator.create(Inst.BinOp);
2703 as_inst.* = .{
2704 .base = .{
2705 .tag = .as,
2706 .src = src,
2707 },
2708 .positionals = .{
2709 .lhs = (try self.emitType(src, typed_value.ty)).inst,
2710 .rhs = (try self.emitComptimeIntVal(src, typed_value.val)).inst,
2711 },
2712 .kw_args = .{},
2713 };
2714 return self.emitUnnamedDecl(&as_inst.base);
2715 },
2716 .Type => {
2717 const ty = try typed_value.val.toType(&self.arena.allocator);
2718 return self.emitType(src, ty);
2719 },
2720 .Fn => {
2721 const module_fn = typed_value.val.castTag(.function).?.data;
2722 return self.emitFn(module_fn, src, typed_value.ty);
2723 },
2724 .Array => {
2725 // TODO more checks to make sure this can be emitted as a string literal
2726 //const array_elem_type = ptr_elem_type.elemType();
2727 //if (array_elem_type.eql(Type.initTag(.u8)) and
2728 // ptr_elem_type.hasSentinel(Value.initTag(.zero)))
2729 //{
2730 //}
2731 const bytes = typed_value.val.toAllocatedBytes(allocator) catch |err| switch (err) {
2732 error.AnalysisFail => unreachable,
2733 else => |e| return e,
2734 };
2735 const str_inst = try self.arena.allocator.create(Inst.Str);
2736 str_inst.* = .{
2737 .base = .{
2738 .src = src,
2739 .tag = Inst.Str.base_tag,
2740 },
2741 .positionals = .{
2742 .bytes = bytes,
2743 },
2744 .kw_args = .{},
2745 };
2746 return self.emitUnnamedDecl(&str_inst.base);
2747 },
2748 .Void => return self.emitPrimitive(src, .void_value),
2749 .Bool => if (typed_value.val.toBool())
2750 return self.emitPrimitive(src, .@"true")
2751 else
2752 return self.emitPrimitive(src, .@"false"),
2753 .EnumLiteral => {
2754 const enum_literal = typed_value.val.castTag(.enum_literal).?;
2755 const inst = try self.arena.allocator.create(Inst.Str);
2756 inst.* = .{
2757 .base = .{
2758 .src = src,
2759 .tag = .enum_literal,
2760 },
2761 .positionals = .{
2762 .bytes = enum_literal.data,
2763 },
2764 .kw_args = .{},
2765 };
2766 return self.emitUnnamedDecl(&inst.base);
2767 },
2768 else => |t| std.debug.panic("TODO implement emitTypedValue for {s}", .{@tagName(t)}),
2769 }
2770 }
2771
2772 fn emitNoOp(self: *EmitZIR, src: usize, old_inst: *ir.Inst.NoOp, tag: Inst.Tag) Allocator.Error!*Inst {
2773 const new_inst = try self.arena.allocator.create(Inst.NoOp);
2774 new_inst.* = .{
2775 .base = .{
2776 .src = src,
2777 .tag = tag,
2778 },
2779 .positionals = .{},
2780 .kw_args = .{},
2781 };
2782 return &new_inst.base;
2783 }
2784
2785 fn emitUnOp(
2786 self: *EmitZIR,
2787 src: usize,
2788 new_body: ZirBody,
2789 old_inst: *ir.Inst.UnOp,
2790 tag: Inst.Tag,
2791 ) Allocator.Error!*Inst {
2792 const new_inst = try self.arena.allocator.create(Inst.UnOp);
2793 new_inst.* = .{
2794 .base = .{
2795 .src = src,
2796 .tag = tag,
2797 },
2798 .positionals = .{
2799 .operand = try self.resolveInst(new_body, old_inst.operand),
2800 },
2801 .kw_args = .{},
2802 };
2803 return &new_inst.base;
2804 }
2805
2806 fn emitBinOp(
2807 self: *EmitZIR,
2808 src: usize,
2809 new_body: ZirBody,
2810 old_inst: *ir.Inst.BinOp,
2811 tag: Inst.Tag,
2812 ) Allocator.Error!*Inst {
2813 const new_inst = try self.arena.allocator.create(Inst.BinOp);
2814 new_inst.* = .{
2815 .base = .{
2816 .src = src,
2817 .tag = tag,
2818 },
2819 .positionals = .{
2820 .lhs = try self.resolveInst(new_body, old_inst.lhs),
2821 .rhs = try self.resolveInst(new_body, old_inst.rhs),
2822 },
2823 .kw_args = .{},
2824 };
2825 return &new_inst.base;
2826 }
2827
2828 fn emitCast(
2829 self: *EmitZIR,
2830 src: usize,
2831 new_body: ZirBody,
2832 old_inst: *ir.Inst.UnOp,
2833 tag: Inst.Tag,
2834 ) Allocator.Error!*Inst {
2835 const new_inst = try self.arena.allocator.create(Inst.BinOp);
2836 new_inst.* = .{
2837 .base = .{
2838 .src = src,
2839 .tag = tag,
2840 },
2841 .positionals = .{
2842 .lhs = (try self.emitType(old_inst.base.src, old_inst.base.ty)).inst,
2843 .rhs = try self.resolveInst(new_body, old_inst.operand),
2844 },
2845 .kw_args = .{},
2846 };
2847 return &new_inst.base;
2848 }
2849
2850 fn emitBody(
2851 self: *EmitZIR,
2852 body: ir.Body,
2853 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
2854 instructions: *std.ArrayList(*Inst),
2855 ) Allocator.Error!void {
2856 const new_body = ZirBody{
2857 .inst_table = inst_table,
2858 .instructions = instructions,
2859 };
2860 for (body.instructions) |inst| {
2861 const new_inst = switch (inst.tag) {
2862 .constant => unreachable, // excluded from function bodies
2863
2864 .breakpoint => try self.emitNoOp(inst.src, inst.castTag(.breakpoint).?, .breakpoint),
2865 .unreach => try self.emitNoOp(inst.src, inst.castTag(.unreach).?, .unreach_nocheck),
2866 .retvoid => try self.emitNoOp(inst.src, inst.castTag(.retvoid).?, .returnvoid),
2867 .dbg_stmt => try self.emitNoOp(inst.src, inst.castTag(.dbg_stmt).?, .dbg_stmt),
2868
2869 .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot),
2870 .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"),
2871 .ptrtoint => try self.emitUnOp(inst.src, new_body, inst.castTag(.ptrtoint).?, .ptrtoint),
2872 .isnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnull).?, .isnull),
2873 .isnonnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnonnull).?, .isnonnull),
2874 .iserr => try self.emitUnOp(inst.src, new_body, inst.castTag(.iserr).?, .iserr),
2875 .load => try self.emitUnOp(inst.src, new_body, inst.castTag(.load).?, .deref),
2876 .ref => try self.emitUnOp(inst.src, new_body, inst.castTag(.ref).?, .ref),
2877 .unwrap_optional => try self.emitUnOp(inst.src, new_body, inst.castTag(.unwrap_optional).?, .unwrap_optional_unsafe),
2878 .wrap_optional => try self.emitCast(inst.src, new_body, inst.castTag(.wrap_optional).?, .as),
2879
2880 .add => try self.emitBinOp(inst.src, new_body, inst.castTag(.add).?, .add),
2881 .sub => try self.emitBinOp(inst.src, new_body, inst.castTag(.sub).?, .sub),
2882 .store => try self.emitBinOp(inst.src, new_body, inst.castTag(.store).?, .store),
2883 .cmp_lt => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_lt).?, .cmp_lt),
2884 .cmp_lte => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_lte).?, .cmp_lte),
2885 .cmp_eq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_eq).?, .cmp_eq),
2886 .cmp_gte => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_gte).?, .cmp_gte),
2887 .cmp_gt => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_gt).?, .cmp_gt),
2888 .cmp_neq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_neq).?, .cmp_neq),
2889 .booland => try self.emitBinOp(inst.src, new_body, inst.castTag(.booland).?, .booland),
2890 .boolor => try self.emitBinOp(inst.src, new_body, inst.castTag(.boolor).?, .boolor),
2891 .bitand => try self.emitBinOp(inst.src, new_body, inst.castTag(.bitand).?, .bitand),
2892 .bitor => try self.emitBinOp(inst.src, new_body, inst.castTag(.bitor).?, .bitor),
2893 .xor => try self.emitBinOp(inst.src, new_body, inst.castTag(.xor).?, .xor),
2894
2895 .bitcast => try self.emitCast(inst.src, new_body, inst.castTag(.bitcast).?, .bitcast),
2896 .intcast => try self.emitCast(inst.src, new_body, inst.castTag(.intcast).?, .intcast),
2897 .floatcast => try self.emitCast(inst.src, new_body, inst.castTag(.floatcast).?, .floatcast),
2898
2899 .alloc => blk: {
2900 const new_inst = try self.arena.allocator.create(Inst.UnOp);
2901 new_inst.* = .{
2902 .base = .{
2903 .src = inst.src,
2904 .tag = .alloc,
2905 },
2906 .positionals = .{
2907 .operand = (try self.emitType(inst.src, inst.ty)).inst,
2908 },
2909 .kw_args = .{},
2910 };
2911 break :blk &new_inst.base;
2912 },
2913
2914 .arg => blk: {
2915 const old_inst = inst.castTag(.arg).?;
2916 const new_inst = try self.arena.allocator.create(Inst.Arg);
2917 new_inst.* = .{
2918 .base = .{
2919 .src = inst.src,
2920 .tag = .arg,
2921 },
2922 .positionals = .{
2923 .name = try self.arena.allocator.dupe(u8, mem.spanZ(old_inst.name)),
2924 },
2925 .kw_args = .{},
2926 };
2927 break :blk &new_inst.base;
2928 },
2929
2930 .block => blk: {
2931 const old_inst = inst.castTag(.block).?;
2932 const new_inst = try self.arena.allocator.create(Inst.Block);
2933
2934 try self.block_table.put(old_inst, new_inst);
2935
2936 var block_body = std.ArrayList(*Inst).init(self.allocator);
2937 defer block_body.deinit();
2938
2939 try self.emitBody(old_inst.body, inst_table, &block_body);
2940
2941 new_inst.* = .{
2942 .base = .{
2943 .src = inst.src,
2944 .tag = Inst.Block.base_tag,
2945 },
2946 .positionals = .{
2947 .body = .{ .instructions = block_body.toOwnedSlice() },
2948 },
2949 .kw_args = .{},
2950 };
2951
2952 break :blk &new_inst.base;
2953 },
2954
2955 .loop => blk: {
2956 const old_inst = inst.castTag(.loop).?;
2957 const new_inst = try self.arena.allocator.create(Inst.Loop);
2958
2959 try self.loop_table.put(old_inst, new_inst);
2960
2961 var loop_body = std.ArrayList(*Inst).init(self.allocator);
2962 defer loop_body.deinit();
2963
2964 try self.emitBody(old_inst.body, inst_table, &loop_body);
2965
2966 new_inst.* = .{
2967 .base = .{
2968 .src = inst.src,
2969 .tag = Inst.Loop.base_tag,
2970 },
2971 .positionals = .{
2972 .body = .{ .instructions = loop_body.toOwnedSlice() },
2973 },
2974 .kw_args = .{},
2975 };
2976
2977 break :blk &new_inst.base;
2978 },
2979
2980 .brvoid => blk: {
2981 const old_inst = inst.cast(ir.Inst.BrVoid).?;
2982 const new_block = self.block_table.get(old_inst.block).?;
2983 const new_inst = try self.arena.allocator.create(Inst.BreakVoid);
2984 new_inst.* = .{
2985 .base = .{
2986 .src = inst.src,
2987 .tag = Inst.BreakVoid.base_tag,
2988 },
2989 .positionals = .{
2990 .block = new_block,
2991 },
2992 .kw_args = .{},
2993 };
2994 break :blk &new_inst.base;
2995 },
2996
2997 .br => blk: {
2998 const old_inst = inst.castTag(.br).?;
2999 const new_block = self.block_table.get(old_inst.block).?;
3000 const new_inst = try self.arena.allocator.create(Inst.Break);
3001 new_inst.* = .{
3002 .base = .{
3003 .src = inst.src,
3004 .tag = Inst.Break.base_tag,
3005 },
3006 .positionals = .{
3007 .block = new_block,
3008 .operand = try self.resolveInst(new_body, old_inst.operand),
3009 },
3010 .kw_args = .{},
3011 };
3012 break :blk &new_inst.base;
3013 },
3014
3015 .call => blk: {
3016 const old_inst = inst.castTag(.call).?;
3017 const new_inst = try self.arena.allocator.create(Inst.Call);
3018
3019 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.len);
3020 for (args) |*elem, i| {
3021 elem.* = try self.resolveInst(new_body, old_inst.args[i]);
3022 }
3023 new_inst.* = .{
3024 .base = .{
3025 .src = inst.src,
3026 .tag = Inst.Call.base_tag,
3027 },
3028 .positionals = .{
3029 .func = try self.resolveInst(new_body, old_inst.func),
3030 .args = args,
3031 },
3032 .kw_args = .{},
3033 };
3034 break :blk &new_inst.base;
3035 },
3036
3037 .assembly => blk: {
3038 const old_inst = inst.castTag(.assembly).?;
3039 const new_inst = try self.arena.allocator.create(Inst.Asm);
3040
3041 const inputs = try self.arena.allocator.alloc(*Inst, old_inst.inputs.len);
3042 for (inputs) |*elem, i| {
3043 elem.* = (try self.emitStringLiteral(inst.src, old_inst.inputs[i])).inst;
3044 }
3045
3046 const clobbers = try self.arena.allocator.alloc(*Inst, old_inst.clobbers.len);
3047 for (clobbers) |*elem, i| {
3048 elem.* = (try self.emitStringLiteral(inst.src, old_inst.clobbers[i])).inst;
3049 }
3050
3051 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.len);
3052 for (args) |*elem, i| {
3053 elem.* = try self.resolveInst(new_body, old_inst.args[i]);
3054 }
3055
3056 new_inst.* = .{
3057 .base = .{
3058 .src = inst.src,
3059 .tag = Inst.Asm.base_tag,
3060 },
3061 .positionals = .{
3062 .asm_source = (try self.emitStringLiteral(inst.src, old_inst.asm_source)).inst,
3063 .return_type = (try self.emitType(inst.src, inst.ty)).inst,
3064 },
3065 .kw_args = .{
3066 .@"volatile" = old_inst.is_volatile,
3067 .output = if (old_inst.output) |o|
3068 (try self.emitStringLiteral(inst.src, o)).inst
3069 else
3070 null,
3071 .inputs = inputs,
3072 .clobbers = clobbers,
3073 .args = args,
3074 },
3075 };
3076 break :blk &new_inst.base;
3077 },
3078
3079 .condbr => blk: {
3080 const old_inst = inst.castTag(.condbr).?;
3081
3082 var then_body = std.ArrayList(*Inst).init(self.allocator);
3083 var else_body = std.ArrayList(*Inst).init(self.allocator);
3084
3085 defer then_body.deinit();
3086 defer else_body.deinit();
3087
3088 const then_deaths = try self.arena.allocator.alloc(*Inst, old_inst.thenDeaths().len);
3089 const else_deaths = try self.arena.allocator.alloc(*Inst, old_inst.elseDeaths().len);
3090
3091 for (old_inst.thenDeaths()) |death, i| {
3092 then_deaths[i] = try self.resolveInst(new_body, death);
3093 }
3094 for (old_inst.elseDeaths()) |death, i| {
3095 else_deaths[i] = try self.resolveInst(new_body, death);
3096 }
3097
3098 try self.emitBody(old_inst.then_body, inst_table, &then_body);
3099 try self.emitBody(old_inst.else_body, inst_table, &else_body);
3100
3101 const new_inst = try self.arena.allocator.create(Inst.CondBr);
3102
3103 try self.body_metadata.put(&new_inst.positionals.then_body, .{ .deaths = then_deaths });
3104 try self.body_metadata.put(&new_inst.positionals.else_body, .{ .deaths = else_deaths });
3105
3106 new_inst.* = .{
3107 .base = .{
3108 .src = inst.src,
3109 .tag = Inst.CondBr.base_tag,
3110 },
3111 .positionals = .{
3112 .condition = try self.resolveInst(new_body, old_inst.condition),
3113 .then_body = .{ .instructions = then_body.toOwnedSlice() },
3114 .else_body = .{ .instructions = else_body.toOwnedSlice() },
3115 },
3116 .kw_args = .{},
3117 };
3118 break :blk &new_inst.base;
3119 },
3120 .switchbr => blk: {
3121 const old_inst = inst.castTag(.switchbr).?;
3122 const cases = try self.arena.allocator.alloc(Inst.SwitchBr.Case, old_inst.cases.len);
3123 const new_inst = try self.arena.allocator.create(Inst.SwitchBr);
3124 new_inst.* = .{
3125 .base = .{
3126 .src = inst.src,
3127 .tag = Inst.SwitchBr.base_tag,
3128 },
3129 .positionals = .{
3130 .target_ptr = try self.resolveInst(new_body, old_inst.target_ptr),
3131 .cases = cases,
3132 .items = &[_]*Inst{}, // TODO this should actually be populated
3133 .else_body = undefined, // populated below
3134 },
3135 .kw_args = .{},
3136 };
3137
3138 var body_tmp = std.ArrayList(*Inst).init(self.allocator);
3139 defer body_tmp.deinit();
3140
3141 for (old_inst.cases) |*case, i| {
3142 body_tmp.items.len = 0;
3143
3144 const case_deaths = try self.arena.allocator.alloc(*Inst, old_inst.caseDeaths(i).len);
3145 for (old_inst.caseDeaths(i)) |death, j| {
3146 case_deaths[j] = try self.resolveInst(new_body, death);
3147 }
3148 try self.body_metadata.put(&cases[i].body, .{ .deaths = case_deaths });
3149
3150 try self.emitBody(case.body, inst_table, &body_tmp);
3151 const item = (try self.emitTypedValue(inst.src, .{
3152 .ty = old_inst.target_ptr.ty.elemType(),
3153 .val = case.item,
3154 })).inst;
3155
3156 cases[i] = .{
3157 .item = item,
3158 .body = .{ .instructions = try self.arena.allocator.dupe(*Inst, body_tmp.items) },
3159 };
3160 }
3161 { // else
3162 const else_deaths = try self.arena.allocator.alloc(*Inst, old_inst.elseDeaths().len);
3163 for (old_inst.elseDeaths()) |death, j| {
3164 else_deaths[j] = try self.resolveInst(new_body, death);
3165 }
3166 try self.body_metadata.put(&new_inst.positionals.else_body, .{ .deaths = else_deaths });
3167
3168 body_tmp.items.len = 0;
3169 try self.emitBody(old_inst.else_body, inst_table, &body_tmp);
3170 new_inst.positionals.else_body = .{
3171 .instructions = try self.arena.allocator.dupe(*Inst, body_tmp.items),
3172 };
3173 }
3174
3175 break :blk &new_inst.base;
3176 },
3177 .varptr => @panic("TODO"),
3178 };
3179 try self.metadata.put(new_inst, .{
3180 .deaths = inst.deaths,
3181 .addr = @ptrToInt(inst),
3182 });
3183 try instructions.append(new_inst);
3184 try inst_table.put(inst, new_inst);
3185 }
3186 }
3187
3188 fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Decl {
3189 switch (ty.tag()) {
3190 .i8 => return self.emitPrimitive(src, .i8),
3191 .u8 => return self.emitPrimitive(src, .u8),
3192 .i16 => return self.emitPrimitive(src, .i16),
3193 .u16 => return self.emitPrimitive(src, .u16),
3194 .i32 => return self.emitPrimitive(src, .i32),
3195 .u32 => return self.emitPrimitive(src, .u32),
3196 .i64 => return self.emitPrimitive(src, .i64),
3197 .u64 => return self.emitPrimitive(src, .u64),
3198 .isize => return self.emitPrimitive(src, .isize),
3199 .usize => return self.emitPrimitive(src, .usize),
3200 .c_short => return self.emitPrimitive(src, .c_short),
3201 .c_ushort => return self.emitPrimitive(src, .c_ushort),
3202 .c_int => return self.emitPrimitive(src, .c_int),
3203 .c_uint => return self.emitPrimitive(src, .c_uint),
3204 .c_long => return self.emitPrimitive(src, .c_long),
3205 .c_ulong => return self.emitPrimitive(src, .c_ulong),
3206 .c_longlong => return self.emitPrimitive(src, .c_longlong),
3207 .c_ulonglong => return self.emitPrimitive(src, .c_ulonglong),
3208 .c_longdouble => return self.emitPrimitive(src, .c_longdouble),
3209 .c_void => return self.emitPrimitive(src, .c_void),
3210 .f16 => return self.emitPrimitive(src, .f16),
3211 .f32 => return self.emitPrimitive(src, .f32),
3212 .f64 => return self.emitPrimitive(src, .f64),
3213 .f128 => return self.emitPrimitive(src, .f128),
3214 .anyerror => return self.emitPrimitive(src, .anyerror),
3215 else => switch (ty.zigTypeTag()) {
3216 .Bool => return self.emitPrimitive(src, .bool),
3217 .Void => return self.emitPrimitive(src, .void),
3218 .NoReturn => return self.emitPrimitive(src, .noreturn),
3219 .Type => return self.emitPrimitive(src, .type),
3220 .ComptimeInt => return self.emitPrimitive(src, .comptime_int),
3221 .ComptimeFloat => return self.emitPrimitive(src, .comptime_float),
3222 .Fn => {
3223 const param_types = try self.allocator.alloc(Type, ty.fnParamLen());
3224 defer self.allocator.free(param_types);
3225
3226 ty.fnParamTypes(param_types);
3227 const emitted_params = try self.arena.allocator.alloc(*Inst, param_types.len);
3228 for (param_types) |param_type, i| {
3229 emitted_params[i] = (try self.emitType(src, param_type)).inst;
3230 }
3231
3232 const fntype_inst = try self.arena.allocator.create(Inst.FnType);
3233 fntype_inst.* = .{
3234 .base = .{
3235 .src = src,
3236 .tag = Inst.FnType.base_tag,
3237 },
3238 .positionals = .{
3239 .param_types = emitted_params,
3240 .return_type = (try self.emitType(src, ty.fnReturnType())).inst,
3241 },
3242 .kw_args = .{
3243 .cc = ty.fnCallingConvention(),
3244 },
3245 };
3246 return self.emitUnnamedDecl(&fntype_inst.base);
3247 },
3248 .Int => {
3249 const info = ty.intInfo(self.old_module.getTarget());
3250 const signed = try self.emitPrimitive(src, switch (info.signedness) {
3251 .signed => .@"true",
3252 .unsigned => .@"false",
3253 });
3254 const bits_val = try Value.Tag.int_u64.create(&self.arena.allocator, info.bits);
3255 const bits = try self.emitComptimeIntVal(src, bits_val);
3256 const inttype_inst = try self.arena.allocator.create(Inst.IntType);
3257 inttype_inst.* = .{
3258 .base = .{
3259 .src = src,
3260 .tag = Inst.IntType.base_tag,
3261 },
3262 .positionals = .{
3263 .signed = signed.inst,
3264 .bits = bits.inst,
3265 },
3266 .kw_args = .{},
3267 };
3268 return self.emitUnnamedDecl(&inttype_inst.base);
3269 },
3270 .Pointer => {
3271 if (ty.isSinglePointer()) {
3272 const inst = try self.arena.allocator.create(Inst.UnOp);
3273 const tag: Inst.Tag = if (ty.isConstPtr()) .single_const_ptr_type else .single_mut_ptr_type;
3274 inst.* = .{
3275 .base = .{
3276 .src = src,
3277 .tag = tag,
3278 },
3279 .positionals = .{
3280 .operand = (try self.emitType(src, ty.elemType())).inst,
3281 },
3282 .kw_args = .{},
3283 };
3284 return self.emitUnnamedDecl(&inst.base);
3285 } else {
3286 std.debug.panic("TODO implement emitType for {}", .{ty});
3287 }
3288 },
3289 .Optional => {
3290 var buf: Type.Payload.ElemType = undefined;
3291 const inst = try self.arena.allocator.create(Inst.UnOp);
3292 inst.* = .{
3293 .base = .{
3294 .src = src,
3295 .tag = .optional_type,
3296 },
3297 .positionals = .{
3298 .operand = (try self.emitType(src, ty.optionalChild(&buf))).inst,
3299 },
3300 .kw_args = .{},
3301 };
3302 return self.emitUnnamedDecl(&inst.base);
3303 },
3304 .Array => {
3305 var len_pl = Value.Payload.U64{
3306 .base = .{ .tag = .int_u64 },
3307 .data = ty.arrayLen(),
3308 };
3309 const len = Value.initPayload(&len_pl.base);
3310
3311 const inst = if (ty.sentinel()) |sentinel| blk: {
3312 const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel);
3313 inst.* = .{
3314 .base = .{
3315 .src = src,
3316 .tag = .array_type,
3317 },
3318 .positionals = .{
3319 .len = (try self.emitTypedValue(src, .{
3320 .ty = Type.initTag(.usize),
3321 .val = len,
3322 })).inst,
3323 .sentinel = (try self.emitTypedValue(src, .{
3324 .ty = ty.elemType(),
3325 .val = sentinel,
3326 })).inst,
3327 .elem_type = (try self.emitType(src, ty.elemType())).inst,
3328 },
3329 .kw_args = .{},
3330 };
3331 break :blk &inst.base;
3332 } else blk: {
3333 const inst = try self.arena.allocator.create(Inst.BinOp);
3334 inst.* = .{
3335 .base = .{
3336 .src = src,
3337 .tag = .array_type,
3338 },
3339 .positionals = .{
3340 .lhs = (try self.emitTypedValue(src, .{
3341 .ty = Type.initTag(.usize),
3342 .val = len,
3343 })).inst,
3344 .rhs = (try self.emitType(src, ty.elemType())).inst,
3345 },
3346 .kw_args = .{},
3347 };
3348 break :blk &inst.base;
3349 };
3350 return self.emitUnnamedDecl(inst);
3351 },
3352 else => std.debug.panic("TODO implement emitType for {}", .{ty}),
3353 },
3354 }
3355 }
3356
3357 fn autoName(self: *EmitZIR) ![]u8 {
3358 while (true) {
3359 const proposed_name = try std.fmt.allocPrint(&self.arena.allocator, "unnamed${d}", .{self.next_auto_name});
3360 self.next_auto_name += 1;
3361 const gop = try self.names.getOrPut(proposed_name);
3362 if (!gop.found_existing) {
3363 gop.entry.value = {};
3364 return proposed_name;
3365 }
3366 }
3367 }
3368
3369 fn emitPrimitive(self: *EmitZIR, src: usize, tag: Inst.Primitive.Builtin) !*Decl {
3370 const gop = try self.primitive_table.getOrPut(tag);
3371 if (!gop.found_existing) {
3372 const primitive_inst = try self.arena.allocator.create(Inst.Primitive);
3373 primitive_inst.* = .{
3374 .base = .{
3375 .src = src,
3376 .tag = Inst.Primitive.base_tag,
3377 },
3378 .positionals = .{
3379 .tag = tag,
3380 },
3381 .kw_args = .{},
3382 };
3383 gop.entry.value = try self.emitUnnamedDecl(&primitive_inst.base);
3384 }
3385 return gop.entry.value;
3386 }
3387
3388 fn emitStringLiteral(self: *EmitZIR, src: usize, str: []const u8) !*Decl {
3389 const str_inst = try self.arena.allocator.create(Inst.Str);
3390 str_inst.* = .{
3391 .base = .{
3392 .src = src,
3393 .tag = Inst.Str.base_tag,
3394 },
3395 .positionals = .{
3396 .bytes = str,
3397 },
3398 .kw_args = .{},
3399 };
3400 return self.emitUnnamedDecl(&str_inst.base);
3401 }
3402
3403 fn emitUnnamedDecl(self: *EmitZIR, inst: *Inst) !*Decl {
3404 const decl = try self.arena.allocator.create(Decl);
3405 decl.* = .{
3406 .name = try self.autoName(),
3407 .contents_hash = undefined,
3408 .inst = inst,
3409 };
3410 try self.decls.append(self.allocator, decl);
3411 return decl;
3412 }
3413};
3414
34151859/// For debugging purposes, like dumpFn but for unanalyzed zir blocks
34161860pub fn dumpZir(allocator: *Allocator, kind: []const u8, decl_name: [*:0]const u8, instructions: []*Inst) !void {
34171861 var fib = std.heap.FixedBufferAllocator.init(&[_]u8{});
34181862 var module = Module{
3419 .decls = &[_]*Decl{},
1863 .decls = &[_]*Module.Decl{},
34201864 .arena = std.heap.ArenaAllocator.init(&fib.allocator),
34211865 .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(&fib.allocator),
3422 .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(&fib.allocator),
1866 .body_metadata = std.AutoHashMap(*Body, Module.BodyMetaData).init(&fib.allocator),
34231867 };
34241868 var write = Writer{
34251869 .module = &module,
src/zir_sema.zig+47-132
......@@ -63,7 +63,6 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
6363 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),
6464 .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?),
6565 .declval => return analyzeInstDeclVal(mod, scope, old_inst.castTag(.declval).?),
66 .declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?),
6766 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
6867 .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),
6968 .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?),
......@@ -166,7 +165,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
166165 }
167166}
168167
169pub fn analyzeBody(mod: *Module, block: *Scope.Block, body: zir.Module.Body) !void {
168pub fn analyzeBody(mod: *Module, block: *Scope.Block, body: zir.Body) !void {
170169 const tracy = trace(@src());
171170 defer tracy.end();
172171
......@@ -183,7 +182,7 @@ pub fn analyzeBodyValueAsType(
183182 mod: *Module,
184183 block_scope: *Scope.Block,
185184 zir_result_inst: *zir.Inst,
186 body: zir.Module.Body,
185 body: zir.Body,
187186) !Type {
188187 try analyzeBody(mod, block_scope, body);
189188 const result_inst = block_scope.inst_table.get(zir_result_inst).?;
......@@ -191,84 +190,6 @@ pub fn analyzeBodyValueAsType(
191190 return val.toType(block_scope.base.arena());
192191}
193192
194pub fn analyzeZirDecl(mod: *Module, decl: *Decl, src_decl: *zir.Decl) InnerError!bool {
195 var decl_scope: Scope.DeclAnalysis = .{
196 .decl = decl,
197 .arena = std.heap.ArenaAllocator.init(mod.gpa),
198 };
199 errdefer decl_scope.arena.deinit();
200
201 decl.analysis = .in_progress;
202
203 const typed_value = try analyzeConstInst(mod, &decl_scope.base, src_decl.inst);
204 const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
205
206 var prev_type_has_bits = false;
207 var type_changed = true;
208
209 if (decl.typedValueManaged()) |tvm| {
210 prev_type_has_bits = tvm.typed_value.ty.hasCodeGenBits();
211 type_changed = !tvm.typed_value.ty.eql(typed_value.ty);
212
213 tvm.deinit(mod.gpa);
214 }
215
216 arena_state.* = decl_scope.arena.state;
217 decl.typed_value = .{
218 .most_recent = .{
219 .typed_value = typed_value,
220 .arena = arena_state,
221 },
222 };
223 decl.analysis = .complete;
224 decl.generation = mod.generation;
225 if (typed_value.ty.hasCodeGenBits()) {
226 // We don't fully codegen the decl until later, but we do need to reserve a global
227 // offset table index for it. This allows us to codegen decls out of dependency order,
228 // increasing how many computations can be done in parallel.
229 try mod.comp.bin_file.allocateDeclIndexes(decl);
230 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
231 } else if (prev_type_has_bits) {
232 mod.comp.bin_file.freeDecl(decl);
233 }
234
235 return type_changed;
236}
237
238pub fn resolveZirDecl(mod: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
239 const zir_module = mod.root_scope.cast(Scope.ZIRModule).?;
240 const entry = zir_module.contents.module.findDecl(src_decl.name).?;
241 return resolveZirDeclHavingIndex(mod, scope, src_decl, entry.index);
242}
243
244fn resolveZirDeclHavingIndex(mod: *Module, scope: *Scope, src_decl: *zir.Decl, src_index: usize) InnerError!*Decl {
245 const name_hash = scope.namespace().fullyQualifiedNameHash(src_decl.name);
246 const decl = mod.decl_table.get(name_hash).?;
247 decl.src_index = src_index;
248 try mod.ensureDeclAnalyzed(decl);
249 return decl;
250}
251
252/// Declares a dependency on the decl.
253fn resolveCompleteZirDecl(mod: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
254 const decl = try resolveZirDecl(mod, scope, src_decl);
255 switch (decl.analysis) {
256 .unreferenced => unreachable,
257 .in_progress => unreachable,
258 .outdated => unreachable,
259
260 .dependency_failure,
261 .sema_failure,
262 .sema_failure_retryable,
263 .codegen_failure,
264 .codegen_failure_retryable,
265 => return error.AnalysisFail,
266
267 .complete => {},
268 }
269 return decl;
270}
271
272193pub fn resolveInst(mod: *Module, scope: *Scope, zir_inst: *zir.Inst) InnerError!*Inst {
273194 const block = scope.cast(Scope.Block).?;
274195 return block.inst_table.get(zir_inst).?; // Instruction does not dominate all uses!
......@@ -640,22 +561,28 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
640561}
641562
642563fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst {
643 std.debug.print("| ", .{});
644 for (inst.positionals.to_log) |item, i| {
645 const to_log = try resolveInst(mod, scope, item);
646 if (to_log.value()) |val| {
647 std.debug.print("{}", .{val});
564 var managed = mod.compile_log_text.toManaged(mod.gpa);
565 defer mod.compile_log_text = managed.moveToUnmanaged();
566 const writer = managed.writer();
567
568 for (inst.positionals.to_log) |arg_inst, i| {
569 if (i != 0) try writer.print(", ", .{});
570
571 const arg = try resolveInst(mod, scope, arg_inst);
572 if (arg.value()) |val| {
573 try writer.print("@as({}, {})", .{ arg.ty, val });
648574 } else {
649 std.debug.print("(runtime value)", .{});
575 try writer.print("@as({}, [runtime value])", .{arg.ty});
650576 }
651 if (i != inst.positionals.to_log.len - 1) std.debug.print(", ", .{});
652577 }
653 std.debug.print("\n", .{});
654 if (!inst.kw_args.seen) {
578 try writer.print("\n", .{});
655579
656 // so that we do not give multiple compile errors if it gets evaled twice
657 inst.kw_args.seen = true;
658 try mod.failCompileLog(scope, inst.base.src);
580 const gop = try mod.compile_log_decls.getOrPut(mod.gpa, scope.ownerDecl().?);
581 if (!gop.found_existing) {
582 gop.entry.value = .{
583 .file_scope = scope.getFileScope(),
584 .byte_offset = inst.base.src,
585 };
659586 }
660587 return mod.constVoid(scope, inst.base.src);
661588}
......@@ -705,7 +632,8 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError
705632 .parent = parent_block,
706633 .inst_table = parent_block.inst_table,
707634 .func = parent_block.func,
708 .decl = parent_block.decl,
635 .owner_decl = parent_block.owner_decl,
636 .src_decl = parent_block.src_decl,
709637 .instructions = .{},
710638 .arena = parent_block.arena,
711639 .inlining = parent_block.inlining,
......@@ -732,7 +660,8 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c
732660 .parent = parent_block,
733661 .inst_table = parent_block.inst_table,
734662 .func = parent_block.func,
735 .decl = parent_block.decl,
663 .owner_decl = parent_block.owner_decl,
664 .src_decl = parent_block.src_decl,
736665 .instructions = .{},
737666 .arena = parent_block.arena,
738667 .label = null,
......@@ -744,13 +673,14 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c
744673
745674 try analyzeBody(mod, &child_block, inst.positionals.body);
746675
747 try parent_block.instructions.appendSlice(mod.gpa, child_block.instructions.items);
748
749 // comptime blocks won't generate any runtime values
750 if (child_block.instructions.items.len == 0)
751 return mod.constVoid(scope, inst.base.src);
676 // Move the analyzed instructions into the parent block arena.
677 const copied_instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items);
678 try parent_block.instructions.appendSlice(mod.gpa, copied_instructions);
752679
753 return parent_block.instructions.items[parent_block.instructions.items.len - 1];
680 // The result of a flat block is the last instruction.
681 const zir_inst_list = inst.positionals.body.instructions;
682 const last_zir_inst = zir_inst_list[zir_inst_list.len - 1];
683 return resolveInst(mod, scope, last_zir_inst);
754684}
755685
756686fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_comptime: bool) InnerError!*Inst {
......@@ -775,7 +705,8 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt
775705 .parent = parent_block,
776706 .inst_table = parent_block.inst_table,
777707 .func = parent_block.func,
778 .decl = parent_block.decl,
708 .owner_decl = parent_block.owner_decl,
709 .src_decl = parent_block.src_decl,
779710 .instructions = .{},
780711 .arena = parent_block.arena,
781712 // TODO @as here is working around a stage1 miscompilation bug :(
......@@ -890,22 +821,15 @@ fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr
890821fn analyzeInstDeclRef(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) InnerError!*Inst {
891822 const tracy = trace(@src());
892823 defer tracy.end();
893 return mod.analyzeDeclRefByName(scope, inst.base.src, inst.positionals.name);
824 return mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);
894825}
895826
896827fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Inst {
897828 const tracy = trace(@src());
898829 defer tracy.end();
899 const decl = try analyzeDeclVal(mod, scope, inst);
900 const ptr = try mod.analyzeDeclRef(scope, inst.base.src, decl);
901 return mod.analyzeDeref(scope, inst.base.src, ptr, inst.base.src);
902}
903
904fn analyzeInstDeclValInModule(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst {
905 const tracy = trace(@src());
906 defer tracy.end();
907 const decl = inst.positionals.decl;
908 return mod.analyzeDeclRef(scope, inst.base.src, decl);
830 const decl_ref = try mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);
831 // TODO look into avoiding the call to analyzeDeref here
832 return mod.analyzeDeref(scope, inst.base.src, decl_ref, inst.base.src);
909833}
910834
911835fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
......@@ -1032,9 +956,8 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError
1032956 .parent = null,
1033957 .inst_table = &inst_table,
1034958 .func = module_fn,
1035 // Note that we pass the caller's Decl, not the callee. This causes
1036 // compile errors to be attached (correctly) to the caller's Decl.
1037 .decl = scope.decl().?,
959 .owner_decl = scope.ownerDecl().?,
960 .src_decl = module_fn.owner_decl,
1038961 .instructions = .{},
1039962 .arena = scope.arena(),
1040963 .label = null,
......@@ -1069,7 +992,7 @@ fn analyzeInstFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!
1069992 .state = if (fn_inst.kw_args.is_inline) .inline_only else .queued,
1070993 .zir = fn_inst.positionals.body,
1071994 .body = undefined,
1072 .owner_decl = scope.decl().?,
995 .owner_decl = scope.ownerDecl().?,
1073996 };
1074997 return mod.constInst(scope, fn_inst.base.src, .{
1075998 .ty = fn_type,
......@@ -1391,7 +1314,7 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
13911314 return mod.analyzeDeclRef(scope, fieldptr.base.src, decl);
13921315 }
13931316
1394 if (&container_scope.file_scope.base == mod.root_scope) {
1317 if (container_scope.file_scope == mod.root_scope) {
13951318 return mod.fail(scope, fieldptr.base.src, "root source file has no member called '{s}'", .{field_name});
13961319 } else {
13971320 return mod.fail(scope, fieldptr.base.src, "container '{}' has no member called '{s}'", .{ child_type, field_name });
......@@ -1606,7 +1529,8 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In
16061529 .parent = parent_block,
16071530 .inst_table = parent_block.inst_table,
16081531 .func = parent_block.func,
1609 .decl = parent_block.decl,
1532 .owner_decl = parent_block.owner_decl,
1533 .src_decl = parent_block.src_decl,
16101534 .instructions = .{},
16111535 .arena = parent_block.arena,
16121536 .inlining = parent_block.inlining,
......@@ -2182,7 +2106,8 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
21822106 .parent = parent_block,
21832107 .inst_table = parent_block.inst_table,
21842108 .func = parent_block.func,
2185 .decl = parent_block.decl,
2109 .owner_decl = parent_block.owner_decl,
2110 .src_decl = parent_block.src_decl,
21862111 .instructions = .{},
21872112 .arena = parent_block.arena,
21882113 .inlining = parent_block.inlining,
......@@ -2196,7 +2121,8 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
21962121 .parent = parent_block,
21972122 .inst_table = parent_block.inst_table,
21982123 .func = parent_block.func,
2199 .decl = parent_block.decl,
2124 .owner_decl = parent_block.owner_decl,
2125 .src_decl = parent_block.src_decl,
22002126 .instructions = .{},
22012127 .arena = parent_block.arena,
22022128 .inlining = parent_block.inlining,
......@@ -2294,17 +2220,6 @@ fn analyzeBreak(
22942220 } else unreachable;
22952221}
22962222
2297fn analyzeDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Decl {
2298 const decl_name = inst.positionals.name;
2299 const zir_module = scope.namespace().cast(Scope.ZIRModule).?;
2300 const src_decl = zir_module.contents.module.findDecl(decl_name) orelse
2301 return mod.fail(scope, inst.base.src, "use of undeclared identifier '{s}'", .{decl_name});
2302
2303 const decl = try resolveCompleteZirDecl(mod, scope, src_decl.decl);
2304
2305 return decl;
2306}
2307
23082223fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*Inst {
23092224 const tracy = trace(@src());
23102225 defer tracy.end();
test/stage2/test.zig+42-20
......@@ -36,7 +36,7 @@ pub fn addCases(ctx: *TestContext) !void {
3636 {
3737 var case = ctx.exe("hello world with updates", linux_x64);
3838
39 case.addError("", &[_][]const u8{"no entry point found"});
39 case.addError("", &[_][]const u8{"error: no entry point found"});
4040
4141 // Incorrect return type
4242 case.addError(
......@@ -147,7 +147,7 @@ pub fn addCases(ctx: *TestContext) !void {
147147
148148 {
149149 var case = ctx.exe("hello world with updates", macosx_x64);
150 case.addError("", &[_][]const u8{"no entry point found"});
150 case.addError("", &[_][]const u8{"error: no entry point found"});
151151
152152 // Incorrect return type
153153 case.addError(
......@@ -1243,24 +1243,46 @@ pub fn addCases(ctx: *TestContext) !void {
12431243 \\}
12441244 , &[_][]const u8{":3:9: error: redefinition of 'testing'"});
12451245 }
1246 ctx.compileError("compileLog", linux_x64,
1247 \\export fn _start() noreturn {
1248 \\ const b = true;
1249 \\ var f: u32 = 1;
1250 \\ @compileLog(b, 20, f, x);
1251 \\ @compileLog(1000);
1252 \\ var bruh: usize = true;
1253 \\ unreachable;
1254 \\}
1255 \\fn x() void {}
1256 , &[_][]const u8{
1257 ":4:3: error: found compile log statement",
1258 ":5:3: error: found compile log statement",
1259 ":6:21: error: expected usize, found bool",
1260 });
1261 // TODO if this is here it invalidates the compile error checker:
1262 // "| true, 20, (runtime value), (function)"
1263 // "| 1000"
1246
1247 {
1248 // TODO make the test harness support checking the compile log output too
1249 var case = ctx.obj("@compileLog", linux_x64);
1250 // The other compile error prevents emission of a "found compile log" statement.
1251 case.addError(
1252 \\export fn _start() noreturn {
1253 \\ const b = true;
1254 \\ var f: u32 = 1;
1255 \\ @compileLog(b, 20, f, x);
1256 \\ @compileLog(1000);
1257 \\ var bruh: usize = true;
1258 \\ unreachable;
1259 \\}
1260 \\export fn other() void {
1261 \\ @compileLog(1234);
1262 \\}
1263 \\fn x() void {}
1264 , &[_][]const u8{
1265 ":6:23: error: expected usize, found bool",
1266 });
1267
1268 // Now only compile log statements remain. One per Decl.
1269 case.addError(
1270 \\export fn _start() noreturn {
1271 \\ const b = true;
1272 \\ var f: u32 = 1;
1273 \\ @compileLog(b, 20, f, x);
1274 \\ @compileLog(1000);
1275 \\ unreachable;
1276 \\}
1277 \\export fn other() void {
1278 \\ @compileLog(1234);
1279 \\}
1280 \\fn x() void {}
1281 , &[_][]const u8{
1282 ":11:8: error: found compile log statement",
1283 ":4:5: note: also here",
1284 });
1285 }
12641286
12651287 {
12661288 var case = ctx.obj("extern variable has no type", linux_x64);